add password change
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sat, 1 Mar 2008 16:53:35 +0000 (16:53 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Sat, 1 Mar 2008 16:53:35 +0000 (16:53 +0000)
git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@99 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

doc/prog_protocol.html
src/overview.cpp
src/overview.h
src/user.cpp
src/user.h
src/webrequest.cpp
src/webrequest.h
www/inc/machine/session.php
www/machine.php

index 1b7ca1a..b6f2e7b 100644 (file)
@@ -261,11 +261,13 @@ Both calls use this structure for the request:<p>
 
 <pre>
 &lt;Users>
-  &lt;User name="loginname">Description of User&lt;/User>
+  &lt;User name="loginname" passwd="initial password">Description of User&lt;/User>
   ...
 &lt;/Users>
 </pre>
 
+The passwd attribute is optional.<p>
+
 The <tt>adduser</tt> call also uses it for the response, leaving out any user name that already existed or does not conform to the syntax requirements.
 
 <h3>Deleting a User</h3>
@@ -276,6 +278,26 @@ FIXME: this call can fail silently if the user is still referenced somewhere. Th
 
 FIXME 2: currently this transaction is not atomic for a reason: if it fails to delete the user it will at least succeed in deleting its access rights.
 
+<h3>Changing a Users own Password</h3>
+
+The <tt>setmypasswd</tt> can be used to change the user of the current session. The request looks like:<p>
+
+<pre>
+&lt;SetMyPasswd oldpwd="old password" newpwd="new password"\>
+</pre>
+
+The response is empty. Only the status counts.
+
+<h3>Changing another Users Password</h3>
+
+The <tt>setpasswd</tt> can be used to change the user of the current session. The request looks like:<p>
+
+<pre>
+&lt;SetPasswd user="user name" newpwd="new password"\>
+</pre>
+
+The response is empty. Only the status counts.
+
 <h3>Getting User ACLs</h3>
 
 The <tt>getuseracl</tt> transaction returns the ACL of a specific user. The request contains only the login name of the user. The response looks like:<p>
index 1884745..f3da814 100644 (file)
@@ -45,6 +45,7 @@ MOverview::MOverview(MWebRequest*mw,QString pk)
        QMenu*m=mb->addMenu(tr("&Session"));
        m->addAction(tr("&Re-Login"),this,SLOT(relogin()));
        m->addAction(tr("&Offline mode"))->setEnabled(false);
+       m->addAction(tr("Change my &Password"),this,SLOT(setMyPassword())) ->setEnabled(req->hasRole("setmypasswd"));
        m->addSeparator();
        m->addAction(tr("&Close Session"),this,SLOT(close()));
        
@@ -85,7 +86,9 @@ MOverview::MOverview(MWebRequest*mw,QString pk)
        connect(p,SIGNAL(clicked()),this,SLOT(editEvent()));
        p->setEnabled(req->hasRole("geteventdata"));
        vl->addSpacing(15);
-       vl->addWidget(new QPushButton(tr("Order Ticket...")),0);
+       vl->addWidget(p=new QPushButton(tr("Order Ticket...")),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(eventOrderTicket()));
+       p->setEnabled(req->hasRole("createorder"));
        vl->addStretch(10);
        
        tab->addTab(carttab=new QWidget,tr("Shopping Cart"));
@@ -147,6 +150,9 @@ MOverview::MOverview(MWebRequest*mw,QString pk)
        vl->addWidget(p=new QPushButton(tr("Roles...")),0);
        connect(p,SIGNAL(clicked()),this,SLOT(editUserRoles()));
        p->setEnabled(req->hasRole("getuseracl"));
+       vl->addWidget(p=new QPushButton(tr("Set Password...")),0);
+       connect(p,SIGNAL(clicked()),this,SLOT(setUserPassword()));
+       p->setEnabled(req->hasRole("setpasswd"));
        vl->addStretch(10);
        
        //host tab
@@ -189,6 +195,10 @@ MOverview::MOverview(MWebRequest*mw,QString pk)
                eventtab->setEnabled(false);
                tab->setTabEnabled(tab->indexOf(eventtab),false);
        }
+       if(!req->hasRole("createorder")){
+               carttab->setEnabled(false);
+               tab->setTabEnabled(tab->indexOf(carttab),false);
+       }
        if(req->hasRole("getusers")){
                updateUsers();
        }else{
@@ -290,8 +300,10 @@ void MOverview::newUser()
                if(QMessageBox::warning(this,tr("Error"),tr("The user name must contain only letters, digits, and underscores and must be at least one character long!"),QMessageBox::Retry|QMessageBox::Abort)!=QMessageBox::Retry)
                        return;
        }
+       //get password
+       QString pwd=QInputDialog::getText(this,tr("Password"),tr("Please enter an initial password for the user:"),QLineEdit::Password);
        //send request
