mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-11 12:33:25 -08:00
[Server] Serve account self-service updates through the database interface
cmdAccountEdit assembled a dynamic UPDATE for the real name, email and country columns in the socket handler, and cmdAccountImage wrote the avatar blob there too. Add AccountUpdateRecord, updateUserAccount and setUserAvatar to Server_DatabaseInterface with fail-closed defaults, implement them with the previous query text and bind values, and keep the password gate, the email permission check, the empty-edit early return and the in-memory userInfo updates in the handler.
This commit is contained in:
parent
4b5408aad1
commit
d36b18c76e
4 changed files with 75 additions and 30 deletions
|
|
@ -774,6 +774,24 @@ public:
|
||||||
virtual void setForcePasswordChange(const QString & /* user */, bool /* force */)
|
virtual void setForcePasswordChange(const QString & /* user */, bool /* force */)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
/** @brief The account fields a self-service edit may change; unset fields are left alone. */
|
||||||
|
struct AccountUpdateRecord
|
||||||
|
{
|
||||||
|
bool hasRealName = false;
|
||||||
|
QString realName;
|
||||||
|
bool hasEmail = false;
|
||||||
|
QString email;
|
||||||
|
bool hasCountry = false;
|
||||||
|
QString country;
|
||||||
|
};
|
||||||
|
virtual bool updateUserAccount(const QString & /* userName */, const AccountUpdateRecord & /* update */)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool setUserAvatar(int /* userId */, const QByteArray & /* image */)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/** @brief Outcome of reading or writing one account field. */
|
/** @brief Outcome of reading or writing one account field. */
|
||||||
enum class UserFieldResult
|
enum class UserFieldResult
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2244,6 +2244,51 @@ void Servatrice_DatabaseInterface::setForcePasswordChange(const QString &user, b
|
||||||
execSqlQuery(query);
|
execSqlQuery(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Servatrice_DatabaseInterface::updateUserAccount(const QString &userName, const AccountUpdateRecord &update)
|
||||||
|
{
|
||||||
|
if (!checkSql()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList queryList;
|
||||||
|
if (update.hasRealName) {
|
||||||
|
queryList << "realname=:realName";
|
||||||
|
}
|
||||||
|
if (update.hasEmail) {
|
||||||
|
queryList << "email=:email";
|
||||||
|
}
|
||||||
|
if (update.hasCountry) {
|
||||||
|
queryList << "country=:country";
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString queryText = QString("update {prefix}_users set %1 where name=:userName").arg(queryList.join(", "));
|
||||||
|
QSqlQuery *query = prepareQuery(queryText);
|
||||||
|
if (update.hasRealName) {
|
||||||
|
query->bindValue(":realName", update.realName);
|
||||||
|
}
|
||||||
|
if (update.hasEmail) {
|
||||||
|
query->bindValue(":email", update.email);
|
||||||
|
}
|
||||||
|
if (update.hasCountry) {
|
||||||
|
query->bindValue(":country", update.country);
|
||||||
|
}
|
||||||
|
query->bindValue(":userName", userName);
|
||||||
|
|
||||||
|
return execSqlQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Servatrice_DatabaseInterface::setUserAvatar(int userId, const QByteArray &image)
|
||||||
|
{
|
||||||
|
if (!checkSql()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery *query = prepareQuery("update {prefix}_users set avatar_bmp=:image where id=:id");
|
||||||
|
query->bindValue(":image", image);
|
||||||
|
query->bindValue(":id", userId);
|
||||||
|
return execSqlQuery(query);
|
||||||
|
}
|
||||||
|
|
||||||
bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user,
|
bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user,
|
||||||
const QString &oldPassword,
|
const QString &oldPassword,
|
||||||
bool oldPasswordNeedsHash,
|
bool oldPasswordNeedsHash,
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,8 @@ public:
|
||||||
const QString &newPassword,
|
const QString &newPassword,
|
||||||
bool newPasswordNeedsHash) override;
|
bool newPasswordNeedsHash) override;
|
||||||
void setForcePasswordChange(const QString &user, bool force) override;
|
void setForcePasswordChange(const QString &user, bool force) override;
|
||||||
|
bool updateUserAccount(const QString &userName, const AccountUpdateRecord &update) override;
|
||||||
|
bool setUserAvatar(int userId, const QByteArray &image) override;
|
||||||
QList<ServerInfo_Ban> getUserBanHistory(const QString &userName) override;
|
QList<ServerInfo_Ban> getUserBanHistory(const QString &userName) override;
|
||||||
bool addWarning(const QString userName,
|
bool addWarning(const QString userName,
|
||||||
const QString adminName,
|
const QString adminName,
|
||||||
|
|
|
||||||
|
|
@ -2903,43 +2903,26 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountEdit(const Comma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList queryList({});
|
Server_DatabaseInterface::AccountUpdateRecord update;
|
||||||
if (cmd.has_real_name()) {
|
update.hasRealName = cmd.has_real_name();
|
||||||
queryList << "realname=:realName";
|
update.realName = realName;
|
||||||
}
|
update.hasCountry = cmd.has_country();
|
||||||
|
update.country = country;
|
||||||
if (cmd.has_email()) {
|
if (cmd.has_email()) {
|
||||||
// a real password is required in order to change the email address
|
// a real password is required in order to change the email address
|
||||||
if (usingRealPassword || checkedPassword) {
|
if (usingRealPassword || checkedPassword) {
|
||||||
queryList << "email=:email";
|
update.hasEmail = true;
|
||||||
|
update.email = parsedEmailAddress;
|
||||||
} else {
|
} else {
|
||||||
return Response::RespFunctionNotAllowed;
|
return Response::RespFunctionNotAllowed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cmd.has_country()) {
|
|
||||||
queryList << "country=:country";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryList.isEmpty()) {
|
if (!update.hasRealName && !update.hasEmail && !update.hasCountry) {
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString queryText = QString("update {prefix}_users set %1 where name=:userName").arg(queryList.join(", "));
|
if (!databaseInterface->updateUserAccount(userName, update)) {
|
||||||
QSqlQuery *query = sqlInterface->prepareQuery(queryText);
|
|
||||||
if (cmd.has_real_name()) {
|
|
||||||
auto _realName = nameFromStdString(cmd.real_name());
|
|
||||||
query->bindValue(":realName", _realName);
|
|
||||||
}
|
|
||||||
if (cmd.has_email()) {
|
|
||||||
const auto _parsedEmailAddress = EmailParser::getParsedEmailAddress(nameFromStdString(cmd.email()));
|
|
||||||
query->bindValue(":email", _parsedEmailAddress);
|
|
||||||
}
|
|
||||||
if (cmd.has_country()) {
|
|
||||||
auto _country = nameFromStdString(cmd.country());
|
|
||||||
query->bindValue(":country", _country);
|
|
||||||
}
|
|
||||||
query->bindValue(":userName", userName);
|
|
||||||
|
|
||||||
if (!sqlInterface->execSqlQuery(query)) {
|
|
||||||
return Response::RespInternalError;
|
return Response::RespInternalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2967,10 +2950,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdAccountImage(const Comm
|
||||||
QByteArray image(cmd.image().c_str(), length);
|
QByteArray image(cmd.image().c_str(), length);
|
||||||
int id = userInfo->id();
|
int id = userInfo->id();
|
||||||
|
|
||||||
QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_users set avatar_bmp=:image where id=:id");
|
if (!databaseInterface->setUserAvatar(id, image)) {
|
||||||
query->bindValue(":image", image);
|
|
||||||
query->bindValue(":id", id);
|
|
||||||
if (!sqlInterface->execSqlQuery(query)) {
|
|
||||||
return Response::RespInternalError;
|
return Response::RespInternalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue