mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-10 03:53:26 -08:00
[Server] Move deck folder writes into the database interface (#7833)
Setting a deck or folder public, creating a folder, and deleting a folder tree were SQL statements in the socket handler. Declare them on Server_DatabaseInterface with a DeckStorageResult so the caller can still tell a missing row from a failed write, implement them in Servatrice_DatabaseInterface with the same statements, and let the three folder commands ask the injected interface. Readiness probing keeps its previous ignore-the-result shape.
This commit is contained in:
parent
8c0e796b0d
commit
23781af1f0
5 changed files with 121 additions and 59 deletions
|
|
@ -195,6 +195,29 @@ public:
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/** @brief Outcome of a deck-storage write, so callers can map it to a response code. */
|
||||||
|
enum class DeckStorageResult
|
||||||
|
{
|
||||||
|
Ok,
|
||||||
|
NotFound,
|
||||||
|
Failed
|
||||||
|
};
|
||||||
|
virtual DeckStorageResult setDeckVisibility(int /* deckId */, int /* userId */, bool /* isPublic */)
|
||||||
|
{
|
||||||
|
return DeckStorageResult::Failed;
|
||||||
|
}
|
||||||
|
virtual DeckStorageResult setDeckFolderVisibility(int /* folderId */, int /* userId */, bool /* isPublic */)
|
||||||
|
{
|
||||||
|
return DeckStorageResult::Failed;
|
||||||
|
}
|
||||||
|
virtual DeckStorageResult createDeckFolder(int /* parentId */, int /* userId */, const QString & /* name */)
|
||||||
|
{
|
||||||
|
return DeckStorageResult::Failed;
|
||||||
|
}
|
||||||
|
/** @brief Delete a folder, its deck files, and every nested folder. */
|
||||||
|
virtual void deleteDeckFolder(int /* folderId */)
|
||||||
|
{
|
||||||
|
}
|
||||||
virtual bool removeForgotPassword(const QString & /* user */)
|
virtual bool removeForgotPassword(const QString & /* user */)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1023,6 +1023,81 @@ int Servatrice_DatabaseInterface::getDeckPathId(const QString &path, int userId)
|
||||||
return getDeckPathIdAt(0, path.split("/"), userId);
|
return getDeckPathIdAt(0, path.split("/"), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Servatrice_DatabaseInterface::DeckStorageResult
|
||||||
|
Servatrice_DatabaseInterface::setDeckVisibility(int deckId, int userId, bool isPublic)
|
||||||
|
{
|
||||||
|
QSqlQuery *query = prepareQuery("select 1 from {prefix}_decklist_files where id = :id and id_user = :id_user");
|
||||||
|
query->bindValue(":id", deckId);
|
||||||
|
query->bindValue(":id_user", userId);
|
||||||
|
execSqlQuery(query);
|
||||||
|
if (!query->next()) {
|
||||||
|
return DeckStorageResult::NotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
query = prepareQuery("update {prefix}_decklist_files set is_public = :is_public where id = :id "
|
||||||
|
"and id_user = :id_user");
|
||||||
|
query->bindValue(":is_public", isPublic ? 1 : 0);
|
||||||
|
query->bindValue(":id", deckId);
|
||||||
|
query->bindValue(":id_user", userId);
|
||||||
|
if (!execSqlQuery(query)) {
|
||||||
|
return DeckStorageResult::Failed;
|
||||||
|
}
|
||||||
|
return DeckStorageResult::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
Servatrice_DatabaseInterface::DeckStorageResult
|
||||||
|
Servatrice_DatabaseInterface::setDeckFolderVisibility(int folderId, int userId, bool isPublic)
|
||||||
|
{
|
||||||
|
QSqlQuery *query = prepareQuery(
|
||||||
|
"update {prefix}_decklist_folders set is_public = :is_public where id = :id and id_user = :id_user");
|
||||||
|
query->bindValue(":is_public", isPublic ? 1 : 0);
|
||||||
|
query->bindValue(":id", folderId);
|
||||||
|
query->bindValue(":id_user", userId);
|
||||||
|
if (!execSqlQuery(query)) {
|
||||||
|
return DeckStorageResult::Failed;
|
||||||
|
}
|
||||||
|
return DeckStorageResult::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
Servatrice_DatabaseInterface::DeckStorageResult
|
||||||
|
Servatrice_DatabaseInterface::createDeckFolder(int parentId, int userId, const QString &name)
|
||||||
|
{
|
||||||
|
QSqlQuery *query = prepareQuery(
|
||||||
|
"insert into {prefix}_decklist_folders (id_parent, id_user, name) values(:id_parent, :id_user, :name)");
|
||||||
|
query->bindValue(":id_parent", parentId);
|
||||||
|
query->bindValue(":id_user", userId);
|
||||||
|
query->bindValue(":name", name);
|
||||||
|
if (!execSqlQuery(query)) {
|
||||||
|
return DeckStorageResult::Failed;
|
||||||
|
}
|
||||||
|
return DeckStorageResult::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Servatrice_DatabaseInterface::deleteDeckFolderTree(int basePathId)
|
||||||
|
{
|
||||||
|
checkSql();
|
||||||
|
|
||||||
|
QSqlQuery *query = prepareQuery("select id from {prefix}_decklist_folders where id_parent = :id_parent");
|
||||||
|
query->bindValue(":id_parent", basePathId);
|
||||||
|
execSqlQuery(query);
|
||||||
|
while (query->next()) {
|
||||||
|
deleteDeckFolderTree(query->value(0).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
query = prepareQuery("delete from {prefix}_decklist_files where id_folder = :id_folder");
|
||||||
|
query->bindValue(":id_folder", basePathId);
|
||||||
|
execSqlQuery(query);
|
||||||
|
|
||||||
|
query = prepareQuery("delete from {prefix}_decklist_folders where id = :id");
|
||||||
|
query->bindValue(":id", basePathId);
|
||||||
|
execSqlQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Servatrice_DatabaseInterface::deleteDeckFolder(int folderId)
|
||||||
|
{
|
||||||
|
deleteDeckFolderTree(folderId);
|
||||||
|
}
|
||||||
|
|
||||||
int Servatrice_DatabaseInterface::getDeckOwnerId(int deckId)
|
int Servatrice_DatabaseInterface::getDeckOwnerId(int deckId)
|
||||||
{
|
{
|
||||||
QSqlQuery *query = prepareQuery("select id_user from {prefix}_decklist_files where id = :id");
|
QSqlQuery *query = prepareQuery("select id_user from {prefix}_decklist_files where id = :id");
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ private:
|
||||||
QString sealLegacyBackup(const QString &storedName, const QString &credential);
|
QString sealLegacyBackup(const QString &storedName, const QString &credential);
|
||||||
bool isStrictModeEnabled(bool &ok) const;
|
bool isStrictModeEnabled(bool &ok) const;
|
||||||
int getDeckPathIdAt(int basePathId, QStringList path, int userId);
|
int getDeckPathIdAt(int basePathId, QStringList path, int userId);
|
||||||
|
void deleteDeckFolderTree(int basePathId);
|
||||||
bool addToList(const QString &table, int userId, int targetId);
|
bool addToList(const QString &table, int userId, int targetId);
|
||||||
bool removeFromList(const QString &table, int userId, int targetId);
|
bool removeFromList(const QString &table, int userId, int targetId);
|
||||||
|
|
||||||
|
|
@ -124,6 +125,10 @@ public:
|
||||||
int getDeckPathId(const QString &path, int userId) override;
|
int getDeckPathId(const QString &path, int userId) override;
|
||||||
int getDeckOwnerId(int deckId) override;
|
int getDeckOwnerId(int deckId) override;
|
||||||
bool isDeckEffectivelyPublic(int deckId) override;
|
bool isDeckEffectivelyPublic(int deckId) override;
|
||||||
|
DeckStorageResult setDeckVisibility(int deckId, int userId, bool isPublic) override;
|
||||||
|
DeckStorageResult setDeckFolderVisibility(int folderId, int userId, bool isPublic) override;
|
||||||
|
DeckStorageResult createDeckFolder(int parentId, int userId, const QString &name) override;
|
||||||
|
void deleteDeckFolder(int folderId) override;
|
||||||
QMap<QString, ServerInfo_User> getBuddyList(const QString &name) override;
|
QMap<QString, ServerInfo_User> getBuddyList(const QString &name) override;
|
||||||
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) override;
|
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) override;
|
||||||
bool isInBuddyList(const QString &whoseList, const QString &who) override;
|
bool isInBuddyList(const QString &whoseList, const QString &who) override;
|
||||||
|
|
|
||||||
|
|
@ -762,46 +762,30 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckSetVisibility(const
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlInterface->checkSql();
|
databaseInterface->checkSql();
|
||||||
|
|
||||||
|
Server_DatabaseInterface::DeckStorageResult result;
|
||||||
if (cmd.has_deck_id()) {
|
if (cmd.has_deck_id()) {
|
||||||
QSqlQuery *query =
|
result = databaseInterface->setDeckVisibility(cmd.deck_id(), userInfo->id(), cmd.is_public());
|
||||||
sqlInterface->prepareQuery("select 1 from {prefix}_decklist_files where id = :id and id_user = :id_user");
|
|
||||||
query->bindValue(":id", cmd.deck_id());
|
|
||||||
query->bindValue(":id_user", userInfo->id());
|
|
||||||
sqlInterface->execSqlQuery(query);
|
|
||||||
if (!query->next()) {
|
|
||||||
return Response::RespNameNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
query = sqlInterface->prepareQuery("update {prefix}_decklist_files set is_public = :is_public where id = :id "
|
|
||||||
"and id_user = :id_user");
|
|
||||||
query->bindValue(":is_public", cmd.is_public() ? 1 : 0);
|
|
||||||
query->bindValue(":id", cmd.deck_id());
|
|
||||||
query->bindValue(":id_user", userInfo->id());
|
|
||||||
if (!sqlInterface->execSqlQuery(query)) {
|
|
||||||
return Response::RespContextError;
|
|
||||||
}
|
|
||||||
} else if (cmd.has_folder_path()) {
|
} else if (cmd.has_folder_path()) {
|
||||||
const int folderId = databaseInterface->getDeckPathId(nameFromStdString(cmd.folder_path()), userInfo->id());
|
const int folderId = databaseInterface->getDeckPathId(nameFromStdString(cmd.folder_path()), userInfo->id());
|
||||||
if (folderId == -1 || folderId == 0) {
|
if (folderId == -1 || folderId == 0) {
|
||||||
return Response::RespNameNotFound;
|
return Response::RespNameNotFound;
|
||||||
}
|
}
|
||||||
|
result = databaseInterface->setDeckFolderVisibility(folderId, userInfo->id(), cmd.is_public());
|
||||||
QSqlQuery *query =
|
|
||||||
sqlInterface->prepareQuery("update {prefix}_decklist_folders set is_public = :is_public where id = :id "
|
|
||||||
"and id_user = :id_user");
|
|
||||||
query->bindValue(":is_public", cmd.is_public() ? 1 : 0);
|
|
||||||
query->bindValue(":id", folderId);
|
|
||||||
query->bindValue(":id_user", userInfo->id());
|
|
||||||
if (!sqlInterface->execSqlQuery(query)) {
|
|
||||||
return Response::RespContextError;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Response::RespInvalidData;
|
return Response::RespInvalidData;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response::RespOk;
|
switch (result) {
|
||||||
|
case Server_DatabaseInterface::DeckStorageResult::Ok:
|
||||||
|
return Response::RespOk;
|
||||||
|
case Server_DatabaseInterface::DeckStorageResult::NotFound:
|
||||||
|
return Response::RespNameNotFound;
|
||||||
|
case Server_DatabaseInterface::DeckStorageResult::Failed:
|
||||||
|
return Response::RespContextError;
|
||||||
|
}
|
||||||
|
return Response::RespContextError;
|
||||||
}
|
}
|
||||||
|
|
||||||
Response::ResponseCode AbstractServerSocketInterface::cmdDeckDownloadPublic(const Command_DeckDownloadPublic &cmd,
|
Response::ResponseCode AbstractServerSocketInterface::cmdDeckDownloadPublic(const Command_DeckDownloadPublic &cmd,
|
||||||
|
|
@ -841,7 +825,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckNewDir(const Comman
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlInterface->checkSql();
|
databaseInterface->checkSql();
|
||||||
|
|
||||||
QString path = nameFromStdString(cmd.path());
|
QString path = nameFromStdString(cmd.path());
|
||||||
int folderId = databaseInterface->getDeckPathId(path, userInfo->id());
|
int folderId = databaseInterface->getDeckPathId(path, userInfo->id());
|
||||||
|
|
@ -854,37 +838,13 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckNewDir(const Comman
|
||||||
return Response::RespContextError; // do not allow creation of paths that would be too long to delete
|
return Response::RespContextError; // do not allow creation of paths that would be too long to delete
|
||||||
}
|
}
|
||||||
|
|
||||||
QSqlQuery *query = sqlInterface->prepareQuery(
|
if (databaseInterface->createDeckFolder(folderId, userInfo->id(), name) !=
|
||||||
"insert into {prefix}_decklist_folders (id_parent, id_user, name) values(:id_parent, :id_user, :name)");
|
Server_DatabaseInterface::DeckStorageResult::Ok) {
|
||||||
query->bindValue(":id_parent", folderId);
|
|
||||||
query->bindValue(":id_user", userInfo->id());
|
|
||||||
query->bindValue(":name", name);
|
|
||||||
if (!sqlInterface->execSqlQuery(query)) {
|
|
||||||
return Response::RespContextError;
|
return Response::RespContextError;
|
||||||
}
|
}
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractServerSocketInterface::deckDelDirHelper(int basePathId)
|
|
||||||
{
|
|
||||||
sqlInterface->checkSql();
|
|
||||||
QSqlQuery *query =
|
|
||||||
sqlInterface->prepareQuery("select id from {prefix}_decklist_folders where id_parent = :id_parent");
|
|
||||||
query->bindValue(":id_parent", basePathId);
|
|
||||||
sqlInterface->execSqlQuery(query);
|
|
||||||
while (query->next()) {
|
|
||||||
deckDelDirHelper(query->value(0).toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
query = sqlInterface->prepareQuery("delete from {prefix}_decklist_files where id_folder = :id_folder");
|
|
||||||
query->bindValue(":id_folder", basePathId);
|
|
||||||
sqlInterface->execSqlQuery(query);
|
|
||||||
|
|
||||||
query = sqlInterface->prepareQuery("delete from {prefix}_decklist_folders where id = :id");
|
|
||||||
query->bindValue(":id", basePathId);
|
|
||||||
sqlInterface->execSqlQuery(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractServerSocketInterface::sendServerMessage(const QString userName, const QString message)
|
void AbstractServerSocketInterface::sendServerMessage(const QString userName, const QString message)
|
||||||
{
|
{
|
||||||
AbstractServerSocketInterface *user =
|
AbstractServerSocketInterface *user =
|
||||||
|
|
@ -909,13 +869,13 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckDelDir(const Comman
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlInterface->checkSql();
|
databaseInterface->checkSql();
|
||||||
|
|
||||||
int basePathId = databaseInterface->getDeckPathId(nameFromStdString(cmd.path()), userInfo->id());
|
int basePathId = databaseInterface->getDeckPathId(nameFromStdString(cmd.path()), userInfo->id());
|
||||||
if ((basePathId == -1) || (basePathId == 0)) {
|
if ((basePathId == -1) || (basePathId == 0)) {
|
||||||
return Response::RespNameNotFound;
|
return Response::RespNameNotFound;
|
||||||
}
|
}
|
||||||
deckDelDirHelper(basePathId);
|
databaseInterface->deleteDeckFolder(basePathId);
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,6 @@ private:
|
||||||
Response::ResponseCode cmdDeckListOtherUser(const Command_DeckListOtherUser &cmd, ResponseContainer &rc);
|
Response::ResponseCode cmdDeckListOtherUser(const Command_DeckListOtherUser &cmd, ResponseContainer &rc);
|
||||||
Response::ResponseCode cmdDeckSetVisibility(const Command_DeckSetVisibility &cmd, ResponseContainer &rc);
|
Response::ResponseCode cmdDeckSetVisibility(const Command_DeckSetVisibility &cmd, ResponseContainer &rc);
|
||||||
Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc);
|
Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc);
|
||||||
void deckDelDirHelper(int basePathId);
|
|
||||||
void sendServerMessage(const QString userName, const QString message);
|
void sendServerMessage(const QString userName, const QString message);
|
||||||
Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc);
|
Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc);
|
||||||
Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc);
|
Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue