source: trunk/services/admins.php @ 677

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