source: trunk/services/admins.php @ 19

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

Rebuilt the services/admins.php script and templates. Fixes since v2 conversion. Lots of bugs and more to come!

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