<pre>
<Users>
- <User name="loginname">Description of User</User>
+ <User name="loginname" passwd="initial password">Description of User</User>
...
</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>
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>
+<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>
+<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>
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()));
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"));
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
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{
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();
}
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()
{
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();
+}
#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
void editEvent();
/**update list of events*/
void updateEvents();
+ /**order ticket from event tab*/
+ void eventOrderTicket();
/**update list of users*/
void updateUsers();
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();
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
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;
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);
}
}
+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;
/**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();
/**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;
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;
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*/
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)
{
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;
$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"]));
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
//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
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