diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 99f2e62e..f20c61ce 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -11,7 +11,10 @@ SET(cockatrice_SOURCES src/dlg_filter_games.cpp src/dlg_connect.cpp src/dlg_create_token.cpp + src/dlg_edit_avatar.cpp + src/dlg_edit_password.cpp src/dlg_edit_tokens.cpp + src/dlg_edit_user.cpp src/dlg_register.cpp src/abstractclient.cpp src/remoteclient.cpp diff --git a/cockatrice/src/dlg_edit_avatar.cpp b/cockatrice/src/dlg_edit_avatar.cpp new file mode 100644 index 00000000..89d3e5fe --- /dev/null +++ b/cockatrice/src/dlg_edit_avatar.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dlg_edit_avatar.h" + +DlgEditAvatar::DlgEditAvatar(QWidget *parent) + : QDialog(parent) +{ + imageLabel = new QLabel(tr("No image chosen.")); + imageLabel->setFixedSize(400, 200); + imageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + imageLabel->setStyleSheet("border: 1px solid #000"); + + textLabel = new QLabel(tr("To change your avatar, choose a new image.\nTo remove your current avatar, just confirm without choosing a new image.")); + browseButton = new QPushButton(tr("Browse...")); + connect(browseButton, SIGNAL(clicked()), this, SLOT(actBrowse())); + + QGridLayout *grid = new QGridLayout; + grid->addWidget(imageLabel, 0, 0, 1, 2); + grid->addWidget(textLabel, 1, 0); + grid->addWidget(browseButton, 1, 1); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(actCancel())); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(grid); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + setWindowTitle(tr("Change avatar")); + setFixedHeight(sizeHint().height()); + setMinimumWidth(300); +} + +void DlgEditAvatar::actOk() +{ + accept(); +} + +void DlgEditAvatar::actCancel() +{ + reject(); +} + +void DlgEditAvatar::actBrowse() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), QDir::homePath(), tr("Image Files (*.png *.jpg *.bmp)")); + if(fileName.isEmpty()) + { + imageLabel->setText(tr("No image chosen.")); + return; + } + + QImage image; + QImageReader imgReader; + imgReader.setDecideFormatFromContent(true); + imgReader.setFileName(fileName); + if(!imgReader.read(&image)) + { + imageLabel->setText(tr("Invalid image chosen.")); + return; + } + imageLabel->setPixmap(QPixmap::fromImage(image).scaled(400, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation)); +} + +QByteArray DlgEditAvatar::getImage() +{ + const QPixmap *pix = imageLabel->pixmap(); + if(!pix || pix->isNull()) + return QByteArray(); + + QImage image = pix->toImage(); + if(image.isNull()) + return QByteArray(); + + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "JPG"); + return ba; +} diff --git a/cockatrice/src/dlg_edit_avatar.h b/cockatrice/src/dlg_edit_avatar.h new file mode 100644 index 00000000..0c34f0bb --- /dev/null +++ b/cockatrice/src/dlg_edit_avatar.h @@ -0,0 +1,26 @@ +#ifndef DLG_EDITAVATAR_H +#define DLG_EDITAVATAR_H + +#include +#include +#include + +class QLabel; +class QPushButton; +class QCheckBox; + +class DlgEditAvatar : public QDialog { + Q_OBJECT +public: + DlgEditAvatar(QWidget *parent = 0); + QByteArray getImage(); +private slots: + void actOk(); + void actCancel(); + void actBrowse(); +private: + QLabel *textLabel, *imageLabel; + QPushButton *browseButton; +}; + +#endif diff --git a/cockatrice/src/dlg_edit_password.cpp b/cockatrice/src/dlg_edit_password.cpp new file mode 100644 index 00000000..e6992f0a --- /dev/null +++ b/cockatrice/src/dlg_edit_password.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +#include "dlg_edit_password.h" + +DlgEditPassword::DlgEditPassword(QWidget *parent) + : QDialog(parent) +{ + QSettings settings; + settings.beginGroup("server"); + + oldPasswordLabel = new QLabel(tr("Old password:")); + oldPasswordEdit = new QLineEdit(settings.value("password").toString()); + oldPasswordLabel->setBuddy(oldPasswordEdit); + oldPasswordEdit->setEchoMode(QLineEdit::Password); + + newPasswordLabel = new QLabel(tr("New password:")); + newPasswordEdit = new QLineEdit(); + newPasswordLabel->setBuddy(newPasswordLabel); + newPasswordEdit->setEchoMode(QLineEdit::Password); + + QGridLayout *grid = new QGridLayout; + grid->addWidget(oldPasswordLabel, 0, 0); + grid->addWidget(oldPasswordEdit, 0, 1); + grid->addWidget(newPasswordLabel, 1, 0); + grid->addWidget(newPasswordEdit, 1, 1); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(actCancel())); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(grid); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + setWindowTitle(tr("Change password")); + setFixedHeight(sizeHint().height()); + setMinimumWidth(300); +} + +void DlgEditPassword::actOk() +{ + QSettings settings; + settings.beginGroup("server"); + // always save the password so it will be picked up by the connect dialog + settings.setValue("password", newPasswordEdit->text()); + settings.endGroup(); + + accept(); +} + +void DlgEditPassword::actCancel() +{ + reject(); +} diff --git a/cockatrice/src/dlg_edit_password.h b/cockatrice/src/dlg_edit_password.h new file mode 100644 index 00000000..9a2e6ec0 --- /dev/null +++ b/cockatrice/src/dlg_edit_password.h @@ -0,0 +1,26 @@ +#ifndef DLG_EDITPASSWORD_H +#define DLG_EDITPASSWORD_H + +#include +#include +#include + +class QLabel; +class QPushButton; +class QCheckBox; + +class DlgEditPassword : public QDialog { + Q_OBJECT +public: + DlgEditPassword(QWidget *parent = 0); + QString getOldPassword() const { return oldPasswordEdit->text(); } + QString getNewPassword() const { return newPasswordEdit->text(); } +private slots: + void actOk(); + void actCancel(); +private: + QLabel *oldPasswordLabel, *newPasswordLabel; + QLineEdit *oldPasswordEdit, *newPasswordEdit; +}; + +#endif diff --git a/cockatrice/src/dlg_edit_user.cpp b/cockatrice/src/dlg_edit_user.cpp new file mode 100644 index 00000000..74b2d4fd --- /dev/null +++ b/cockatrice/src/dlg_edit_user.cpp @@ -0,0 +1,326 @@ +#include +#include +#include +#include +#include +#include + +#include "dlg_edit_user.h" + +DlgEditUser::DlgEditUser(QWidget *parent, QString email, int gender, QString country, QString realName) + : QDialog(parent) +{ + emailLabel = new QLabel(tr("Email:")); + emailEdit = new QLineEdit(); + emailLabel->setBuddy(emailEdit); + emailEdit->setText(email); + + genderLabel = new QLabel(tr("Gender:")); + genderEdit = new QComboBox(); + genderLabel->setBuddy(genderEdit); + genderEdit->insertItem(0, QIcon(":/resources/genders/unknown.svg"), tr("Undefined")); + genderEdit->insertItem(1, QIcon(":/resources/genders/male.svg"), tr("Male")); + genderEdit->insertItem(2, QIcon(":/resources/genders/female.svg"), tr("Female")); + genderEdit->setCurrentIndex(gender + 1); + + countryLabel = new QLabel(tr("Country:")); + countryEdit = new QComboBox(); + countryLabel->setBuddy(countryEdit); + countryEdit->insertItem(0, tr("Undefined")); + countryEdit->addItem(QPixmap(":/resources/countries/ad.svg"), "ad"); + countryEdit->addItem(QIcon(":/resources/countries/ae.svg"), "ae"); + countryEdit->addItem(QIcon(":/resources/countries/af.svg"), "af"); + countryEdit->addItem(QIcon(":/resources/countries/ag.svg"), "ag"); + countryEdit->addItem(QIcon(":/resources/countries/ai.svg"), "ai"); + countryEdit->addItem(QIcon(":/resources/countries/al.svg"), "al"); + countryEdit->addItem(QIcon(":/resources/countries/am.svg"), "am"); + countryEdit->addItem(QIcon(":/resources/countries/ao.svg"), "ao"); + countryEdit->addItem(QIcon(":/resources/countries/aq.svg"), "aq"); + countryEdit->addItem(QIcon(":/resources/countries/ar.svg"), "ar"); + countryEdit->addItem(QIcon(":/resources/countries/as.svg"), "as"); + countryEdit->addItem(QIcon(":/resources/countries/at.svg"), "at"); + countryEdit->addItem(QIcon(":/resources/countries/au.svg"), "au"); + countryEdit->addItem(QIcon(":/resources/countries/aw.svg"), "aw"); + countryEdit->addItem(QIcon(":/resources/countries/ax.svg"), "ax"); + countryEdit->addItem(QIcon(":/resources/countries/az.svg"), "az"); + countryEdit->addItem(QIcon(":/resources/countries/ba.svg"), "ba"); + countryEdit->addItem(QIcon(":/resources/countries/bb.svg"), "bb"); + countryEdit->addItem(QIcon(":/resources/countries/bd.svg"), "bd"); + countryEdit->addItem(QIcon(":/resources/countries/be.svg"), "be"); + countryEdit->addItem(QIcon(":/resources/countries/bf.svg"), "bf"); + countryEdit->addItem(QIcon(":/resources/countries/bg.svg"), "bg"); + countryEdit->addItem(QIcon(":/resources/countries/bh.svg"), "bh"); + countryEdit->addItem(QIcon(":/resources/countries/bi.svg"), "bi"); + countryEdit->addItem(QIcon(":/resources/countries/bj.svg"), "bj"); + countryEdit->addItem(QIcon(":/resources/countries/bl.svg"), "bl"); + countryEdit->addItem(QIcon(":/resources/countries/bm.svg"), "bm"); + countryEdit->addItem(QIcon(":/resources/countries/bn.svg"), "bn"); + countryEdit->addItem(QIcon(":/resources/countries/bo.svg"), "bo"); + countryEdit->addItem(QIcon(":/resources/countries/bq.svg"), "bq"); + countryEdit->addItem(QIcon(":/resources/countries/br.svg"), "br"); + countryEdit->addItem(QIcon(":/resources/countries/bs.svg"), "bs"); + countryEdit->addItem(QIcon(":/resources/countries/bt.svg"), "bt"); + countryEdit->addItem(QIcon(":/resources/countries/bv.svg"), "bv"); + countryEdit->addItem(QIcon(":/resources/countries/bw.svg"), "bw"); + countryEdit->addItem(QIcon(":/resources/countries/by.svg"), "by"); + countryEdit->addItem(QIcon(":/resources/countries/bz.svg"), "bz"); + countryEdit->addItem(QIcon(":/resources/countries/ca.svg"), "ca"); + countryEdit->addItem(QIcon(":/resources/countries/cc.svg"), "cc"); + countryEdit->addItem(QIcon(":/resources/countries/cd.svg"), "cd"); + countryEdit->addItem(QIcon(":/resources/countries/cf.svg"), "cf"); + countryEdit->addItem(QIcon(":/resources/countries/cg.svg"), "cg"); + countryEdit->addItem(QIcon(":/resources/countries/ch.svg"), "ch"); + countryEdit->addItem(QIcon(":/resources/countries/ci.svg"), "ci"); + countryEdit->addItem(QIcon(":/resources/countries/ck.svg"), "ck"); + countryEdit->addItem(QIcon(":/resources/countries/cl.svg"), "cl"); + countryEdit->addItem(QIcon(":/resources/countries/cm.svg"), "cm"); + countryEdit->addItem(QIcon(":/resources/countries/cn.svg"), "cn"); + countryEdit->addItem(QIcon(":/resources/countries/co.svg"), "co"); + countryEdit->addItem(QIcon(":/resources/countries/cr.svg"), "cr"); + countryEdit->addItem(QIcon(":/resources/countries/cu.svg"), "cu"); + countryEdit->addItem(QIcon(":/resources/countries/cv.svg"), "cv"); + countryEdit->addItem(QIcon(":/resources/countries/cw.svg"), "cw"); + countryEdit->addItem(QIcon(":/resources/countries/cx.svg"), "cx"); + countryEdit->addItem(QIcon(":/resources/countries/cy.svg"), "cy"); + countryEdit->addItem(QIcon(":/resources/countries/cz.svg"), "cz"); + countryEdit->addItem(QIcon(":/resources/countries/de.svg"), "de"); + countryEdit->addItem(QIcon(":/resources/countries/dj.svg"), "dj"); + countryEdit->addItem(QIcon(":/resources/countries/dk.svg"), "dk"); + countryEdit->addItem(QIcon(":/resources/countries/dm.svg"), "dm"); + countryEdit->addItem(QIcon(":/resources/countries/do.svg"), "do"); + countryEdit->addItem(QIcon(":/resources/countries/dz.svg"), "dz"); + countryEdit->addItem(QIcon(":/resources/countries/ec.svg"), "ec"); + countryEdit->addItem(QIcon(":/resources/countries/ee.svg"), "ee"); + countryEdit->addItem(QIcon(":/resources/countries/eg.svg"), "eg"); + countryEdit->addItem(QIcon(":/resources/countries/eh.svg"), "eh"); + countryEdit->addItem(QIcon(":/resources/countries/er.svg"), "er"); + countryEdit->addItem(QIcon(":/resources/countries/es.svg"), "es"); + countryEdit->addItem(QIcon(":/resources/countries/et.svg"), "et"); + countryEdit->addItem(QIcon(":/resources/countries/fi.svg"), "fi"); + countryEdit->addItem(QIcon(":/resources/countries/fj.svg"), "fj"); + countryEdit->addItem(QIcon(":/resources/countries/fk.svg"), "fk"); + countryEdit->addItem(QIcon(":/resources/countries/fm.svg"), "fm"); + countryEdit->addItem(QIcon(":/resources/countries/fo.svg"), "fo"); + countryEdit->addItem(QIcon(":/resources/countries/fr.svg"), "fr"); + countryEdit->addItem(QIcon(":/resources/countries/ga.svg"), "ga"); + countryEdit->addItem(QIcon(":/resources/countries/gb.svg"), "gb"); + countryEdit->addItem(QIcon(":/resources/countries/gd.svg"), "gd"); + countryEdit->addItem(QIcon(":/resources/countries/ge.svg"), "ge"); + countryEdit->addItem(QIcon(":/resources/countries/gf.svg"), "gf"); + countryEdit->addItem(QIcon(":/resources/countries/gg.svg"), "gg"); + countryEdit->addItem(QIcon(":/resources/countries/gh.svg"), "gh"); + countryEdit->addItem(QIcon(":/resources/countries/gi.svg"), "gi"); + countryEdit->addItem(QIcon(":/resources/countries/gl.svg"), "gl"); + countryEdit->addItem(QIcon(":/resources/countries/gm.svg"), "gm"); + countryEdit->addItem(QIcon(":/resources/countries/gn.svg"), "gn"); + countryEdit->addItem(QIcon(":/resources/countries/gp.svg"), "gp"); + countryEdit->addItem(QIcon(":/resources/countries/gq.svg"), "gq"); + countryEdit->addItem(QIcon(":/resources/countries/gr.svg"), "gr"); + countryEdit->addItem(QIcon(":/resources/countries/gs.svg"), "gs"); + countryEdit->addItem(QIcon(":/resources/countries/gt.svg"), "gt"); + countryEdit->addItem(QIcon(":/resources/countries/gu.svg"), "gu"); + countryEdit->addItem(QIcon(":/resources/countries/gw.svg"), "gw"); + countryEdit->addItem(QIcon(":/resources/countries/gy.svg"), "gy"); + countryEdit->addItem(QIcon(":/resources/countries/hk.svg"), "hk"); + countryEdit->addItem(QIcon(":/resources/countries/hm.svg"), "hm"); + countryEdit->addItem(QIcon(":/resources/countries/hn.svg"), "hn"); + countryEdit->addItem(QIcon(":/resources/countries/hr.svg"), "hr"); + countryEdit->addItem(QIcon(":/resources/countries/ht.svg"), "ht"); + countryEdit->addItem(QIcon(":/resources/countries/hu.svg"), "hu"); + countryEdit->addItem(QIcon(":/resources/countries/id.svg"), "id"); + countryEdit->addItem(QIcon(":/resources/countries/ie.svg"), "ie"); + countryEdit->addItem(QIcon(":/resources/countries/il.svg"), "il"); + countryEdit->addItem(QIcon(":/resources/countries/im.svg"), "im"); + countryEdit->addItem(QIcon(":/resources/countries/in.svg"), "in"); + countryEdit->addItem(QIcon(":/resources/countries/io.svg"), "io"); + countryEdit->addItem(QIcon(":/resources/countries/iq.svg"), "iq"); + countryEdit->addItem(QIcon(":/resources/countries/ir.svg"), "ir"); + countryEdit->addItem(QIcon(":/resources/countries/is.svg"), "is"); + countryEdit->addItem(QIcon(":/resources/countries/it.svg"), "it"); + countryEdit->addItem(QIcon(":/resources/countries/je.svg"), "je"); + countryEdit->addItem(QIcon(":/resources/countries/jm.svg"), "jm"); + countryEdit->addItem(QIcon(":/resources/countries/jo.svg"), "jo"); + countryEdit->addItem(QIcon(":/resources/countries/jp.svg"), "jp"); + countryEdit->addItem(QIcon(":/resources/countries/ke.svg"), "ke"); + countryEdit->addItem(QIcon(":/resources/countries/kg.svg"), "kg"); + countryEdit->addItem(QIcon(":/resources/countries/kh.svg"), "kh"); + countryEdit->addItem(QIcon(":/resources/countries/ki.svg"), "ki"); + countryEdit->addItem(QIcon(":/resources/countries/km.svg"), "km"); + countryEdit->addItem(QIcon(":/resources/countries/kn.svg"), "kn"); + countryEdit->addItem(QIcon(":/resources/countries/kp.svg"), "kp"); + countryEdit->addItem(QIcon(":/resources/countries/kr.svg"), "kr"); + countryEdit->addItem(QIcon(":/resources/countries/kw.svg"), "kw"); + countryEdit->addItem(QIcon(":/resources/countries/ky.svg"), "ky"); + countryEdit->addItem(QIcon(":/resources/countries/kz.svg"), "kz"); + countryEdit->addItem(QIcon(":/resources/countries/la.svg"), "la"); + countryEdit->addItem(QIcon(":/resources/countries/lb.svg"), "lb"); + countryEdit->addItem(QIcon(":/resources/countries/lc.svg"), "lc"); + countryEdit->addItem(QIcon(":/resources/countries/li.svg"), "li"); + countryEdit->addItem(QIcon(":/resources/countries/lk.svg"), "lk"); + countryEdit->addItem(QIcon(":/resources/countries/lr.svg"), "lr"); + countryEdit->addItem(QIcon(":/resources/countries/ls.svg"), "ls"); + countryEdit->addItem(QIcon(":/resources/countries/lt.svg"), "lt"); + countryEdit->addItem(QIcon(":/resources/countries/lu.svg"), "lu"); + countryEdit->addItem(QIcon(":/resources/countries/lv.svg"), "lv"); + countryEdit->addItem(QIcon(":/resources/countries/ly.svg"), "ly"); + countryEdit->addItem(QIcon(":/resources/countries/ma.svg"), "ma"); + countryEdit->addItem(QIcon(":/resources/countries/mc.svg"), "mc"); + countryEdit->addItem(QIcon(":/resources/countries/md.svg"), "md"); + countryEdit->addItem(QIcon(":/resources/countries/me.svg"), "me"); + countryEdit->addItem(QIcon(":/resources/countries/mf.svg"), "mf"); + countryEdit->addItem(QIcon(":/resources/countries/mg.svg"), "mg"); + countryEdit->addItem(QIcon(":/resources/countries/mh.svg"), "mh"); + countryEdit->addItem(QIcon(":/resources/countries/mk.svg"), "mk"); + countryEdit->addItem(QIcon(":/resources/countries/ml.svg"), "ml"); + countryEdit->addItem(QIcon(":/resources/countries/mm.svg"), "mm"); + countryEdit->addItem(QIcon(":/resources/countries/mn.svg"), "mn"); + countryEdit->addItem(QIcon(":/resources/countries/mo.svg"), "mo"); + countryEdit->addItem(QIcon(":/resources/countries/mp.svg"), "mp"); + countryEdit->addItem(QIcon(":/resources/countries/mq.svg"), "mq"); + countryEdit->addItem(QIcon(":/resources/countries/mr.svg"), "mr"); + countryEdit->addItem(QIcon(":/resources/countries/ms.svg"), "ms"); + countryEdit->addItem(QIcon(":/resources/countries/mt.svg"), "mt"); + countryEdit->addItem(QIcon(":/resources/countries/mu.svg"), "mu"); + countryEdit->addItem(QIcon(":/resources/countries/mv.svg"), "mv"); + countryEdit->addItem(QIcon(":/resources/countries/mw.svg"), "mw"); + countryEdit->addItem(QIcon(":/resources/countries/mx.svg"), "mx"); + countryEdit->addItem(QIcon(":/resources/countries/my.svg"), "my"); + countryEdit->addItem(QIcon(":/resources/countries/mz.svg"), "mz"); + countryEdit->addItem(QIcon(":/resources/countries/na.svg"), "na"); + countryEdit->addItem(QIcon(":/resources/countries/nc.svg"), "nc"); + countryEdit->addItem(QIcon(":/resources/countries/ne.svg"), "ne"); + countryEdit->addItem(QIcon(":/resources/countries/nf.svg"), "nf"); + countryEdit->addItem(QIcon(":/resources/countries/ng.svg"), "ng"); + countryEdit->addItem(QIcon(":/resources/countries/ni.svg"), "ni"); + countryEdit->addItem(QIcon(":/resources/countries/nl.svg"), "nl"); + countryEdit->addItem(QIcon(":/resources/countries/no.svg"), "no"); + countryEdit->addItem(QIcon(":/resources/countries/np.svg"), "np"); + countryEdit->addItem(QIcon(":/resources/countries/nr.svg"), "nr"); + countryEdit->addItem(QIcon(":/resources/countries/nu.svg"), "nu"); + countryEdit->addItem(QIcon(":/resources/countries/nz.svg"), "nz"); + countryEdit->addItem(QIcon(":/resources/countries/om.svg"), "om"); + countryEdit->addItem(QIcon(":/resources/countries/pa.svg"), "pa"); + countryEdit->addItem(QIcon(":/resources/countries/pe.svg"), "pe"); + countryEdit->addItem(QIcon(":/resources/countries/pf.svg"), "pf"); + countryEdit->addItem(QIcon(":/resources/countries/pg.svg"), "pg"); + countryEdit->addItem(QIcon(":/resources/countries/ph.svg"), "ph"); + countryEdit->addItem(QIcon(":/resources/countries/pk.svg"), "pk"); + countryEdit->addItem(QIcon(":/resources/countries/pl.svg"), "pl"); + countryEdit->addItem(QIcon(":/resources/countries/pm.svg"), "pm"); + countryEdit->addItem(QIcon(":/resources/countries/pn.svg"), "pn"); + countryEdit->addItem(QIcon(":/resources/countries/pr.svg"), "pr"); + countryEdit->addItem(QIcon(":/resources/countries/ps.svg"), "ps"); + countryEdit->addItem(QIcon(":/resources/countries/pt.svg"), "pt"); + countryEdit->addItem(QIcon(":/resources/countries/pw.svg"), "pw"); + countryEdit->addItem(QIcon(":/resources/countries/py.svg"), "py"); + countryEdit->addItem(QIcon(":/resources/countries/qa.svg"), "qa"); + countryEdit->addItem(QIcon(":/resources/countries/re.svg"), "re"); + countryEdit->addItem(QIcon(":/resources/countries/ro.svg"), "ro"); + countryEdit->addItem(QIcon(":/resources/countries/rs.svg"), "rs"); + countryEdit->addItem(QIcon(":/resources/countries/ru.svg"), "ru"); + countryEdit->addItem(QIcon(":/resources/countries/rw.svg"), "rw"); + countryEdit->addItem(QIcon(":/resources/countries/sa.svg"), "sa"); + countryEdit->addItem(QIcon(":/resources/countries/sb.svg"), "sb"); + countryEdit->addItem(QIcon(":/resources/countries/sc.svg"), "sc"); + countryEdit->addItem(QIcon(":/resources/countries/sd.svg"), "sd"); + countryEdit->addItem(QIcon(":/resources/countries/se.svg"), "se"); + countryEdit->addItem(QIcon(":/resources/countries/sg.svg"), "sg"); + countryEdit->addItem(QIcon(":/resources/countries/sh.svg"), "sh"); + countryEdit->addItem(QIcon(":/resources/countries/si.svg"), "si"); + countryEdit->addItem(QIcon(":/resources/countries/sj.svg"), "sj"); + countryEdit->addItem(QIcon(":/resources/countries/sk.svg"), "sk"); + countryEdit->addItem(QIcon(":/resources/countries/sl.svg"), "sl"); + countryEdit->addItem(QIcon(":/resources/countries/sm.svg"), "sm"); + countryEdit->addItem(QIcon(":/resources/countries/sn.svg"), "sn"); + countryEdit->addItem(QIcon(":/resources/countries/so.svg"), "so"); + countryEdit->addItem(QIcon(":/resources/countries/sr.svg"), "sr"); + countryEdit->addItem(QIcon(":/resources/countries/ss.svg"), "ss"); + countryEdit->addItem(QIcon(":/resources/countries/st.svg"), "st"); + countryEdit->addItem(QIcon(":/resources/countries/sv.svg"), "sv"); + countryEdit->addItem(QIcon(":/resources/countries/sx.svg"), "sx"); + countryEdit->addItem(QIcon(":/resources/countries/sy.svg"), "sy"); + countryEdit->addItem(QIcon(":/resources/countries/sz.svg"), "sz"); + countryEdit->addItem(QIcon(":/resources/countries/tc.svg"), "tc"); + countryEdit->addItem(QIcon(":/resources/countries/td.svg"), "td"); + countryEdit->addItem(QIcon(":/resources/countries/tf.svg"), "tf"); + countryEdit->addItem(QIcon(":/resources/countries/tg.svg"), "tg"); + countryEdit->addItem(QIcon(":/resources/countries/th.svg"), "th"); + countryEdit->addItem(QIcon(":/resources/countries/tj.svg"), "tj"); + countryEdit->addItem(QIcon(":/resources/countries/tk.svg"), "tk"); + countryEdit->addItem(QIcon(":/resources/countries/tl.svg"), "tl"); + countryEdit->addItem(QIcon(":/resources/countries/tm.svg"), "tm"); + countryEdit->addItem(QIcon(":/resources/countries/tn.svg"), "tn"); + countryEdit->addItem(QIcon(":/resources/countries/to.svg"), "to"); + countryEdit->addItem(QIcon(":/resources/countries/tr.svg"), "tr"); + countryEdit->addItem(QIcon(":/resources/countries/tt.svg"), "tt"); + countryEdit->addItem(QIcon(":/resources/countries/tv.svg"), "tv"); + countryEdit->addItem(QIcon(":/resources/countries/tw.svg"), "tw"); + countryEdit->addItem(QIcon(":/resources/countries/tz.svg"), "tz"); + countryEdit->addItem(QIcon(":/resources/countries/ua.svg"), "ua"); + countryEdit->addItem(QIcon(":/resources/countries/ug.svg"), "ug"); + countryEdit->addItem(QIcon(":/resources/countries/um.svg"), "um"); + countryEdit->addItem(QIcon(":/resources/countries/us.svg"), "us"); + countryEdit->addItem(QIcon(":/resources/countries/uy.svg"), "uy"); + countryEdit->addItem(QIcon(":/resources/countries/uz.svg"), "uz"); + countryEdit->addItem(QIcon(":/resources/countries/va.svg"), "va"); + countryEdit->addItem(QIcon(":/resources/countries/vc.svg"), "vc"); + countryEdit->addItem(QIcon(":/resources/countries/ve.svg"), "ve"); + countryEdit->addItem(QIcon(":/resources/countries/vg.svg"), "vg"); + countryEdit->addItem(QIcon(":/resources/countries/vi.svg"), "vi"); + countryEdit->addItem(QIcon(":/resources/countries/vn.svg"), "vn"); + countryEdit->addItem(QIcon(":/resources/countries/vu.svg"), "vu"); + countryEdit->addItem(QIcon(":/resources/countries/wf.svg"), "wf"); + countryEdit->addItem(QIcon(":/resources/countries/ws.svg"), "ws"); + countryEdit->addItem(QIcon(":/resources/countries/ye.svg"), "ye"); + countryEdit->addItem(QIcon(":/resources/countries/yt.svg"), "yt"); + countryEdit->addItem(QIcon(":/resources/countries/za.svg"), "za"); + countryEdit->addItem(QIcon(":/resources/countries/zm.svg"), "zm"); + countryEdit->addItem(QIcon(":/resources/countries/zw.svg"), "zw"); + countryEdit->setCurrentIndex(0); + for(int i = 0; i < countryEdit->count(); ++i) + { + if(countryEdit->itemText(i) == country) + { + countryEdit->setCurrentIndex(i); + break; + } + } + + realnameLabel = new QLabel(tr("Real name:")); + realnameEdit = new QLineEdit(); + realnameLabel->setBuddy(realnameEdit); + realnameEdit->setText(realName); + + QGridLayout *grid = new QGridLayout; + grid->addWidget(emailLabel, 0, 0); + grid->addWidget(emailEdit, 0, 1); + grid->addWidget(genderLabel, 1, 0); + grid->addWidget(genderEdit, 1, 1); + grid->addWidget(countryLabel, 2, 0); + grid->addWidget(countryEdit, 2, 1); + grid->addWidget(realnameLabel, 3, 0); + grid->addWidget(realnameEdit, 3, 1); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(actCancel())); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(grid); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + setWindowTitle(tr("Edit user informations")); + setFixedHeight(sizeHint().height()); + setMinimumWidth(300); +} + +void DlgEditUser::actOk() +{ + accept(); +} + +void DlgEditUser::actCancel() +{ + reject(); +} diff --git a/cockatrice/src/dlg_edit_user.h b/cockatrice/src/dlg_edit_user.h new file mode 100644 index 00000000..f7044973 --- /dev/null +++ b/cockatrice/src/dlg_edit_user.h @@ -0,0 +1,29 @@ +#ifndef DLG_EDITUSER_H +#define DLG_EDITUSER_H + +#include +#include +#include + +class QLabel; +class QPushButton; +class QCheckBox; + +class DlgEditUser : public QDialog { + Q_OBJECT +public: + DlgEditUser(QWidget *parent = 0, QString email = QString(), int gender = -1, QString country = QString(), QString realName = QString()); + QString getEmail() const { return emailEdit->text(); } + int getGender() const { return genderEdit->currentIndex() - 1; } + QString getCountry() const { return genderEdit->currentIndex() == 0 ? "" : countryEdit->currentText(); } + QString getRealName() const { return realnameEdit->text(); } +private slots: + void actOk(); + void actCancel(); +private: + QLabel *emailLabel, *genderLabel, *countryLabel, *realnameLabel; + QLineEdit *emailEdit, *realnameEdit; + QComboBox *genderEdit, *countryEdit; +}; + +#endif diff --git a/cockatrice/src/playerlistwidget.cpp b/cockatrice/src/playerlistwidget.cpp index e3897533..6aac922d 100644 --- a/cockatrice/src/playerlistwidget.cpp +++ b/cockatrice/src/playerlistwidget.cpp @@ -6,7 +6,6 @@ #include "tab_supervisor.h" #include "tab_userlists.h" #include "userlist.h" -#include "userinfobox.h" #include "user_context_menu.h" #include #include diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index 12820686..2da72776 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -12,7 +12,6 @@ #include "tab_server.h" #include "abstractclient.h" #include "userlist.h" -#include "userinfobox.h" #include #include "pending_command.h" diff --git a/cockatrice/src/tab_userlists.cpp b/cockatrice/src/tab_userlists.cpp index 61fe693c..7cd3fec7 100644 --- a/cockatrice/src/tab_userlists.cpp +++ b/cockatrice/src/tab_userlists.cpp @@ -21,7 +21,7 @@ TabUserLists::TabUserLists(TabSupervisor *_tabSupervisor, AbstractClient *_clien allUsersList = new UserList(_tabSupervisor, client, UserList::AllUsersList); buddyList = new UserList(_tabSupervisor, client, UserList::BuddyList); ignoreList = new UserList(_tabSupervisor, client, UserList::IgnoreList); - userInfoBox = new UserInfoBox(client, false); + userInfoBox = new UserInfoBox(client, true); userInfoBox->updateInfo(userInfo); connect(allUsersList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); diff --git a/cockatrice/src/user_context_menu.cpp b/cockatrice/src/user_context_menu.cpp index ad3372d1..ace5a44b 100644 --- a/cockatrice/src/user_context_menu.cpp +++ b/cockatrice/src/user_context_menu.cpp @@ -145,7 +145,7 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName QAction *actionClicked = menu->exec(pos); if (actionClicked == aDetails) { - UserInfoBox *infoWidget = new UserInfoBox(client, true, static_cast(parent()), Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); + UserInfoBox *infoWidget = new UserInfoBox(client, false, static_cast(parent()), Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint); infoWidget->setAttribute(Qt::WA_DeleteOnClose); infoWidget->updateInfo(userName); } else if (actionClicked == aChat) diff --git a/cockatrice/src/userinfobox.cpp b/cockatrice/src/userinfobox.cpp index 9edd0c22..6b87d8c4 100644 --- a/cockatrice/src/userinfobox.cpp +++ b/cockatrice/src/userinfobox.cpp @@ -1,10 +1,15 @@ #include "userinfobox.h" #include "pixmapgenerator.h" #include "abstractclient.h" +#include "dlg_edit_user.h" +#include "dlg_edit_password.h" +#include "dlg_edit_avatar.h" + #include #include #include - +#include +#include #include "pending_command.h" #include "pb/session_commands.pb.h" @@ -14,8 +19,8 @@ const qint64 SIXTY = 60; const qint64 HOURS_IN_A_DAY = 24; const qint64 DAYS_IN_A_YEAR = 365; -UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *parent, Qt::WindowFlags flags) - : QWidget(parent, flags), client(_client), fullInfo(_fullInfo) +UserInfoBox::UserInfoBox(AbstractClient *_client, bool _editable, QWidget *parent, Qt::WindowFlags flags) + : QWidget(parent, flags), client(_client), editable(_editable) { QFont nameFont = nameLabel.font(); nameFont.setBold(true); @@ -41,6 +46,19 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren mainLayout->addWidget(&accountAgeLebel1, 6, 0, 1, 1); mainLayout->addWidget(&accountAgeLabel2, 6, 2, 1, 1); mainLayout->setColumnStretch(2, 10); + + if(editable) + { + QHBoxLayout * buttonsLayout = new QHBoxLayout; + buttonsLayout->addWidget(&editButton); + buttonsLayout->addWidget(&passwordButton); + buttonsLayout->addWidget(&avatarButton); + mainLayout->addLayout(buttonsLayout, 7, 0, 1, 3); + + connect(&editButton, SIGNAL(clicked()), this, SLOT(actEdit())); + connect(&passwordButton, SIGNAL(clicked()), this, SLOT(actPassword())); + connect(&avatarButton, SIGNAL(clicked()), this, SLOT(actAvatar())); + } setWindowTitle(tr("User information")); setLayout(mainLayout); @@ -54,6 +72,10 @@ void UserInfoBox::retranslateUi() countryLabel1.setText(tr("Location:")); userLevelLabel1.setText(tr("User level:")); accountAgeLebel1.setText(tr("Account Age:")); + + editButton.setText(tr("Edit")); + passwordButton.setText(tr("Change password")); + avatarButton.setText(tr("Change avatar")); } void UserInfoBox::updateInfo(const ServerInfo_User &user) @@ -140,3 +162,126 @@ void UserInfoBox::processResponse(const Response &r) setFixedSize(sizeHint()); show(); } + +void UserInfoBox::actEdit() +{ + Command_GetUserInfo cmd; + + PendingCommand *pend = client->prepareSessionCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(actEditInternal(const Response &))); + + client->sendCommand(pend); +} + +void UserInfoBox::actEditInternal(const Response &r) +{ + const Response_GetUserInfo &response = r.GetExtension(Response_GetUserInfo::ext); + const ServerInfo_User &user = response.user_info(); + + QString email = QString::fromStdString(user.email()); + int gender = user.gender(); + QString country = QString::fromStdString(user.country()); + QString realName = QString::fromStdString(user.real_name()); + + DlgEditUser dlg(this, email, gender, country, realName); + if(!dlg.exec()) + return; + + Command_AccountEdit cmd; + cmd.set_real_name(dlg.getRealName().toStdString()); + cmd.set_email(dlg.getEmail().toStdString()); + cmd.set_gender((ServerInfo_User_Gender) dlg.getGender()); + cmd.set_country(dlg.getCountry().toStdString()); + + PendingCommand *pend = client->prepareSessionCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(processEditResponse(const Response &))); + + client->sendCommand(pend); +} + +void UserInfoBox::actPassword() +{ + DlgEditPassword dlg(this); + if(!dlg.exec()) + return; + + Command_AccountPassword cmd; + cmd.set_old_password(dlg.getOldPassword().toStdString()); + cmd.set_new_password(dlg.getNewPassword().toStdString()); + + PendingCommand *pend = client->prepareSessionCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(processPasswordResponse(const Response &))); + + client->sendCommand(pend); +} + +void UserInfoBox::actAvatar() +{ + DlgEditAvatar dlg(this); + if(!dlg.exec()) + return; + + Command_AccountImage cmd; + cmd.set_image(dlg.getImage().data(), dlg.getImage().size()); + + PendingCommand *pend = client->prepareSessionCommand(cmd); + connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(processAvatarResponse(const Response &))); + + client->sendCommand(pend); +} + +void UserInfoBox::processEditResponse(const Response &r) +{ + switch (r.response_code()) { + case Response::RespOk: + updateInfo(nameLabel.text()); + QMessageBox::information(this, tr("Information"), tr("User information updated.")); + break; + case Response::RespFunctionNotAllowed: + QMessageBox::critical(this, tr("Error"), tr("This server does not permit you to update your user informations.")); + break; + case Response::RespInternalError: + default: + QMessageBox::critical(this, tr("Error"), tr("An error occured while trying to update your user informations.")); + break; + } +} + +void UserInfoBox::processPasswordResponse(const Response &r) +{ + switch (r.response_code()) { + case Response::RespOk: + QMessageBox::information(this, tr("Information"), tr("Password changed.")); + break; + case Response::RespFunctionNotAllowed: + QMessageBox::critical(this, tr("Error"), tr("This server does not permit you to change your password.")); + break; + case Response::RespPasswordTooShort: + QMessageBox::critical(this, tr("Error"), tr("The new password is too short.")); + break; + case Response::RespWrongPassword: + QMessageBox::critical(this, tr("Error"), tr("The old password is incorrect.")); + break; + case Response::RespInternalError: + default: + QMessageBox::critical(this, tr("Error"), tr("An error occured while trying to update your user informations.")); + break; + } +} + +void UserInfoBox::processAvatarResponse(const Response &r) +{ + switch (r.response_code()) { + case Response::RespOk: + updateInfo(nameLabel.text()); + QMessageBox::information(this, tr("Information"), tr("Avatar updated.")); + break; + case Response::RespFunctionNotAllowed: + QMessageBox::critical(this, tr("Error"), tr("This server does not permit you to update your avatar.")); + break; + case Response::RespInternalError: + default: + QMessageBox::critical(this, tr("Error"), tr("An error occured while trying to updater your avatar.")); + break; + } +} \ No newline at end of file diff --git a/cockatrice/src/userinfobox.h b/cockatrice/src/userinfobox.h index e144cd4c..43ae7034 100644 --- a/cockatrice/src/userinfobox.h +++ b/cockatrice/src/userinfobox.h @@ -3,8 +3,8 @@ #include #include +#include -class QLabel; class ServerInfo_User; class AbstractClient; class Response; @@ -13,14 +13,24 @@ class UserInfoBox : public QWidget { Q_OBJECT private: AbstractClient *client; - bool fullInfo; + bool editable; QLabel avatarLabel, nameLabel, realNameLabel1, realNameLabel2, genderLabel1, genderLabel2, countryLabel1, countryLabel2, countryLabel3, userLevelLabel1, userLevelLabel2, userLevelLabel3, accountAgeLebel1, accountAgeLabel2; + QPushButton editButton, passwordButton, avatarButton; + public: - UserInfoBox(AbstractClient *_client, bool fullInfo, QWidget *parent = 0, Qt::WindowFlags flags = 0); + UserInfoBox(AbstractClient *_client, bool editable, QWidget *parent = 0, Qt::WindowFlags flags = 0); void retranslateUi(); private slots: void processResponse(const Response &r); + void processEditResponse(const Response &r); + void processPasswordResponse(const Response &r); + void processAvatarResponse(const Response &r); + + void actEdit(); + void actEditInternal(const Response &r); + void actPassword(); + void actAvatar(); public slots: void updateInfo(const ServerInfo_User &user); void updateInfo(const QString &userName); diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index a4c7d7dc..6afbc610 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -3,7 +3,6 @@ #include "tab_supervisor.h" #include "abstractclient.h" #include "pixmapgenerator.h" -#include "userinfobox.h" #include "user_context_menu.h" #include "gameselector.h" #include diff --git a/common/pb/serverinfo_user.proto b/common/pb/serverinfo_user.proto index e7176e00..577acfbd 100644 --- a/common/pb/serverinfo_user.proto +++ b/common/pb/serverinfo_user.proto @@ -22,4 +22,5 @@ message ServerInfo_User { optional sint32 server_id = 9 [default = -1]; optional uint64 session_id = 10; optional uint64 accountage_secs = 11; + optional string email = 12; } diff --git a/common/pb/session_commands.proto b/common/pb/session_commands.proto index 11e5ce6f..81907dba 100644 --- a/common/pb/session_commands.proto +++ b/common/pb/session_commands.proto @@ -20,6 +20,9 @@ message SessionCommand { JOIN_ROOM = 1015; REGISTER = 1016; ACTIVATE = 1017; + ACCOUNT_EDIT = 1018; + ACCOUNT_IMAGE = 1019; + ACCOUNT_PASSWORD = 1020; REPLAY_LIST = 1100; REPLAY_DOWNLOAD = 1101; REPLAY_MODIFY_MATCH = 1102; @@ -110,11 +113,11 @@ message Command_Register { required string password = 2; // Email address of the client for user validation optional string email = 3; - // Gender of the user - optional ServerInfo_User.Gender gender = 4; - // Country code of the user. 2 letter ISO format - optional string country = 5; - optional string real_name = 6; + // Gender of the user + optional ServerInfo_User.Gender gender = 4; + // Country code of the user. 2 letter ISO format + optional string country = 5; + optional string real_name = 6; } // User wants to activate an account @@ -127,3 +130,28 @@ message Command_Activate { // Activation token required string token = 2; } + +message Command_AccountEdit { + extend SessionCommand { + optional Command_AccountEdit ext = 1018; + } + optional string real_name = 1; + optional string email = 2; + optional ServerInfo_User.Gender gender = 3; + optional string country = 4; +} + +message Command_AccountImage { + extend SessionCommand { + optional Command_AccountImage ext = 1019; + } + optional bytes image = 1; +} + +message Command_AccountPassword { + extend SessionCommand { + optional Command_AccountPassword ext = 1020; + } + optional string old_password = 1; + optional string new_password = 2; +} \ No newline at end of file diff --git a/common/server_database_interface.h b/common/server_database_interface.h index 60d6c056..03232dbd 100644 --- a/common/server_database_interface.h +++ b/common/server_database_interface.h @@ -44,6 +44,8 @@ public: enum LogMessage_TargetType { MessageTargetRoom, MessageTargetGame, MessageTargetChat, MessageTargetIslRoom }; virtual void logMessage(const int /* senderId */, const QString & /* senderName */, const QString & /* senderIp */, const QString & /* logMessage */, LogMessage_TargetType /* targetType */, const int /* targetId */, const QString & /* targetName */) { }; bool checkUserIsBanned(Server_ProtocolHandler *session, QString &banReason, int &banSecondsRemaining); + virtual bool changeUserPassword(const QString & /* user */, const QString & /* oldPassword */, const QString & /* newPassword */) { return true; }; + virtual QChar getGenderChar(ServerInfo_User_Gender const &gender) { return QChar('u'); }; }; #endif diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index b48fb738..d8ba9589 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -476,6 +476,10 @@ ServerInfo_User Servatrice_DatabaseInterface::evalUserQueryResult(const QSqlQuer qint64 accountAgeInSeconds = regDate.secsTo(QDateTime::currentDateTime()); result.set_accountage_secs(accountAgeInSeconds); } + + const QString email = query->value(8).toString(); + if (!email.isEmpty()) + result.set_email(email.toStdString()); } return result; } @@ -490,7 +494,7 @@ ServerInfo_User Servatrice_DatabaseInterface::getUserData(const QString &name, b if (!checkSql()) return result; - QSqlQuery *query = prepareQuery("select id, name, admin, country, gender, realname, avatar_bmp, registrationDate from {prefix}_users where name = :name and active = 1"); + QSqlQuery *query = prepareQuery("select id, name, admin, country, gender, realname, avatar_bmp, registrationDate, email from {prefix}_users where name = :name and active = 1"); query->bindValue(":name", name); if (!execSqlQuery(query)) return result; @@ -761,4 +765,41 @@ void Servatrice_DatabaseInterface::logMessage(const int senderId, const QString query->bindValue(":target_id", (targetType == MessageTargetChat && targetId < 1) ? QVariant() : targetId); query->bindValue(":target_name", targetName); execSqlQuery(query); +} + +bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword) +{ + if(server->getAuthenticationMethod() != Servatrice::AuthenticationSql) + return true; + + if (!checkSql()) + return true; + + if (!usernameIsValid(user)) + return true; + + QSqlQuery *passwordQuery = prepareQuery("select password_sha512 from {prefix}_users where name = :name"); + passwordQuery->bindValue(":name", user); + if (!execSqlQuery(passwordQuery)) { + qDebug("Change password denied: SQL error"); + return true; + } + + if (!passwordQuery->next()) + return true; + + const QString correctPassword = passwordQuery->value(0).toString(); + if (correctPassword != PasswordHasher::computeHash(oldPassword, correctPassword.left(16))) + return true; + + QString passwordSha512 = PasswordHasher::computeHash(newPassword, PasswordHasher::generateRandomSalt()); + + passwordQuery = prepareQuery("update {prefix}_users set password_sha512=:password where name = :name"); + passwordQuery->bindValue(":password", passwordSha512); + passwordQuery->bindValue(":name", user); + if (!execSqlQuery(passwordQuery)) { + qDebug("Change password denied: SQL error"); + return true; + } + return false; } \ No newline at end of file diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index e5aae344..70c6f51b 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -25,7 +25,6 @@ private: bool checkUserIsIpBanned(const QString &ipAddress, QString &banReason, int &banSecondsRemaining); /** Must be called after checkSql and server is known to be in auth mode. */ bool checkUserIsNameBanned(QString const &userName, QString &banReason, int &banSecondsRemaining); - QChar getGenderChar(ServerInfo_User_Gender const &gender); protected: AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft); public slots: @@ -70,6 +69,8 @@ public: bool activateUser(const QString &userName, const QString &token); void logMessage(const int senderId, const QString &senderName, const QString &senderIp, const QString &logMessage, LogMessage_TargetType targetType, const int targetId, const QString &targetName); + bool changeUserPassword(const QString &user, const QString &oldPassword, const QString &newPassword); + QChar getGenderChar(ServerInfo_User_Gender const &gender); }; #endif diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index d781e3e4..b7f12269 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -272,6 +272,10 @@ Response::ResponseCode ServerSocketInterface::processExtendedSessionCommand(int case SessionCommand::REPLAY_DELETE_MATCH: return cmdReplayDeleteMatch(cmd.GetExtension(Command_ReplayDeleteMatch::ext), rc); case SessionCommand::REGISTER: return cmdRegisterAccount(cmd.GetExtension(Command_Register::ext), rc); break; case SessionCommand::ACTIVATE: return cmdActivateAccount(cmd.GetExtension(Command_Activate::ext), rc); break; + + case SessionCommand::ACCOUNT_EDIT: return cmdAccountEdit(cmd.GetExtension(Command_AccountEdit::ext), rc); + case SessionCommand::ACCOUNT_IMAGE: return cmdAccountImage(cmd.GetExtension(Command_AccountImage::ext), rc); + case SessionCommand::ACCOUNT_PASSWORD: return cmdAccountPassword(cmd.GetExtension(Command_AccountPassword::ext), rc); default: return Response::RespFunctionNotAllowed; } } @@ -948,6 +952,75 @@ Response::ResponseCode ServerSocketInterface::cmdActivateAccount(const Command_A } } +Response::ResponseCode ServerSocketInterface::cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer &rc) +{ + if (authState != PasswordRight) + return Response::RespFunctionNotAllowed; + + QString realName = QString::fromStdString(cmd.real_name()); + QString emailAddress = QString::fromStdString(cmd.email()); + ServerInfo_User_Gender gender = cmd.gender(); + QString country = QString::fromStdString(cmd.country()); + + QString userName = QString::fromStdString(userInfo->name()); + + + QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_users set realname=:realName, email=:email, gender=:gender, country=:country where name=:userName"); + query->bindValue(":realName", realName); + query->bindValue(":email", emailAddress); + query->bindValue(":gender", sqlInterface->getGenderChar(gender)); + query->bindValue(":country", country); + query->bindValue(":userName", userName); + if (!sqlInterface->execSqlQuery(query)) + return Response::RespInternalError; + + userInfo->set_real_name(cmd.real_name()); + userInfo->set_email(cmd.email()); + userInfo->set_gender(cmd.gender()); + userInfo->set_country(cmd.country()); + + return Response::RespOk; +} + +Response::ResponseCode ServerSocketInterface::cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer &rc) +{ + if (authState != PasswordRight) + return Response::RespFunctionNotAllowed; + + QByteArray image(cmd.image().c_str(), cmd.image().length()); + int id = userInfo->id(); + + QSqlQuery *query = sqlInterface->prepareQuery("update {prefix}_users set avatar_bmp=:image where id=:id"); + query->bindValue(":image", image); + query->bindValue(":id", id); + if (!sqlInterface->execSqlQuery(query)) + return Response::RespInternalError; + + userInfo->set_avatar_bmp(cmd.image().c_str(), cmd.image().length()); + return Response::RespOk; +} + +Response::ResponseCode ServerSocketInterface::cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer &rc) +{ + if (authState != PasswordRight) + return Response::RespFunctionNotAllowed; + + QString oldPassword = QString::fromStdString(cmd.old_password()); + QString newPassword = QString::fromStdString(cmd.new_password()); + + // TODO make this configurable? + if(newPassword.length() < 6) + return Response::RespPasswordTooShort; + + QString userName = QString::fromStdString(userInfo->name()); + + bool changeFailed = databaseInterface->changeUserPassword(userName, oldPassword, newPassword); + + if(changeFailed) + return Response::RespWrongPassword; + + return Response::RespOk; +} // ADMIN FUNCTIONS. // Permission is checked by the calling function. diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index b9471407..df20e118 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -49,6 +49,10 @@ class Command_UpdateServerMessage; class Command_ShutdownServer; class Command_ReloadConfig; +class Command_AccountEdit; +class Command_AccountImage; +class Command_AccountPassword; + class ServerSocketInterface : public Server_ProtocolHandler { Q_OBJECT @@ -101,6 +105,10 @@ private: Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc); Response::ResponseCode processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc); + Response::ResponseCode cmdAccountEdit(const Command_AccountEdit &cmd, ResponseContainer &rc); + Response::ResponseCode cmdAccountImage(const Command_AccountImage &cmd, ResponseContainer &rc); + Response::ResponseCode cmdAccountPassword(const Command_AccountPassword &cmd, ResponseContainer &rc); + bool sendActivationTokenMail(const QString &nickname, const QString &recipient, const QString &token); public: ServerSocketInterface(Servatrice *_server, Servatrice_DatabaseInterface *_databaseInterface, QObject *parent = 0);