-       MUser(req,name).create();
+       MUser(req,name).create(pwd);
        //update display
        updateUsers();
 }
@@ -357,6 +369,34 @@ void MOverview::editUserHosts()
                usr.setHosts(cd.getCheckList());
 }
 
+void MOverview::setMyPassword()
+{
+       MPasswordChange pc(this);
+       if(pc.exec()==QDialog::Accepted){
+               QString e=req->changeMyPassword(pc.oldPassword(),pc.newPassword());
+               if(e!="")
+                       QMessageBox::warning(this,tr("Warning"),tr("Error setting password: %1").arg(e));
+       }
+}
+void MOverview::setUserPassword()
+{
+       //get selection
+       QModelIndex sel=usertable->currentIndex();
+       if(!sel.isValid())return;
+       //get uname
+       QString name=usermodel->data(usermodel->index(sel.row(),0)).toString();
+       //get new password
+       MPasswordChange pc(this,name);
+       if(pc.exec()!=QDialog::Accepted)return;
+       QString p=pc.newPassword();
+       if(p==""){
+               QMessageBox::warning(this,tr("Warning"),tr("The password must be non-empty and both lines must match"));
+               return;
+       }
+       //...
+       MUser usr(req,name);
+       usr.changePassword(p);
+}
 
 void MOverview::updateHosts()
 {
@@ -521,3 +561,56 @@ void MOverview::exportHost()
        fd.write(out.toAscii());
        fd.close();
 }
+
+
+void MOverview::eventOrderTicket()
+{
+}
+
+
+/**********************************************/
+
+MPasswordChange::MPasswordChange(QWidget*par,QString user)
+       :QDialog(par)
+{
+       oldpwd=newpwd1=newpwd2=0;
+       if(user=="")
+               setWindowTitle(tr("Change my password"));
+       else
+               setWindowTitle(tr("Reset password of user %1").arg(user));
+       QGridLayout*gl;
+       setLayout(gl=new QGridLayout);
+       if(user==""){
+               gl->addWidget(new QLabel(tr("Old Password:")),0,0);
+               gl->addWidget(oldpwd=new QLineEdit,0,1);
+               oldpwd->setEchoMode(QLineEdit::Password);
+       }
+       gl->addWidget(new QLabel(tr("New Password:")),1,0);
+       gl->addWidget(newpwd1=new QLineEdit,1,1);
+       newpwd1->setEchoMode(QLineEdit::Password);
+       gl->addWidget(new QLabel(tr("Repeat Password:")),2,0);
+       gl->addWidget(newpwd2=new QLineEdit,2,1);
+       newpwd2->setEchoMode(QLineEdit::Password);
+       
+       QHBoxLayout*hl;
+       gl->addLayout(hl=new QHBoxLayout,3,0,1,2);
+       hl->addStretch(10);
+       QPushButton*p;
+       hl->addWidget(p=new QPushButton(tr("Set Password")));
+       connect(p,SIGNAL(clicked()),this,SLOT(accept()));
+       hl->addWidget(p=new QPushButton(tr("Cancel")));
+       connect(p,SIGNAL(clicked()),this,SLOT(reject()));
+}
+
+QString MPasswordChange::oldPassword()
+{
+       if(oldpwd)return oldpwd->text();
+       return "";
+}
+
+QString MPasswordChange::newPassword()
+{
+       if(newpwd1==0 || newpwd2==0)return "";
+       if(newpwd1->text()!=newpwd2->text())return "";
+       return newpwd1->text();
+}
index 5f99fbc..b58f75b 100644 (file)
 
 #include <QMainWindow>
 #include <QPointer>
+#include <QDialog>
 
 class MWebRequest;
 class QTabWidget;
 class QTableView;
 class QStandardItemModel;
 class QPushButton;
+class QLineEdit;
 
 /**Main Overview Window*/
 class MOverview:public QMainWindow
@@ -43,6 +45,8 @@ class MOverview:public QMainWindow
                void editEvent();
                /**update list of events*/
                void updateEvents();
+               /**order ticket from event tab*/
+               void eventOrderTicket();
                
                /**update list of users*/
                void updateUsers();
@@ -56,6 +60,10 @@ class MOverview:public QMainWindow
                void editUserRoles();
                /**set users hosts*/
                void editUserHosts();
+               /**set my own password*/
+               void setMyPassword();
+               /**set a users password*/
+               void setUserPassword();
                
                /**update list of hosts*/
                void updateHosts();
@@ -85,4 +93,20 @@ class MOverview:public QMainWindow
                QPushButton*thishostbutton;
 };
 
