User Administration Module
This is the development page for the User Administration module. The User Administration module has been committed to the 1.1.6.4 branch and will be available with the 1.1.6.4 release. Documentation http://docs.wikkawiki.org/UserAdministration
This action is meant to allow Wikka Administrators to manage users and perform several maintenance operations.
It displays the standard LastUsers list to non-admins.
See also:
- Are you an administrator of this site ?
Give it a UserAdminTest try
Why?
I've started writing some code for a user administration module. I think this might be interesting for wikka-based projects with a large number of registered users.This action will enable Wikka administrators (or, in the future, users belonging to an Admin group) to have access to several user management functions from a single page:
- Display a pageable, sortable and searchable list of registered users -- done;
- Perform specific actions on single users, like:
- delete users (forthcoming: see this RemovingUsers discussion) -- done as of 1.1.6.4; however, other core changes must be made to recognize users as being deleted
- add users - in case the registration of a page is turned off, but you want to add a user
- noted, good idea -- DarTar
- See DanWestUserReg. Worked for me as intended. I'd say, this function's done --MasinAlDujaili, 2007-05-21
- send user feedback -- done;
- rename users
- If anyone is interested, running through the seven tables and updating every instance of your old wiki name to your new wiki name will effectively change your name throughout the wiki. copied from comment on the homepage. --NilsLindenberg
- manage user privileges (forthcoming);
- Display user's owned pages -- done;
- Display user's comments -- done.
- Display user's changes -- done;
- other...
The code below must be saved as actions/useradmin.php and can be used by adding {{useradmin}} in the body of a page.
Here's a preview of the interface (the email and IP fields are masked for privacy reasons)
sample output
User Administration
Current version
(2005-08-31): 0.5- users can be sorted by different fields (click on table header to reverse sort order), searched and paged;
- if the current user is not an administrator, then the lastuser.php action is displayed
- feedback can be sent to single users.
- displays pages owned by each user.
- displays pages changed by each user.
- displays pages commented by each user.
- added extra column for Signup IP ( installed on this server as a beta feature).
- TrackIPaddressMod for (possible) install on 'your' server
- added constants, UI strings and a bunch of configurable options including styling options (see below).
Files needed
(2004-09-16):- actions/useradmin.php: see code on this page;
- FeedbackActionUpgrade actions/userfeedback.php (enhanced version of FeedbackAction); 2005-04-18 - action parameter support added
- UserPagesAction actions/userpages.php (enhanced version of mypages.php);2005-04-18 - action parameter support added
- UserChangesAction actions/userchanges.php (enhanced version of mychanges.php); 2005-04-18 - action parameter support added
- UserCommentsAction actions/usercomments.php (new action); 2004-11-23 - RewriteRules bug fixed
To do
- mass-operations;
- deleting/banning users;
- integrate with other admin modules.
The code
actions/useradmin.php
Note: this action uses the ipaddress field that has been added as a beta antispam feature to this server. Lines relative to this field have been commented out in the code to allow installation on a native wikka package
The code has also been adapted to take advantage of the WikkaCountingRecords getCount() method, which is required for the action to work.
- <?php
- /**
- * Display a module for user management.
- *
- * This action allows admins to display information on registered users.
- * Users can be searched, paged, filtered. User-related statistics are given,
- * showing the number of commented, created and modified pages. A feedback
- * handler allows admins to send an email to single users. If the current user
- * is not an administrator, then the lastuser action is displayed instead.
- *
- * @package Actions
- * @name Useradmin
- *
- * @author {@link http://wikka.jsnx.com/DarTar Dario Taraborelli}
- * @version 0.5
- * @since Wikka 1.1.X.X
- *
- * @input integer $colcolor optional: enables color for statistics columns
- * 1: enables colored columns;
- * 0: disables colored columns;
- * default: 1;
- * @input integer $rowcolor optional: enables alternate row colors
- * 1: enables colored rows;
- * 0: disables colored rows;
- * default: 1;
- *
- * @output A list of users registered on the current server.
- *
- * @todo
- * - mass-operations;
- * - deleting/banning users;
- * - integrate with other admin modules.
- */
- //utilities
- /**
- * Build an array of numbers consisting of 'ranges' with increasing step size in each 'range'.
- *
- * A list of numbers like this is useful for instance for a dropdown to choose
- * a period expressed in number of days: a difference between 2 and 5 days may
- * be significant while that between 92 and 95 may not be.
- *
- * @author {@link http://wikka.jsnx.com/JavaWoman JavaWoman}
- * @copyright Copyright (c) 2005, Marjolein Katsma
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- * @version 1.0
- *
- * @param mixed $limits required: single integer or array of integers;
- * defines the upper limits of the ranges as well as the next step size
- * @param int $max required: upper limit for the whole list
- * (will be included if smaller than the largest limit)
- * @param int $firstinc optional: increment for the first range; default 1
- * @return array resulting list of numbers
- */
- // utilities
- function optionRanges($limits, $max, $firstinc = 1)
- {
- // initializations
- if ($firstinc < 1) $firstinc = 1;
- $inc = $firstinc;
- // first element is the first increment
- $opts[] = $inc;
- // each $limit is the upper limit of a 'range'
- foreach ($limits as $limit)
- {
- for ($i = $inc + $inc; $i <= $limit && $i < $max; $i += $inc)
- {
- $opts[] = $i;
- }
- // we quit at $max, even if there are more $limit elements
- if ($limit >= $max)
- {
- // add $max to the list; then break out of the loop
- $opts[] = $max;
- break;
- }
- // when $limit is reached, it becomes the new start and increment for the next 'range'
- $inc = $limit;
- }
- return $opts;
- }
- // restrict access to admins
- if ($this->IsAdmin($this->GetUser())) {
- // -------------------------------------
- // set default values as constants
- // -------------------------------------
- // User-interface: icons
- // -------------------------------------
- // User-interface: strings
- //initialize row & column colors variables
- $r = 1; #initialize row counter
- $r_color = ALTERNATE_ROW_COLOR; #get alternate row color option
- $c_color = STAT_COLUMN_COLOR; #get column color option
- // record dropdown
- // pager
- $prev = '';
- $next = '';
- //override defaults with action parameters
- {
- foreach ($vars as $param => $value)
- {
- switch ($param)
- {
- case 'colcolor':
- break;
- case 'rowcolor':
- break;
- }
- }
- }
- //perform actions if required
- if ($_GET['action'] == 'feedback' || $_REQUEST['mail'])
- {
- echo $this->Action('userfeedback');
- }
- elseif ($_GET['action'] == 'owned')
- {
- echo $this->Action('userpages');
- }
- elseif ($_GET['action'] == 'changes')
- {
- echo $this->Action('userchanges');
- }
- elseif ($_GET['action'] == 'comments')
- {
- echo $this->Action('usercomments');
- }
- else
- {
- // process URL variables
- # JW 2005-07-19 some modifications to avoid notices but these are still not actually secure
- // number of records per page
- $l = $_POST['l'];
- $l = $_GET['l'];
- else
- $l = DEFAULT_RECORDS_LIMIT;
- // sort field
- // sort order
- // start record
- // search string
- $q = $_POST['q'];
- $q = $_GET['q'];
- else
- $q = DEFAULT_SEARCH;
- // select all
- $checked = '';
- {
- $checked = (1 == $_GET['selectall']) ? ' checked="checked"' : '';
- }
- // restrict MySQL query by search string
- $where = ('' == $q) ? "1" : "`name` LIKE '%".$q."%'";
- // get total number of users
- $numusers = $this->getCount('users', $where);
- // print page header
- echo $this->Format('==== '.PAGE_TITLE.' ==== --- ');
- // build pager form
- $form = $this->FormOpen('','','post','user_admin_panel');
- $form .= '<fieldset><legend>'.FORM_LEGEND.'</legend>'."\n";
- $form .= '<label for="q">'.FORM_SEARCH_STRING_LABEL.'</label> <input type ="text" id="q" name="q" title="'.FORM_SEARCH_STRING_TITLE.'" size="20" maxlength="50" value="'.$q.'"/> <input type="submit" value="'.FORM_SEARCH_SUBMIT.'" /><br />'."\n";
- // ranged drop-down
- $users_opts = optionRanges($user_limits,$numusers,DEFAULT_MIN_RECORDS_DISPLAY);
- $form .= '<label for="l">'.FORM_PAGER_LABEL_BEFORE.'</label> '."\n";
- $form .= '<select name="l" id="l" title="'.FORM_PAGER_TITLE.'">'."\n";
- // build drop-down
- foreach ($users_opts as $opt) {
- $selected = ($opt == $l) ? ' selected="selected"' : '';
- $form .= '<option value="'.$opt.'"'.$selected.'>'.$opt.'</option>'."\n";
- }
- $form .= '</select> <label for="l">'.FORM_PAGER_LABEL_AFTER.'</label> <input type="submit" value="'.FORM_PAGER_SUBMIT.'" /><br />'."\n";
- // build pager links
- if ($s > 0)
- $prev = '<a href="' .$this->Href('','','l='.$l.'&sort='.$sort.'&d='.$d.'&s='.($s-$l)).'&q='.$q.'" title="'.sprintf(FORM_PAGER_LINK, ($s-$l+1), $s).'">'.($s-$l+1).'-'.$s.'</a> | '."\n";
- if ($numusers > ($s + $l))
- $next = ' | <a href="'.$this->Href('','','l='.$l.'&sort='.$sort.'&d='.$d.'&s='.($s+$l)).'&q='.$q.'" title="'.sprintf(FORM_PAGER_LINK, ($s+$l+1), ($s+2*$l)).'">'.($s+$l+1).'-'.($s+2*$l).'</a>'."\n";
- $form .= FORM_RESULT_INFO.' ('.$numusers.'): '.$prev.($s+1).'-'.($s+$l).$next.'<br />'."\n";
- $form .= '('.FORM_RESULT_SORTED_BY.'<em>'.$sort.', '.$d.'</em>)'."\n";
- $form .= '</fieldset>'.$this->FormClose()."\n";
- // print form
- echo $form;
- // get user list
- $userdata = $this->LoadAll("SELECT * FROM ".$this->config["table_prefix"]."users WHERE ".
- $where." ORDER BY ".$sort." ".$d." limit ".$s.", ".$l);
- if ($userdata) {
- // build header links
- $nameheader = '<a href="'.$this->Href('','', (($sort == 'name' && $d == 'asc')? 'l='.$l.'&sort=name&d=desc' : 'l='.$l.'&sort=name&d=asc')).'" title="'.TABLE_HEADING_USERNAME_TITLE.'">'.TABLE_HEADING_USERNAME.'</a>';
- $emailheader = '<a href="'.$this->Href('','', (($sort == 'email' && $d == 'asc')? 'l='.$l.'&sort=email&d=desc' : 'l='.$l.'&sort=email&d=asc')).'" title="'.TABLE_HEADING_EMAIL_TITLE.'">'.TABLE_HEADING_EMAIL.'</a>';
- $timeheader = '<a href="'.$this->Href('','', (($sort == 'signuptime' && $d == 'desc')? 'l='.$l.'&sort=signuptime&d=asc' : 'l='.$l.'')).'" title="'.TABLE_HEADING_SIGNUPTIME_TITLE.'">'.TABLE_HEADING_SIGNUPTIME.'</a>';
- /*$ipheader = '<a href="'.$this->Href('','', (($sort == 'ipaddress' && $d == 'desc')? 'l='.$l.'&sort=ipaddress&d=asc' : 'l='.$l.'&sort=ipaddress&d=desc')).'" title="'.TABLE_HEADING_SIGNUPIP_TITLE.'">'.TABLE_HEADING_SIGNUPIP.'</a>'; # installed as beta feature at wikka.jsnx.com */
- // build table headers
- $htmlout = "<table summary=\"".TABLE_SUMMARY."\" border=\"1px\" id=\"admin_table\">\n<thead>\n".
- " <tr>\n".
- " <th> </th>\n".
- " <th>".$nameheader."</th>\n".
- " <th>".$emailheader."</th>\n".
- " <th>".$timeheader."</th>\n".
- /* " <th>".$ipheader."</th>\n". # installed as beta feature at wikka.jsnx.com */
- " <th class=\"number ".(($c_color == 1)? ' c1' : '')."\" title=\"".TABLE_HEADING_OWNED_TITLE."\">;<img src=\"".OWNED_ICON."\" alt=\"O\"/></th>\n".
- " <th class=\"number ".(($c_color == 1)? ' c2' : '')."\" title=\"".TABLE_HEADING_EDITS_TITLE."\"><img src=\"".EDITS_ICON."\" alt=\"E\"/></th>\n".
- " <th class=\"number ".(($c_color == 1)? ' c3' : '')."\" title=\"".TABLE_HEADING_COMMENTS_TITLE."\"><img src=\"".COMMENTS_ICON."\" alt=\"C\"/></th>\n".
- " <th class=\"center\">Actions</th>\n".
- " </tr>\n</thead>\n";
- // print user table
- foreach($userdata as $user) {
- // get counts
- $where_owned = "`owner` = '".$user['name']."' AND latest = 'Y'";
- $where_changes = "`user` = '".$user['name']."'";
- $where_comments = "`user` = '".$user['name']."'";
- $numowned = $this->getCount('pages', $where_owned);
- $numchanges = $this->getCount('pages', $where_changes);
- $numcomments = $this->getCount('comments', $where_comments);
- // build statistics links if needed
- $ownedlink = ($numowned > 0)? '<a title="'.sprintf(TABLE_CELL_OWNED_TITLE,$user['name'],$numowned).'" href="'.$this->Href('','','user='.$user['name'].'&action=owned').'">'.$numowned.'</a>' : '0';
- $changeslink = ($numchanges > 0)? '<a title="'.sprintf(TABLE_CELL_EDITS_TITLE,$user['name'],$numchanges).'" href="'.$this->Href('','','user='.$user['name'].'&action=changes').'">'.$numchanges.'</a>' : '0';
- $commentslink = ($numcomments > 0)? '<a title="'.sprintf(TABLE_CELL_COMMENTS_TITLE,$user['name'],$numcomments).'" href="'.$this->Href('','','user='.$user['name'].'&action=comments').'">'.$numcomments.'</a>' : '0';
- // build handler links
- $deleteuser = '<a title="'.sprintf(ACTION_DELETE_LINK_TITLE, $user['name']).'" href="'.$this->Href('','','user='.$user['name'].'&action=delete').'">'.ACTION_DELETE_LINK.'</a>';
- $feedbackuser = '<a title="'.sprintf(ACTION_FEEDBACK_LINK_TITLE, $user['name']).'" href="'.$this->Href('','','user='.$user['name'].'&action=feedback').'">'.ACTION_FEEDBACK_LINK.'</a>';
- // build table body
- $htmlout .= "<tbody>\n";
- if ($r_color == 1) {
- $htmlout .= "<tr ".(($r%2)? '' : 'class="alt"').">\n"; #enable alternate row color
- } else {
- $htmlout .= "<tr>\n"; #disable alternate row color
- }
- $htmlout .= " <td><input type=\"checkbox\" id=\"".$user['id']."\"".$checked." title=\"".sprintf(SELECT_RECORD_TITLE,$user['name'])."\"/></td>\n".
- " <td>".(($this->ExistsPage($user['name']))? $this->Link($user['name']) : $user['name'])."</td>\n". #check if userpage exists
- " <td>".$user['email']."</td>\n".
- " <td class=\"time\">".$user['signuptime']."</td>\n".
- /* " <td>".$user['ipaddress']."</td>\n". # installed as beta feature at wikka.jsnx.com */
- " <td class=\"number".(($c_color == 1)? ' c1' : '')."\">".$ownedlink."</td>\n". #set column color
- " <td class=\"number".(($c_color == 1)? ' c2' : '')."\">".$changeslink."</td>\n". #set column color
- " <td class=\"number".(($c_color == 1)? ' c3' : '')."\">".$commentslink."</td>\n". #set column color
- " <td class=\"center\">".$deleteuser." :: ".$feedbackuser."</td>\n";
- $htmlout .= " </tr>\n</tbody>\n";
- //increase row counter ----- alternate row colors
- if ($r_color == 1) $r++;
- }
- $htmlout .= "</table>\n";
- // print the table
- echo $this->FormOpen('','','get');
- echo $htmlout;
- // multiple-user operations (forthcoming) JW 2005-07-19 accesskey removed (causes more problems than it solves)
- echo '<fieldset><legend>'.FORM_MASSACTION_LEGEND.'</legend>';
- echo '[<a href="'.$this->Href('','','l='.$l.'&sort='.$sort.'&d='.$d.'&s='.$s.'&q='.$q.'&selectall=1').'" title="'.CHECK_ALL_TITLE.'">'.CHECK_ALL.'</a> | <a href="'.$this->Href('','','l='.$l.'&sort='.$sort.'&d='.$d.'&s='.$s.'&q='.$q.'&selectall=0').'" title="'.UNCHECK_ALL_TITLE.'">'.UNCHECK_ALL.'</a>]<br />';
- echo '<label for="action" >'.FORM_MASSACTION_LABEL.'</label> <select title="'.FORM_MASSACTION_SELECT_TITLE.'" id="action" name="action">';
- echo '<option value="" selected="selected">---</option>';
- echo '<option value="massdelete">'.FORM_MASSACTION_OPT_DELETE.'</option>';
- echo '<option value="massfeedback">'.FORM_MASSACTION_OPT_FEEDBACK.'</option>';
- echo '</select> <input type="submit" value="'.FORM_MASSACTION_SUBMIT.'" />';
- echo '</fieldset>';
- echo $this->FormClose();
- }
- else
- {
- // no records matching the search string: print error message
- }
- }
- } else {
- // user is not admin
- echo $this->Action('lastusers');
- }
- ?>
New CSS classes
The styling of the tables requires a bunch of TableStyling new CSS classes.
Styling options
The useradmin action accepts two optional styling parameters:
colcolor
Enables color for statistics columns
1: enables colored columns (default);
0: disables colored columns;
rowcolor
Enables alternate row colors
1: enables colored rows (default);
0: disables colored rows;
The following examples show how the table is rendered using these two parameters:
No styling: {{useradmin colcolor="0" rowcolor="0"}}
User Name | Signup Time | Signup IP | Actions | |||||
---|---|---|---|---|---|---|---|---|
HypeXR | [email protected] | 2005-08-01 09:01:54 | XX.XX.XX.XX | 1 | 2 | 1 | delete :: feedback | |
WiebTest | [email protected] | 2005-07-31 19:35:26 | XX.XX.XX.XX | 0 | 0 | 0 | delete :: feedback | |
DennyShimkoski | [email protected] | 2005-07-31 00:22:58 | XX.XX.XX.XX | 6 | 38 | 1 | delete :: feedback |
Alternate rows only: {{useradmin colcolor="0"}}
User Name | Signup Time | Signup IP | Actions | |||||
---|---|---|---|---|---|---|---|---|
HypeXR | [email protected] | 2005-08-01 09:01:54 | XX.XX.XX.XX | 1 | 2 | 1 | delete :: feedback | |
WiebTest | [email protected] | 2005-07-31 19:35:26 | XX.XX.XX.XX | 0 | 0 | 0 | delete :: feedback | |
DennyShimkoski | [email protected] | 2005-07-31 00:22:58 | XX.XX.XX.XX | 6 | 38 | 1 | delete :: feedback |
Colored columns only: {{useradmin rowcolor="0"}}
User Name | Signup Time | Signup IP | Actions | |||||
---|---|---|---|---|---|---|---|---|
HypeXR | [email protected] | 2005-08-01 09:01:54 | XX.XX.XX.XX | 1 | 2 | 1 | delete :: feedback | |
WiebTest | [email protected] | 2005-07-31 19:35:26 | XX.XX.XX.XX | 0 | 0 | 0 | delete :: feedback | |
DennyShimkoski | [email protected] | 2005-07-31 00:22:58 | XX.XX.XX.XX | 6 | 38 | 1 | delete :: feedback |
Alternate rows and colored columns: {{useradmin}}
User Name | Signup Time | Signup IP | Actions | |||||
---|---|---|---|---|---|---|---|---|
HypeXR | [email protected] | 2005-08-01 09:01:54 | XX.XX.XX.XX | 1 | 2 | 1 | delete :: feedback | |
WiebTest | [email protected] | 2005-07-31 19:35:26 | XX.XX.XX.XX | 0 | 0 | 0 | delete :: feedback | |
DennyShimkoski | [email protected] | 2005-07-31 00:22:58 | XX.XX.XX.XX | 6 | 38 | 1 | delete :: feedback |
CategoryDevelopmentActions CategoryDevelopmentAdmin