source: trunk/services/admins.php @ 295

Last change on this file since 295 was 295, checked in by quinn, 16 years ago

Updated example config file. Added admin2.inc.css and minor corrections into HTML. Module maker fixes.

File size: 21.4 KB
Line 
1<?php
2/**
3 * admins.php
4 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
5 */
6
7// require_once dirname(__FILE__) . '/_config.inc.php';
8
9$auth->requireLogin();
10$app->sslOn();
11
12require_once 'codebase/lib/PageNumbers.inc.php';
13require_once 'codebase/lib/Cache.inc.php';
14require_once 'codebase/lib/FormValidator.inc.php';
15require_once 'codebase/lib/SortOrder.inc.php';
16require_once 'codebase/lib/TemplateGlue.inc.php';
17require_once 'codebase/lib/Prefs.inc.php';
18require_once 'codebase/lib/Lock.inc.php';
19require_once 'codebase/lib/Version.inc.php';
20
21
22/********************************************************************
23* CONFIG
24********************************************************************/
25
26// Titles and navigation header.
27$nav->add(_("Administrators"), null);
28
29// The object to validate form input.
30$fv = new FormValidator();
31
32// Configure the prefs object.
33$tmp_prefs = new Prefs('admins');
34$tmp_prefs->setParam(array('persistent' => false));
35
36// Configure the cache object.
37$cache = new Cache('admins');
38$cache->setParam(array('enable' => true));
39
40// Instantiate a sorting object with the default sort and order. Add SQL for each column.
41$so = new SortOrder('admin_id', 'DESC');
42$so->setColumn('admin_id', $auth->getParam('db_primary_key') . ' ASC', $auth->getParam('db_primary_key') . ' DESC');
43$so->setColumn('username', $auth->getParam('db_username_column') . ' ASC', $auth->getParam('db_username_column') . ' DESC');
44$so->setColumn('userpass', $auth->getParam('db_table') . '.userpass ASC', $auth->getParam('db_table') . '.userpass DESC');
45$so->setColumn('first_name', $auth->getParam('db_table') . '.first_name ASC', $auth->getParam('db_table') . '.first_name DESC');
46$so->setColumn('last_name', $auth->getParam('db_table') . '.last_name ASC', $auth->getParam('db_table') . '.last_name DESC');
47$so->setColumn('email', $auth->getParam('db_table') . '.email ASC', $auth->getParam('db_table') . '.email DESC');
48$so->setColumn('user_type', $auth->getParam('db_table') . '.user_type ASC', $auth->getParam('db_table') . '.user_type DESC');
49$so->setColumn('seconds_online', $auth->getParam('db_table') . '.seconds_online ASC', $auth->getParam('db_table') . '.seconds_online DESC');
50$so->setColumn('last_login_datetime', $auth->getParam('db_table') . '.last_login_datetime ASC', $auth->getParam('db_table') . '.last_login_datetime DESC');
51$so->setColumn('last_access_datetime', $auth->getParam('db_table') . '.last_access_datetime ASC', $auth->getParam('db_table') . '.last_access_datetime DESC');
52$so->setColumn('last_login_ip', $auth->getParam('db_table') . '.last_login_ip ASC', $auth->getParam('db_table') . '.last_login_ip DESC');
53$so->setColumn('added_by_user_id', $auth->getParam('db_table') . '.added_by_user_id ASC', $auth->getParam('db_table') . '.added_by_user_id DESC');
54$so->setColumn('modified_by_user_id', $auth->getParam('db_table') . '.modified_by_user_id ASC', $auth->getParam('db_table') . '.modified_by_user_id DESC');
55$so->setColumn('added_datetime', $auth->getParam('db_table') . '.added_datetime ASC', $auth->getParam('db_table') . '.added_datetime DESC');
56$so->setColumn('modified_datetime', $auth->getParam('db_table') . '.modified_datetime ASC', $auth->getParam('db_table') . '.modified_datetime DESC');
57
58// Instantiate page numbers. Total items are set and calculation is done in the getRecordList function.
59$page = new PageNumbers();
60$page->setPerPage(getFormData('per_page'), 50);
61$page->setPageNumber(getFormData('page_number'));
62
63// Search limiters retain their values between page requests.
64$app->carryQuery('search_query');
65
66
67/********************************************************************
68* MAIN
69********************************************************************/
70
71// We may want to use the add/edit interface from another script, so this
72// allows us to remember which page we came from so we can go back there.
73if (getFormData('boomerang', false) && isset($_SERVER['HTTP_REFERER'])) {
74    $app->setBoomerangURL($_SERVER['HTTP_REFERER'], 'admins');
75}
76
77if (getFormData('break_list_cache', false)) {
78    // Remove any stale cached list data.
79    $cache->delete('list');
80}
81
82// What action to take.
83switch (getFormData('op')) {
84
85case 'add' :
86    // Initialize variables for the form template.
87    $frm =& addRecordForm();
88    $nav->add(_("Add Administrator"));
89    $main_template = 'admin_form.ihtml';
90    break;
91
92case 'edit' :
93    // Initialize variables for the form template.
94    $frm =& editRecordForm(getFormData('admin_id'));
95    $nav->add(_("Edit Administrator"));
96    $main_template = 'admin_form.ihtml';
97    break;
98
99case 'del' :
100    deleteRecord(getFormData('admin_id'));
101    if ($app->validBoomerangURL('admins')) {
102        // Display boomerang page.
103        $app->dieBoomerangURL('admins');
104    }
105    // Display default page.
106    $app->dieURL($_SERVER['PHP_SELF']);
107    break;
108
109case 'insert' :
110    if (getFormdata('cancel', false)) {
111        if ($app->validBoomerangURL('admins')) {
112            // Display boomerang page.
113            $app->dieBoomerangURL('admins');
114        }
115        // Display default page.
116        $app->dieURL($_SERVER['PHP_SELF']);
117    }
118    validateInput();
119    if ($fv->anyErrors()) {
120        $frm =& addRecordForm();
121        $frm = array_merge($frm, getFormData());
122        $nav->add(_("Add Administrator"));
123        $main_template = 'admin_form.ihtml';
124    } else {
125        $admin_id = insertRecord(getFormData());
126        if (getFormdata('repeat', false)) {
127            // Display function again.
128            $app->dieURL($_SERVER['PHP_SELF'] . '?op=add');
129        } else if ($app->validBoomerangURL('admins')) {
130            // Display boomerang page.
131            $app->dieBoomerangURL('admins');
132        }
133        // Display default page.
134        $app->dieURL($_SERVER['PHP_SELF']);
135    }
136    break;
137
138case 'update' :
139    if (getFormdata('reset', false)) {
140        $app->raiseMsg(_("Saved values have been reloaded."), MSG_NOTICE, __FILE__, __LINE__);
141        $app->dieURL($_SERVER['PHP_SELF'] . '?op=edit&admin_id=' . getFormData('admin_id'));
142    }
143    if (getFormdata('cancel', false)) {
144        // Remove lock
145        $lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), getFormData('admin_id'));
146        $lock->remove();
147        if ($app->validBoomerangURL('admins')) {
148            // Display boomerang page.
149            $app->dieBoomerangURL('admins');
150        }
151        // Display default page.
152        $app->dieURL($_SERVER['PHP_SELF']);
153    }
154    validateInput();
155    if ($fv->anyErrors()) {
156        $frm =& editRecordForm(getFormData('admin_id'));
157        $frm = array_merge($frm, getFormData());
158        $nav->add(_("Edit Administrator"));
159        $main_template = 'admin_form.ihtml';
160    } else {
161        updateRecord(getFormData());
162        if (getFormdata('repeat', false)) {
163            // Display edit function with next available ID.
164            $qid = $db->query("SELECT " . $auth->getParam('db_primary_key') . " FROM " . $auth->getParam('db_table') . " WHERE " . $auth->getParam('db_primary_key') . " > '" . $db->escapeString(getFormData('admin_id')) . "' ORDER BY " . $auth->getParam('db_primary_key') . " ASC LIMIT 1");
165            if (list($next_id) = mysql_fetch_row($qid)) {
166                $app->dieURL($_SERVER['PHP_SELF'] . '?op=edit&admin_id=' . $next_id);
167            } else {
168                $app->raiseMsg(_("Cannot edit next, the end of the list was reached"), MSG_NOTICE, __FILE__, __LINE__);
169            }
170        } else if ($app->validBoomerangURL('admins')) {
171            // Display boomerang page.
172            $app->dieBoomerangURL('admins');
173        }
174        // Display default page.
175        $app->dieURL($_SERVER['PHP_SELF']);
176    }
177    break;
178
179default :
180    $list =& getRecordList();
181    $main_template = 'admin_list.ihtml';
182    break;
183}
184
185/******************************************************************************
186 * TEMPLATE INITIALIZATION
187 *****************************************************************************/
188
189include 'header.ihtml';
190include 'codebase/services/templates/' . $main_template;
191include 'footer.ihtml';
192
193/********************************************************************
194* FUNCTIONS
195********************************************************************/
196
197
198function validateInput()
199{
200    global $fv, $auth;
201
202    // If the username was changed during edit, verify.
203    if (((getFormData('username') != getFormData('old_username')) && 'update' == getFormData('op'))
204    || 'insert' == getFormData('op')) {
205        if ($auth->usernameExists(getFormData('username'))) {
206            $fv->addError('username', sprintf(_("The username %s already exists. Please choose another."), getFormData('username')));
207        }
208    }
209
210    if (getFormData('user_type') == 'root' && 'root' != $auth->get('user_type')) {
211        $fv->addError('user_type', sprintf(_("You do not have clearance to create a user with root privileges."), null));
212    }
213
214    $fv->numericRange('admin_id', -32768, 32767, _("<strong>Admin id</strong> must be a valid number between -32768 and 32767."));
215
216    $fv->isEmpty('username', _("<strong>Username</strong> cannot be blank."));
217    $fv->stringLength('username', 0, 255, _("<strong>Username</strong> must contain less than 256 characters."));
218
219    $fv->isEmpty('userpass', _("<strong>Passwords</strong> cannot be blank."));
220    $fv->stringLength('userpass', 6, 36, _("<strong>Passwords</strong> must be between 6 and 36 characters long."));
221
222    $fv->stringLength('first_name', 0, 255, _("<strong>First name</strong> must contain less than 256 characters."));
223
224    $fv->stringLength('last_name', 0, 255, _("<strong>Last name</strong> must contain less than 256 characters."));
225
226    $fv->isEmpty('email', _("<strong>Email</strong> cannot be blank."));
227    $fv->stringLength('email', 0, 255, _("<strong>Email</strong> must contain less than 256 characters."));
228    $fv->validateEmail('email');
229
230    $fv->isEmpty('user_type', _("<strong>User type</strong> cannot be blank."));
231    $fv->stringLength('user_type', 0, 255, _("<strong>User type</strong> has an invalid selection."));
232}
233
234function &addRecordForm()
235{
236    // Set default values for the reset of the fields.
237    $frm = array(
238        'admin_id' => '',
239        'old_username' => '',
240        'username' => '',
241        'userpass' => '',
242        'first_name' => '',
243        'last_name' => '',
244        'email' => '',
245        'user_type' => '',
246        'seconds_online' => '0',
247        'last_login_datetime' => '0000-00-00 00:00:00',
248        'last_access_datetime' => '0000-00-00 00:00:00',
249        'last_login_ip' => '0.0.0.0',
250        'added_by_user_id' => '',
251        'modified_by_user_id' => '',
252        'added_datetime' => '0000-00-00 00:00:00',
253        'modified_datetime' => '0000-00-00 00:00:00',
254        'new_op' => 'insert',
255        'submit_buttons' => array(
256            'submit' => _("Add Administrator"),
257            'repeat' => _("Add &amp; repeat"),
258            'cancel' => _("Cancel"),
259        ),
260    );
261
262    return $frm;
263}
264
265function &editRecordForm($id)
266{
267    global $auth;
268    global $lock;
269    $app =& App::getInstance();
270    $db =& DB::getInstance();
271   
272    $lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $id);
273    if ($lock->isLocked() && !$lock->isMine()) {
274        $lock->dieErrorPage();
275    }
276
277    // Get the information for the form.
278    $qid = $db->query("
279        SELECT *,
280        " . $auth->getParam('db_primary_key') . " AS admin_id
281        FROM " . $auth->getParam('db_table') . "
282        WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($id) . "'
283    ");
284    if (!$frm = mysql_fetch_assoc($qid)) {
285        $app->logMsg('Could not find record with admin_id: ' . $id, LOG_WARNING, __FILE__, __LINE__);
286        $app->raiseMsg(sprintf(_("The requested record %s could not be found."), $id), MSG_ERR, __FILE__, __LINE__);
287        $app->dieBoomerangURL();
288    }
289
290    // Lock this record.
291    $lock->set($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $id, $frm['username']);
292
293    // Set misc values for the form.
294    $frm = array_merge(array(
295        'admin_id' => '',
296        'old_username' => $frm['username'],
297        'username' => '',
298//         'userpass' => '****************',
299        'first_name' => '',
300        'last_name' => '',
301        'email' => '',
302        'user_type' => '',
303        'seconds_online' => '0',
304        'last_login_datetime' => '0000-00-00 00:00:00',
305        'last_access_datetime' => '0000-00-00 00:00:00',
306        'last_login_ip' => '0.0.0.0',
307        'added_by_user_id' => '',
308        'modified_by_user_id' => '',
309        'added_datetime' => '0000-00-00 00:00:00',
310        'modified_datetime' => '0000-00-00 00:00:00',
311        'new_op' => 'update',
312        'old_username' => $frm['username'],
313        'submit_buttons' => array(
314            'submit' => _("Save changes"),
315            'repeat' => _("Save &amp; edit next"),
316            'reset' => _("Reset"),
317            'cancel' => _("Cancel"),
318        ),
319    ), $frm, array('userpass' => '****************'));
320
321    return $frm;
322}
323
324function deleteRecord($id)
325{
326    global $auth;
327    global $lock;
328    global $cache;
329    $app =& App::getInstance();
330    $db =& DB::getInstance();
331   
332    $lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $id);
333    if ($lock->isLocked() && !$lock->isMine()) {
334        $lock->dieErrorPage();
335    }
336
337    // Remove any stale cached list data.
338    $cache->delete('list');
339
340    // Get the information for this object.
341    $qid = $db->query("
342        SELECT " . $auth->getParam('db_username_column') . ", user_type from " . $auth->getParam('db_table') . "
343        WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($id) . "'
344    ");
345    if (! list($name, $user_type) = mysql_fetch_row($qid)) {
346        $app->logMsg('Could not find record with admin_id: ' . $id, LOG_WARNING, __FILE__, __LINE__);
347        $app->raiseMsg(sprintf(_("The requested record %s could not be found."), $id), MSG_ERR, __FILE__, __LINE__);
348        $app->dieBoomerangURL();
349    }
350
351    // Get the information for this object.
352    $qid = $db->query("SELECT COUNT(*) from " . $auth->getParam('db_table') . "");
353    list($num_admins) = mysql_fetch_row($qid);
354    if ('root' == $user_type && 'root' != $auth->get('user_type')) {
355        // Only root users can delete root users!
356        $app->raiseMsg(_("You do not have clearance to delete a root administrator."), MSG_NOTICE, __FILE__, __LINE__);
357    } else if ($num_admins <= 1) {
358        // There must always be at least one admnistrator!
359        $app->raiseMsg(_("You cannot delete the only administrator in the database. There must be at least one to log in and create other users."), MSG_NOTICE, __FILE__, __LINE__);
360    } else if ($auth->get('user_id') == $id) {
361        // Do not delete yourself!
362        $app->raiseMsg(_("You cannot delete yourself."), MSG_NOTICE, __FILE__, __LINE__);
363    } else {
364        // Delete the record.
365        $db->query("DELETE FROM " . $auth->getParam('db_table') . " WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($id) . "'");
366        $app->raiseMsg(sprintf(_("The admin <em>%s</em> has been deleted."), $name), MSG_SUCCESS, __FILE__, __LINE__);
367    }
368
369    // Unlock record.
370    $lock->remove();
371}
372
373function insertRecord($frm)
374{
375    global $auth;
376    global $cache;
377    $app =& App::getInstance();
378    $db =& DB::getInstance();
379   
380    // Remove any stale cached list data.
381    $cache->delete('list');
382
383    // Insert record data.
384    $db->query("
385        INSERT INTO " . $auth->getParam('db_table') . " (
386            " . $auth->getParam('db_username_column') . ",
387            first_name,
388            last_name,
389            email,
390            user_type,
391            added_by_user_id,
392            added_datetime
393        ) VALUES (
394            '" . $db->escapeString($frm['username']) . "',
395            '" . $db->escapeString($frm['first_name']) . "',
396            '" . $db->escapeString($frm['last_name']) . "',
397            '" . $db->escapeString($frm['email']) . "',
398            '" . $db->escapeString($frm['user_type']) . "',
399            '" . $db->escapeString($auth->get('user_id')) . "',
400            NOW()
401        )
402    ");
403    $last_insert_id = mysql_insert_id($db->getDBH());
404
405    // Set admin password.
406    $auth->setPassword($last_insert_id, $frm['userpass']);
407
408    // Create version.
409    $version = Version::getInstance($auth);
410    $version->create($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $last_insert_id, $frm['username']);
411
412    $app->raiseMsg(sprintf(_("The Administrator <em>%s</em> has been added."), $frm['username']), MSG_SUCCESS, __FILE__, __LINE__);
413
414    return $last_insert_id;
415}
416
417function updateRecord($frm)
418{
419    global $auth;
420    global $lock;
421    global $cache;
422    $app =& App::getInstance();
423    $db =& DB::getInstance();
424   
425    $lock->select($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $frm['admin_id']);
426    if ($lock->isLocked() && !$lock->isMine()) {
427        $lock->dieErrorPage();
428    }
429
430    // Remove any stale cached list data.
431    $cache->delete('list');
432
433    // If the userpass is left blank or with the filler **** characters, we don't want to update it.
434    if (!empty($frm['userpass']) && !preg_match('/[\*]{4,}/', $frm['userpass'])) {
435        // Set user password.
436        $auth->setPassword($frm['admin_id'], $frm['userpass']);
437    }
438
439    // Update record data.
440    $db->query("
441        UPDATE " . $auth->getParam('db_table') . " SET
442            " . $auth->getParam('db_username_column') . " = '" . $db->escapeString($frm['username']) . "',
443            first_name = '" . $db->escapeString($frm['first_name']) . "',
444            last_name = '" . $db->escapeString($frm['last_name']) . "',
445            email = '" . $db->escapeString($frm['email']) . "',
446            user_type = '" . $db->escapeString($frm['user_type']) . "',
447            modified_by_user_id = '" . $db->escapeString($auth->get('user_id')) . "',
448            modified_datetime = NOW()
449        WHERE " . $auth->getParam('db_primary_key') . " = '" . $db->escapeString($frm['admin_id']) . "'
450    ");
451
452    // Create version.
453    $version = Version::getInstance($auth);
454    $version->create($auth->getParam('db_table'), $auth->getParam('db_primary_key'), $frm['admin_id'], $frm['username']);
455
456    $app->raiseMsg(sprintf(_("The Administrator <em>%s</em> has been updated."), $frm['username']), MSG_SUCCESS, __FILE__, __LINE__);
457
458    // Unlock record.
459    $lock->remove();
460}
461
462function &getRecordList()
463{
464    global $page;
465    global $so;
466    global $tmp_prefs;
467    global $cache;
468    global $auth;
469    $db =& DB::getInstance();
470   
471    $where_clause = '';
472
473    // Build search query if available.
474    if (getFormData('search_query', false)) {
475        $qry_words = preg_split('/[^\w]/', getFormData('search_query'));
476        for ($i=0; $i<sizeof($qry_words); $i++) {
477            $where_clause .= (empty($where_clause) ? 'WHERE' : 'AND') . "
478                (
479                    " . $auth->getParam('db_table') . "." . $auth->getParam('db_username_column') . " LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
480                    OR " . $auth->getParam('db_table') . ".first_name LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
481                    OR " . $auth->getParam('db_table') . ".last_name LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
482                    OR " . $auth->getParam('db_table') . ".email LIKE '%" . $db->escapeString($qry_words[$i]) . "%'
483                )
484            ";
485        }
486    }
487
488    // Count the total number of records so we can do something about the page numbers.
489    $qid = $db->query("
490        SELECT COUNT(*)
491        FROM " . $auth->getParam('db_table') . "
492        $where_clause
493    ");
494    list($num_results) = mysql_fetch_row($qid);
495
496    // Set page numbers now we know (needed for next step).
497    $page->setTotalItems($num_results);
498    $page->calculate();
499
500    // Final SQL, with sort and page limiters.
501    $sql = "
502        SELECT
503            " . $auth->getParam('db_table') . ".*,
504            " . $auth->getParam('db_table') . "." . $auth->getParam('db_primary_key') . " AS admin_id,           
505            a1." . $auth->getParam('db_username_column') . " AS added_admin_username,
506            a2." . $auth->getParam('db_username_column') . " AS modified_admin_username
507        FROM " . $auth->getParam('db_table') . "
508        LEFT JOIN " . $auth->getParam('db_table') . " a1 ON (" . $auth->getParam('db_table') . ".added_by_user_id = a1." . $auth->getParam('db_primary_key') . ")
509        LEFT JOIN " . $auth->getParam('db_table') . " a2 ON (" . $auth->getParam('db_table') . ".modified_by_user_id = a2." . $auth->getParam('db_primary_key') . ")
510        $where_clause
511        " . $so->getSortOrderSQL() . "
512        " . $page->getLimitSQL() . "
513    ";
514
515    // Use a cash hash to determine if the result-set has changed.
516    // A unique key for this query, with the total_items in case db records
517    // were added since the last cache. This identifies a unique set of
518    // cached data, but we must refer to the list that is cached by a more
519    // generic name. so that we can flush the cache (if records updated)
520    // without knowing the hash.
521    $cache_hash = md5($sql . '|' . $page->total_items);
522    if ($tmp_prefs->get('cache_hash') != $cache_hash) {
523        $cache->delete('list');
524        $tmp_prefs->set('cache_hash', $cache_hash);
525    }
526
527    // First try to return from the cache.
528    if ($cache->exists('list')) {
529        $list = $cache->get('list');
530        return $list;
531    }
532   
533    // The list was not cached, so issue the real query.
534    $qid = $db->query($sql);
535    while ($row = mysql_fetch_assoc($qid)) {
536        $list[] = $row;
537    }
538
539    // Save this list into the cache.
540    if (isset($list) && !empty($list)) {
541        $cache->set('list', $list);
542    }
543
544    return $list;
545}
546
547?>
Note: See TracBrowser for help on using the repository browser.