+/**Helper dialog for changing passwords*/
+class MPasswordChange:public QDialog
+{
+       Q_OBJECT
+       public:
+               /**creates a password change dialog, if user is empty it is presumed to change own password*/
+               MPasswordChange(QWidget*parent,QString user=QString());
+               
+               /**if own password: return old password*/
+               QString oldPassword();
+               /**returns new password, or empty if the two lines don't match*/
+               QString newPassword();
+       private:
+               QLineEdit *oldpwd,*newpwd1,*newpwd2;
+};
+
 #endif
index f364241..327c14d 100644 (file)
@@ -57,7 +57,7 @@ bool MUser::isValid()
        return QRegExp("[A-Za-z0-9_]+").exactMatch(m_userid);
 }
 
-bool MUser::create()
+bool MUser::create(QString pwd)
 {
        //do not attempt to save invalid or incomplete data
        if(!isValid())return false;
@@ -66,6 +66,7 @@ bool MUser::create()
        QDomElement root=doc.createElement("Users");
        QDomElement el=doc.createElement("User");
        el.setAttribute("name",m_userid);
+       el.setAttribute("passwd",pwd);
        el.appendChild(doc.createTextNode(m_descr));
        root.appendChild(el);
        doc.appendChild(root);
@@ -80,6 +81,26 @@ bool MUser::create()
        }
 }
 
+bool MUser::changePassword(QString pwd)
+{
+       //do not attempt to save invalid or incomplete data
+       if(!isValid())return false;
+       //create XML
+       QDomDocument doc;
+       QDomElement el=doc.createElement("SetPasswd");
+       el.setAttribute("user",m_userid);
+       el.setAttribute("newpwd",pwd);
+       doc.appendChild(el);
+       //call
+       req->request("setpasswd",doc.toByteArray());
+       //check success
+       if(req->responseStatus()==MWebRequest::Ok){
+               return true;
+       }else{
+               return false;
+       }
+}
+
 void MUser::deleteUser()
 {
        if(!isValid())return;
index 8db084d..eb61f8f 100644 (file)
@@ -40,8 +40,8 @@ class MUser
                /**checks user name*/
                bool isValid();
                
-               /**creates user in database; returns true on success*/
-               bool create();
+               /**creates user in database with an initial password; returns true on success*/
+               bool create(QString pwd);
                
                /**deletes user from database*/
                void deleteUser();
@@ -61,6 +61,9 @@ class MUser
                /**send the updated host list of the user to the server; returns true on success*/
                bool setHosts(const MCheckList&);
                
+               /**change the password of this user; returns whether successful*/
+               bool changePassword(QString);
+               
        private:
                MWebRequest*req;
                QString m_userid,m_descr;
index b2e8b21..526f5ed 100644 (file)
@@ -271,6 +271,22 @@ bool MWebRequest::relogin()
        return doLogin();
 }
 
+QString MWebRequest::changeMyPassword(QString o,QString n)
+{
+       //check old
+       if(passwd!=o)return tr("Cannot change password, old password does not match!");
+       //create DOM tree
+       QDomDocument doc;
+       QDomElement el=doc.createElement("SetMyPasswd");
+       el.setAttribute("oldpwd",o);
+       el.setAttribute("newpwd",n);
+       doc.appendChild(el);
+       //request
+       request("setmypasswd",doc.toByteArray());
+       if(responseStatus()==MWebRequest::Ok)return "";
+       else return tr(rspdata.data());
+}
+
 QString MWebRequest::errorString()
 {
        return errstr;
index 5d9a237..ef3f60d 100644 (file)
@@ -97,6 +97,8 @@ class MWebRequest:public QObject
                bool relogin();
                /**log out of web server*/
                void logout();
+               /**change password; returns error string if it fails, empty if it succeeds*/
+               QString changeMyPassword(QString oldpwd,QString newpwd);
                
        private slots:
                /**internal: used by wait loop for web requests*/
index 8a3b4f9..32c563b 100644 (file)
@@ -195,6 +195,50 @@ class Session
                echo $tout;
        }
        
