source: trunk/gsdl/src/recpt/usersaction.cpp@ 13844

Last change on this file since 13844 was 13844, checked in by mdewsnip, 17 years ago

Jeffrey's (DL Consulting) changes to userdb to make it a proper class, so it can be easily extended for collection-specific receptionists.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 13.9 KB
Line 
1/**********************************************************************
2 *
3 * usersaction.cpp -- managing users
4 * Copyright (C) 1999 DigiLib Systems Limited, New Zealand
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "gsdl_modules_cfg.h"
27#ifdef GSDL_USE_USERS_ACTION
28
29#include "usersaction.h"
30#include "fileutil.h"
31
32
33///////////////
34// usersaction
35///////////////
36
37usersaction::usersaction () {
38 // this action uses cgi variable "a"
39 cgiarginfo arg_ainfo;
40 arg_ainfo.shortname = "a";
41 arg_ainfo.longname = "action";
42 arg_ainfo.multiplechar = true;
43 arg_ainfo.defaultstatus = cgiarginfo::weak;
44 arg_ainfo.argdefault = "um"; // user management
45 arg_ainfo.savedarginfo = cgiarginfo::must;
46 argsinfo.addarginfo (NULL, arg_ainfo);
47
48 // "uma"
49 arg_ainfo.shortname = "uma";
50 arg_ainfo.longname = "user management action";
51 arg_ainfo.multiplechar = true;
52 arg_ainfo.defaultstatus = cgiarginfo::weak;
53 arg_ainfo.argdefault = "listusers";
54 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
55 argsinfo.addarginfo (NULL, arg_ainfo);
56
57 // "umun"
58 arg_ainfo.shortname = "umun";
59 arg_ainfo.longname = "user management user name";
60 arg_ainfo.multiplechar = true;
61 arg_ainfo.defaultstatus = cgiarginfo::weak;
62 arg_ainfo.argdefault = g_EmptyText;
63 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
64 argsinfo.addarginfo (NULL, arg_ainfo);
65
66 // "umpw"
67 arg_ainfo.shortname = "umpw";
68 arg_ainfo.longname = "user management password";
69 arg_ainfo.multiplechar = true;
70 arg_ainfo.defaultstatus = cgiarginfo::weak;
71 arg_ainfo.argdefault = g_EmptyText;
72 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
73 argsinfo.addarginfo (NULL, arg_ainfo);
74
75 // "umnpw1"
76 arg_ainfo.shortname = "umnpw1";
77 arg_ainfo.longname = "user management new password 1";
78 arg_ainfo.multiplechar = true;
79 arg_ainfo.defaultstatus = cgiarginfo::weak;
80 arg_ainfo.argdefault = g_EmptyText;
81 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
82 argsinfo.addarginfo (NULL, arg_ainfo);
83
84 // "umnpw2"
85 arg_ainfo.shortname = "umnpw2";
86 arg_ainfo.longname = "user management new password 2";
87 arg_ainfo.multiplechar = true;
88 arg_ainfo.defaultstatus = cgiarginfo::weak;
89 arg_ainfo.argdefault = g_EmptyText;
90 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
91 argsinfo.addarginfo (NULL, arg_ainfo);
92
93 // "umus"
94 arg_ainfo.shortname = "umus";
95 arg_ainfo.longname = "user management account status";
96 arg_ainfo.multiplechar = true;
97 arg_ainfo.defaultstatus = cgiarginfo::weak;
98 arg_ainfo.argdefault = g_EmptyText;
99 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
100 argsinfo.addarginfo (NULL, arg_ainfo);
101
102 // "umug"
103 arg_ainfo.shortname = "umug";
104 arg_ainfo.longname = "user management groups"; // comma seperated list
105 arg_ainfo.multiplechar = true;
106 arg_ainfo.defaultstatus = cgiarginfo::weak;
107 arg_ainfo.argdefault = g_EmptyText;
108 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
109 argsinfo.addarginfo (NULL, arg_ainfo);
110
111 // "umc"
112 arg_ainfo.shortname = "umc";
113 arg_ainfo.longname = "user management comment";
114 arg_ainfo.multiplechar = true;
115 arg_ainfo.defaultstatus = cgiarginfo::weak;
116 arg_ainfo.argdefault = g_EmptyText;
117 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
118 argsinfo.addarginfo (NULL, arg_ainfo);
119
120 // "bcp"
121 arg_ainfo.shortname = "bcp";
122 arg_ainfo.longname = "change password submit button";
123 arg_ainfo.multiplechar = true;
124 arg_ainfo.defaultstatus = cgiarginfo::weak;
125 arg_ainfo.argdefault = g_EmptyText;
126 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
127 argsinfo.addarginfo (NULL, arg_ainfo);
128
129 // "beu"
130 arg_ainfo.shortname = "beu";
131 arg_ainfo.longname = "edit user submit button";
132 arg_ainfo.multiplechar = true;
133 arg_ainfo.defaultstatus = cgiarginfo::weak;
134 arg_ainfo.argdefault = g_EmptyText;
135 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
136 argsinfo.addarginfo (NULL, arg_ainfo);
137
138 // "cm"
139 arg_ainfo.shortname = "cm";
140 arg_ainfo.longname = "confirm an action";
141 arg_ainfo.multiplechar = true;
142 arg_ainfo.defaultstatus = cgiarginfo::weak;
143 arg_ainfo.argdefault = g_EmptyText;
144 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
145 argsinfo.addarginfo (NULL, arg_ainfo);
146}
147
148void usersaction::configure (const text_t &key, const text_tarray &cfgline) {
149 // get the password filename
150 if (cfgline.size() == 1) {
151 if (key == "usersfile") usersfile = cfgline[0];
152 }
153
154 action::configure (key, cfgline);
155}
156
157bool usersaction::init (ostream &logout) {
158
159 if (gdbmhome.empty()) {
160 logout << "ERROR (usersaction::init) gdbmhome is not set\n";
161 return false;
162 }
163
164 if (usersfile.empty()) usersfile = filename_cat (gdbmhome, "etc", "users.db");
165
166 return action::init (logout);
167}
168
169bool usersaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
170 recptprotolistclass * /*protos*/, ostream &/*logout*/) {
171 args["uan"] = "1"; // user authentication is needed
172
173 if (args["uma"] == "changepasswd") {
174 // no particular group is needed to change a password
175 args["ug"].clear();
176 } else {
177 // administrator is needed for all other management tasks
178 args["ug"] = "administrator";
179 }
180
181 return true;
182}
183
184void usersaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
185 response_t &response, text_t &response_data,
186 ostream &/*logout*/) {
187 response = content;
188 response_data = "text/html";
189}
190
191bool usersaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
192 browsermapclass * /*browsers*/, displayclass &disp,
193 outconvertclass &outconvert, ostream &textout,
194 ostream &logout) {
195
196 // open the user database (it will be used a lot)
197 user_database = new userdbclass(usersfile);
198
199 if (args["uma"] == "adduser" || args["uma"] == "edituser") {
200 // adduser is handled by edituser
201 return do_edituser (args, disp, outconvert, textout, logout);
202
203 } else if (args["uma"] == "deleteuser") {
204 return do_deleteuser (args, disp, outconvert, textout, logout);
205
206 } else if (args["uma"] == "changepasswd") {
207 return do_changepasswd (args, disp, outconvert, textout, logout);
208 }
209
210 // default
211 return do_listusers (args, disp, outconvert, textout, logout);
212}
213
214bool usersaction::do_listusers (cgiargsclass &/*args*/, displayclass &disp,
215 outconvertclass &outconvert, ostream &textout,
216 ostream &/*logout*/) {
217
218 textout << outconvert << disp
219 << "_userslistusers:header_\n_userslistusers:contentstart_\n";
220
221 text_tarray userlist;
222 // get user list
223 user_database->get_user_list (userlist);
224
225 // sort the list
226 sort(userlist.begin(), userlist.end());
227
228 // output the information for each user
229 userinfo_t userinfo;
230 text_tarray::iterator users_here = userlist.begin();
231 text_tarray::iterator users_end = userlist.end();
232 while (users_here != users_end) {
233 if (user_database->get_user_info(*users_here, userinfo) == ERRNO_SUCCEED) {
234 textout << outconvert << disp
235 << "<tr><td bgcolor=\"\\#eeeeee\">" << userinfo.username << "</td>\n"
236 << "<td bgcolor=\"\\#eeeeee\">" << (char *) (userinfo.enabled ? "enabled" : "disabled") << "</td>\n"
237 << "<td bgcolor=\"\\#eeeeee\">" << userinfo.groups << "&nbsp;</td>\n"
238 << "<td bgcolor=\"\\#eeeeee\">" << userinfo.comment << "&nbsp;</td>\n"
239 << "<td><a href=\"_httpcurrentdocument_&a=um&uma=edituser&umun="
240 << userinfo.username << "\">_userslistusers:textedituser_</a> "
241 << "<a href=\"_httpcurrentdocument_&a=um&uma=deleteuser&umun="
242 << userinfo.username << "\">_userslistusers:textdeleteuser_</a>"
243 << "</td></tr>\n\n";
244
245 } else {
246 textout << outconvert << disp
247 << "<tr><td bgcolor=\"\\#eeeeee\">" << *users_here << "</td>\n"
248 << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
249 << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
250 << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
251 << "<td>&nbsp;</td></tr>\n\n";
252 }
253
254 ++users_here;
255 }
256
257 textout << outconvert << disp
258 << "_userslistusers:contentend_\n_userslistusers:footer_\n";
259 return true;
260}
261
262void usersaction::define_user_macros (cgiargsclass &args, displayclass &disp) {
263 disp.setmacro ("usersargun", "users", args["umun"]);
264 disp.setmacro ("usersargpw", "users", args["umpw"]);
265 disp.setmacro ("usersargus", "users", args["umus"]);
266 disp.setmacro ("usersargug", "users", args["umug"]);
267 disp.setmacro ("usersargc", "users", args["umc"]);
268}
269
270
271bool usersaction::do_edituser (cgiargsclass &args, displayclass &disp,
272 outconvertclass &outconvert, ostream &textout,
273 ostream &logout) {
274
275 userinfo_t userinfo;
276 text_t messagestatus;
277 bool noproblems = true;
278
279 // fill in defaults from user database (if appropriate)
280 if (args["umun"].empty()) {
281 noproblems = false;
282
283 } else if (!userdbclass::username_ok (args["umun"])) {
284 // problem with username
285 noproblems = false;
286 messagestatus += "_users:messageinvalidusername_";
287
288 } else if (user_database->get_user_info (args["umun"], userinfo) == ERRNO_SUCCEED) {
289 if (args["uma"] == "adduser") {
290 // must not add a user that has the same name as another user
291 noproblems = false;
292 messagestatus += "_users:messageuserexists_";
293
294 } else {
295 // only fill in the data if there is no user status defined
296 if (args["umus"].empty()) {
297 args["umus"] = userinfo.enabled ? "enabled" : "disabled";
298 if (args["umug"].empty()) args["umug"] = userinfo.groups;
299 if (args["umc"].empty()) args["umc"] = userinfo.comment;
300 }
301 }
302 }
303
304 // fill in the user status default
305 if (args["umus"].empty()) {
306 noproblems = false;
307 args["umus"] = "enabled";
308 }
309
310 // make sure the password is ok
311 if (args["umpw"].empty()) {
312 // password must not be empty if none were supplied from database
313 // and we have had no other problems
314 if (userinfo.password.empty() && noproblems) {
315 noproblems = false;
316 messagestatus += "_users:messageemptypassword_";
317 }
318
319 } else if (!userdbclass::password_ok(args["umpw"])) {
320 noproblems = false;
321 messagestatus += "_users:messageinvalidpassword_";
322 }
323
324 // set this info if no problems have been encounted
325 // and the submit button was pressed
326 if (noproblems && !args["beu"].empty()) {
327 userinfo.username = args["umun"];
328 if (!args["umpw"].empty()) {
329 // only set the password if it is not empty
330 userinfo.password = userdbclass::crypt_text(args["umpw"]);
331 }
332 userinfo.enabled = (args["umus"] == "enabled");
333 userinfo.groups = userdbclass::format_user_groups(args["umug"]);
334 userinfo.comment = args["umc"];
335
336 user_database->set_user_info (args["umun"], userinfo);
337
338 // show list of users
339 return do_listusers (args, disp, outconvert, textout, logout);
340 }
341
342 // define the macros for the user
343 define_user_macros (args, disp);
344 disp.setmacro ("messagestatus", "users", messagestatus);
345
346 textout << outconvert << disp
347 << "_usersedituser:header_\n_usersedituser:content_\n_usersedituser:footer_\n";
348
349 return true;
350}
351
352bool usersaction::do_deleteuser (cgiargsclass &args, displayclass &disp,
353 outconvertclass &outconvert, ostream &textout,
354 ostream &logout) {
355 if (!args["cm"].empty()) {
356 if (args["cm"] == "yes" && !args["umun"].empty()) {
357 // user confirmed the deletion of the user
358 user_database->delete_user(args["umun"]);
359 }
360
361 // redirect the user back to the listusers page
362 return do_listusers (args, disp, outconvert, textout, logout);
363 }
364
365 define_user_macros (args, disp);
366 textout << outconvert << disp
367 << "_usersdeleteuser:header_\n_usersdeleteuser:content_\n_usersdeleteuser:footer_\n";
368
369 return true;
370}
371
372bool usersaction::do_changepasswd (cgiargsclass &args, displayclass &disp,
373 outconvertclass &outconvert, ostream &textout,
374 ostream &/*logout*/) {
375 text_t messagestatus;
376
377 if (!args["bcp"].empty()) {
378 if (args["un"].empty()) {
379 messagestatus = "_users:messageusernameempty_";
380 } else if (args["umpw"].empty()) {
381 messagestatus = "_users:messagepasswordempty_";
382 } else if (args["umnpw1"].empty()) {
383 messagestatus = "_users:messagenewpass1empty_";
384 } else if (args["umnpw2"].empty()) {
385 messagestatus = "_users:messagenewpass2empty_";
386 } else if (args["umnpw1"] != args["umnpw2"]) {
387 messagestatus = "_users:messagenewpassmismatch_";
388 } else if (!userdbclass::password_ok(args["umnpw1"])) {
389 messagestatus = "_users:messageinvalidpassword_";
390 } else {
391 userinfo_t userinfo;
392 if (user_database->get_user_info (args["un"], userinfo) == ERRNO_SUCCEED) {
393 // check old password
394 if (userinfo.password != userdbclass::crypt_text(args["umpw"])) {
395 messagestatus = "_users:messagefailed_";
396
397 } else {
398 userinfo.password = userdbclass::crypt_text(args["umnpw1"]);
399 if (user_database->set_user_info (args["un"], userinfo) == ERRNO_SUCCEED) {
400 // everything is ok
401 textout << outconvert << disp
402 << "_userschangepasswdok:header_\n"
403 "_userschangepasswdok:content_\n"
404 "_userschangepasswdok:footer_\n";
405 return true;
406 }
407 }
408 }
409 }
410 }
411
412 disp.setmacro ("messagestatus", "users", messagestatus);
413
414 textout << outconvert << disp
415 << "_userschangepasswd:header_\n"
416 "_userschangepasswd:content_\n"
417 "_userschangepasswd:footer_\n";
418
419 return true;
420}
421
422#endif //GSDL_USE_USERS_ACTION
Note: See TracBrowser for help on using the repository browser.