source: trunk/services/admins.php @ 137

Last change on this file since 137 was 137, checked in by scdev, 18 years ago

Q - Renamed SessionCache? to Cache, RecordVersion? to Version, and RecordLock? to Lock

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