+       /**set my own password*/
+       public function setMyPasswd($txt)
+       {
+               //check whether I really can do that
+               if(!$this->isAuthenticated()){
+                       header("X-MagicSmoke-Status: Unauthenticated");
+                       die("Not authenticated. Can't change password.");
+               }
+               //parse XML
+               $dom=new DOMDocument;
+               if(!$dom->loadXML($txt)){
+                       header("X-MagicSmoke-Status: SyntaxError");
+                       die("unable to parse XML data");
+               }
+               $nl=$dom->getElementsByTagName("SetMyPasswd");
+               if($nl->length!=1){
+                       header("X-MagicSmoke-Status: SyntaxError");
+                       die("expected exactly one passwd element");
+               }
+               $spw=$nl->item(0);
+               $old=$spw->getAttribute("oldpwd");
+               $nwp=$spw->getAttribute("newpwd");
+               //sanity check
+               if($nwp==""){
+                       header("X-MagicSmoke-Status: SyntaxError");
+                       die("cannot set an empty password");
+               }
+               //check old password
+               global $db;
+               $res=$db->select("users","passwd","uname=".$db->escapeString($this->user));
+               if(count($res)!=1){
+                       header("X-MagicSmoke-Status: Error");
+                       die("Ooops. Unable to find user. You have been deleted.");
+               }
+               if($old!=$res[0]["passwd"]){
+                       header("X-MagicSmoke-Status: Error");
+                       deleteSession();
+                       die("Wrong password. Session hijacked, terminating it.");
+               }
+               //set new password
+               $db->update("users",array("passwd"=>$nwp),"uname=".$db->escapeString($this->user));
+               header("X-MagicSmoke-Status: Ok");
+       }
+       
        /**checks whether user can execute this transaction, returns true on success; it always returns true for admins*/
        public function canExecute($transaction)
        {
@@ -411,6 +455,7 @@ function parseUserXml($txt)
        foreach($xml->getElementsByTagName("User") as $el){
                $usr["name"]=$el->getAttribute("name");
                $usr["descr"]="";
+               $usr["passwd"]=$el->getAttribute("passwd");
                foreach($el->childNodes as $cn)
                        if($cn->nodeType==XML_TEXT_NODE)
                                $usr["descr"]=$cn->wholeText;
@@ -445,7 +490,7 @@ function addUserXml($txt)
                $res=$db->select("users","uname","uname='".$usr[$i]["name"]."'");
                if(count($res)==0){
                        //create new
-                       $db->insert("users",array("uname"=>$usr[$i]["name"],"description"=>$usr[$i]["descr"]));
+                       $db->insert("users",array("uname"=>$usr[$i]["name"],"description"=>$usr[$i]["descr"],"passwd"=>$usr[$i]["passwd"]));
                        //print data
                        $udm=$dom->createElement("User",$usr[$i]["descr"]);
                        $udm->setAttributeNode(new DOMAttr("name",$usr[$i]["name"]));
@@ -475,4 +520,35 @@ function deleteUserXml($txt)
        header("X-MagicSmoke-Status: Ok");
 }
 
+//set another users passwd
+function setPasswdXml($txt)
+{
+       global $db;
+       //parse XML
+       $dom=new DOMDocument;
+       if(!$dom->loadXML($txt)){
+               header("X-MagicSmoke-Status: SyntaxError");
+               die("unable to parse XML data");
+       }
+       $nl=$dom->getElementsByTagName("SetPasswd");
+       if($nl->length!=1){
+               header("X-MagicSmoke-Status: SyntaxError");
+               die("expected exactly one passwd element");
+       }
+       $spw=$nl->item(0);
+       $usr=$spw->getAttribute("user");
+       $nwp=$spw->getAttribute("newpwd");
+       //sanity check
+       if($nwp==""){
+               header("X-MagicSmoke-Status: SyntaxError");
+               die("cannot set an empty password");
+       }
+       //set new password
+       if($db->update("users",array("passwd"=>$nwp),"uname=".$db->escapeString($usr))===false){
+               header("X-MagicSmoke-Status: Error");
+               die("Unable to change this password.");
+       }else
+               header("X-MagicSmoke-Status: Ok");
+}
+
 ?>
\ No newline at end of file
index 835e419..b52adc3 100644 (file)
@@ -18,7 +18,7 @@ $ALLOWEDREQUESTS=array(
        //all requests below here need authentication
        tr("getmyroles"), //role management: get my own ACLs
        //all requests below here need a role entry in the DB
-       tr("getusers"),tr("setuserdescription"),tr("getuseracl"),tr("setuseracl"),tr("getuserhosts"),tr("setuserhosts"),tr("adduser"),tr("deleteuser"),//user management
+       tr("getusers"),tr("setuserdescription"),tr("getuseracl"),tr("setuseracl"),tr("getuserhosts"),tr("setuserhosts"),tr("adduser"),tr("deleteuser"),tr("setmypasswd"),tr("setpasswd"),//user management
        tr("gethosts"),tr("sethost"),tr("addhost"),tr("deletehost"), //host management
        tr("geteventlist"),tr("geteventdata"),tr("seteventdata"), //event infos
        tr("getroomdata"),tr("setroomdata"),//room infos
@@ -183,6 +183,16 @@ if($SMOKEREQUEST=="deleteuser"){
        deleteUserXml($REQUESTDATA);
        exit();
 }
+//set my own password
+if($SMOKEREQUEST=="setmypasswd"){
+       $session->setMyPasswd($REQUESTDATA);
+       exit();
+}
+//reset another users password
+if($SMOKEREQUEST=="setpasswd"){
+       setPasswdXml($REQUESTDATA);
+       exit();
+}
 
 //return a list of all hosts with their keys
 // there is currently no transaction to get names only, since this is