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

Last change on this file since 2212 was 2212, checked in by sjboddie, 23 years ago

Fixed a bug that was causing the local library server to attempt to write
files to gsdlhome (i.e. the cd-rom drive if served from a cd) under certain
circumstances.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 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 "usersaction.h"
27#include "fileutil.h"
28#include "userdb.h"
29
30
31///////////////
32// usersaction
33///////////////
34
35usersaction::usersaction () {
36 // this action uses cgi variable "a"
37 cgiarginfo arg_ainfo;
38 arg_ainfo.shortname = "a";
39 arg_ainfo.longname = "action";
40 arg_ainfo.multiplechar = true;
41 arg_ainfo.defaultstatus = cgiarginfo::weak;
42 arg_ainfo.argdefault = "um"; // user management
43 arg_ainfo.savedarginfo = cgiarginfo::must;
44 argsinfo.addarginfo (NULL, arg_ainfo);
45
46 // "uma"
47 arg_ainfo.shortname = "uma";
48 arg_ainfo.longname = "user management action";
49 arg_ainfo.multiplechar = true;
50 arg_ainfo.defaultstatus = cgiarginfo::weak;
51 arg_ainfo.argdefault = "listusers";
52 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
53 argsinfo.addarginfo (NULL, arg_ainfo);
54
55 // "umun"
56 arg_ainfo.shortname = "umun";
57 arg_ainfo.longname = "user management user name";
58 arg_ainfo.multiplechar = true;
59 arg_ainfo.defaultstatus = cgiarginfo::weak;
60 arg_ainfo.argdefault = "";
61 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
62 argsinfo.addarginfo (NULL, arg_ainfo);
63
64 // "umpw"
65 arg_ainfo.shortname = "umpw";
66 arg_ainfo.longname = "user management password";
67 arg_ainfo.multiplechar = true;
68 arg_ainfo.defaultstatus = cgiarginfo::weak;
69 arg_ainfo.argdefault = "";
70 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
71 argsinfo.addarginfo (NULL, arg_ainfo);
72
73 // "umnpw1"
74 arg_ainfo.shortname = "umnpw1";
75 arg_ainfo.longname = "user management new password 1";
76 arg_ainfo.multiplechar = true;
77 arg_ainfo.defaultstatus = cgiarginfo::weak;
78 arg_ainfo.argdefault = "";
79 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
80 argsinfo.addarginfo (NULL, arg_ainfo);
81
82 // "umnpw2"
83 arg_ainfo.shortname = "umnpw2";
84 arg_ainfo.longname = "user management new password 2";
85 arg_ainfo.multiplechar = true;
86 arg_ainfo.defaultstatus = cgiarginfo::weak;
87 arg_ainfo.argdefault = "";
88 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
89 argsinfo.addarginfo (NULL, arg_ainfo);
90
91 // "umus"
92 arg_ainfo.shortname = "umus";
93 arg_ainfo.longname = "user management account status";
94 arg_ainfo.multiplechar = true;
95 arg_ainfo.defaultstatus = cgiarginfo::weak;
96 arg_ainfo.argdefault = "";
97 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
98 argsinfo.addarginfo (NULL, arg_ainfo);
99
100 // "umug"
101 arg_ainfo.shortname = "umug";
102 arg_ainfo.longname = "user management groups"; // comma seperated list
103 arg_ainfo.multiplechar = true;
104 arg_ainfo.defaultstatus = cgiarginfo::weak;
105 arg_ainfo.argdefault = "";
106 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
107 argsinfo.addarginfo (NULL, arg_ainfo);
108
109 // "umc"
110 arg_ainfo.shortname = "umc";
111 arg_ainfo.longname = "user management comment";
112 arg_ainfo.multiplechar = true;
113 arg_ainfo.defaultstatus = cgiarginfo::weak;
114 arg_ainfo.argdefault = "";
115 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
116 argsinfo.addarginfo (NULL, arg_ainfo);
117
118 // "bcp"
119 arg_ainfo.shortname = "bcp";
120 arg_ainfo.longname = "change password submit button";
121 arg_ainfo.multiplechar = true;
122 arg_ainfo.defaultstatus = cgiarginfo::weak;
123 arg_ainfo.argdefault = "";
124 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
125 argsinfo.addarginfo (NULL, arg_ainfo);
126
127 // "beu"
128 arg_ainfo.shortname = "beu";
129 arg_ainfo.longname = "edit user submit button";
130 arg_ainfo.multiplechar = true;
131 arg_ainfo.defaultstatus = cgiarginfo::weak;
132 arg_ainfo.argdefault = "";
133 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
134 argsinfo.addarginfo (NULL, arg_ainfo);
135
136 // "cm"
137 arg_ainfo.shortname = "cm";
138 arg_ainfo.longname = "confirm an action";
139 arg_ainfo.multiplechar = true;
140 arg_ainfo.defaultstatus = cgiarginfo::weak;
141 arg_ainfo.argdefault = "";
142 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
143 argsinfo.addarginfo (NULL, arg_ainfo);
144}
145
146void usersaction::configure (const text_t &key, const text_tarray &cfgline) {
147 // get the password filename
148 if (cfgline.size() == 1) {
149 if (key == "usersfile") usersfile = cfgline[0];
150 }
151
152 action::configure (key, cfgline);
153}
154
155bool usersaction::init (ostream &logout) {
156
157 if (gdbmhome.empty()) {
158 logout << "ERROR (usersaction::init) gdbmhome is not set\n";
159 return false;
160 }
161
162 if (usersfile.empty()) usersfile = filename_cat (gdbmhome, "etc", "users.db");
163
164 return action::init (logout);
165}
166
167bool usersaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
168 ostream &/*logout*/) {
169 args["uan"] = "1"; // user authentication is needed
170
171 if (args["uma"] == "changepasswd") {
172 // no particular group is needed to change a password
173 args["ug"].clear();
174 } else {
175 // administrator is needed for all other management tasks
176 args["ug"] = "administrator";
177 }
178
179 return true;
180}
181
182void usersaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
183 response_t &response, text_t &response_data,
184 ostream &/*logout*/) {
185 response = content;
186 response_data = "text/html";
187}
188
189bool usersaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
190 browsermapclass * /*browsers*/, displayclass &disp,
191 outconvertclass &outconvert, ostream &textout,
192 ostream &logout) {
193
194 if (args["uma"] == "adduser" || args["uma"] == "edituser") {
195 // adduser is handled by edituser
196 return do_edituser (args, disp, outconvert, textout, logout);
197
198 } else if (args["uma"] == "deleteuser") {
199 return do_deleteuser (args, disp, outconvert, textout, logout);
200
201 } else if (args["uma"] == "changepasswd") {
202 return do_changepasswd (args, disp, outconvert, textout, logout);
203 }
204
205 // default
206 return do_listusers (args, disp, outconvert, textout, logout);
207}
208
209bool usersaction::do_listusers (cgiargsclass &/*args*/, displayclass &disp,
210 outconvertclass &outconvert, ostream &textout,
211 ostream &/*logout*/) {
212
213 textout << outconvert << disp
214 << "_userslistusers:header_\n_userslistusers:contentstart_\n";
215
216
217 // open the user database (it will be used a lot)
218 gdbmclass userdb;
219 text_tarray userlist;
220 if (userdb.opendatabase(usersfile, GDBM_READER, 1000, true)) {
221 // get user list
222 get_user_list (userdb, userlist);
223 }
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 (get_user_info (userdb, *users_here, userinfo)) {
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 userdb.closedatabase();
258
259 textout << outconvert << disp
260 << "_userslistusers:contentend_\n_userslistusers:footer_\n";
261 return true;
262}
263
264void usersaction::define_user_macros (cgiargsclass &args, displayclass &disp) {
265 disp.setmacro ("usersargun", "users", args["umun"]);
266 disp.setmacro ("usersargpw", "users", args["umpw"]);
267 disp.setmacro ("usersargus", "users", args["umus"]);
268 disp.setmacro ("usersargug", "users", args["umug"]);
269 disp.setmacro ("usersargc", "users", args["umc"]);
270}
271
272
273bool usersaction::do_edituser (cgiargsclass &args, displayclass &disp,
274 outconvertclass &outconvert, ostream &textout,
275 ostream &logout) {
276 userinfo_t userinfo;
277 text_t messagestatus;
278 bool noproblems = true;
279
280 // fill in defaults from user database (if appropriate)
281 if (args["umun"].empty()) {
282 noproblems = false;
283
284 } else if (!username_ok (args["umun"])) {
285 // problem with username
286 noproblems = false;
287 messagestatus += "_users:messageinvalidusername_";
288
289 } else if (get_user_info (usersfile, args["umun"], userinfo)) {
290 if (args["uma"] == "adduser") {
291 // must not add a user that has the same name as another user
292 noproblems = false;
293 messagestatus += "_users:messageuserexists_";
294
295 } else {
296 // only fill in the data if there is no user status defined
297 if (args["umus"].empty()) {
298 args["umus"] = userinfo.enabled ? "enabled" : "disabled";
299 if (args["umug"].empty()) args["umug"] = userinfo.groups;
300 if (args["umc"].empty()) args["umc"] = userinfo.comment;
301 }
302 }
303 }
304
305 // fill in the user status default
306 if (args["umus"].empty()) {
307 noproblems = false;
308 args["umus"] = "enabled";
309 }
310
311 // make sure the password is ok
312 if (args["umpw"].empty()) {
313 // password must not be empty if none were supplied from database
314 // and we have had no other problems
315 if (userinfo.password.empty() && noproblems) {
316 noproblems = false;
317 messagestatus += "_users:messageemptypassword_";
318 }
319
320 } else if (!password_ok(args["umpw"])) {
321 noproblems = false;
322 messagestatus += "_users:messageinvalidpassword_";
323 }
324
325 // set this info if no problems have been encounted
326 // and the submit button was pressed
327 if (noproblems && !args["beu"].empty()) {
328 userinfo.username = args["umun"];
329 if (!args["umpw"].empty()) {
330 // only set the password if it is not empty
331 userinfo.password = crypt_text(args["umpw"]);
332 }
333 userinfo.enabled = (args["umus"] == "enabled");
334 userinfo.groups = args["umug"];
335 userinfo.comment = args["umc"];
336
337 set_user_info (usersfile, args["umun"], userinfo);
338
339 // show list of users
340 return do_listusers (args, disp, outconvert, textout, logout);
341 }
342
343 // define the macros for the user
344 define_user_macros (args, disp);
345 disp.setmacro ("messagestatus", "users", messagestatus);
346
347 textout << outconvert << disp
348 << "_usersedituser:header_\n_usersedituser:content_\n_usersedituser:footer_\n";
349
350 return true;
351}
352
353bool usersaction::do_deleteuser (cgiargsclass &args, displayclass &disp,
354 outconvertclass &outconvert, ostream &textout,
355 ostream &logout) {
356 if (!args["cm"].empty()) {
357 if (args["cm"] == "yes" && !args["umun"].empty()) {
358 // user confirmed the deletion of the user
359 delete_user (usersfile, args["umun"]);
360 }
361
362 // redirect the user back to the listusers page
363 return do_listusers (args, disp, outconvert, textout, logout);
364 }
365
366 define_user_macros (args, disp);
367 textout << outconvert << disp
368 << "_usersdeleteuser:header_\n_usersdeleteuser:content_\n_usersdeleteuser:footer_\n";
369
370 return true;
371}
372
373bool usersaction::do_changepasswd (cgiargsclass &args, displayclass &disp,
374 outconvertclass &outconvert, ostream &textout,
375 ostream &/*logout*/) {
376 text_t messagestatus;
377
378 if (!args["bcp"].empty()) {
379 if (args["un"].empty()) {
380 messagestatus = "_users:messageusernameempty_";
381 } else if (args["umpw"].empty()) {
382 messagestatus = "_users:messagepasswordempty_";
383 } else if (args["umnpw1"].empty()) {
384 messagestatus = "_users:messagenewpass1empty_";
385 } else if (args["umnpw2"].empty()) {
386 messagestatus = "_users:messagenewpass2empty_";
387 } else if (args["umnpw1"] != args["umnpw2"]) {
388 messagestatus = "_users:messagenewpassmismatch_";
389 } else if (!password_ok(args["umnpw1"])) {
390 messagestatus = "_users:messageinvalidpassword_";
391 } else {
392 userinfo_t userinfo;
393 if (get_user_info (usersfile, args["un"], userinfo)) {
394 // check old password
395 if (userinfo.password != crypt_text(args["umpw"])) {
396 messagestatus = "_users:messagefailed_";
397
398 } else {
399 userinfo.password = crypt_text(args["umnpw1"]);
400 if (set_user_info (usersfile, args["un"], userinfo)) {
401 // everything is ok
402 textout << outconvert << disp
403 << "_userschangepasswdok:header_\n"
404 "_userschangepasswdok:content_\n"
405 "_userschangepasswdok:footer_\n";
406 return true;
407 }
408 }
409 }
410 }
411 }
412
413 disp.setmacro ("messagestatus", "users", messagestatus);
414
415 textout << outconvert << disp
416 << "_userschangepasswd:header_\n"
417 "_userschangepasswd:content_\n"
418 "_userschangepasswd:footer_\n";
419
420 return true;
421}
Note: See TracBrowser for help on using the repository browser.