requireAdminLogin() ->setPageTitle(WT_I18N::translate('User administration')); require_once WT_ROOT.'includes/functions/functions_edit.php'; // Valid values for form variables $ALL_ACTIONS=array('cleanup', 'cleanup2', 'createform', 'createuser', 'deleteuser', 'listusers', 'loadrows', 'load1row'); $ALL_THEMES_DIRS=array(); foreach (get_theme_names() as $themename=>$themedir) { $ALL_THEME_DIRS[]=$themedir; } $ALL_EDIT_OPTIONS=array( 'none' => /* I18N: Listbox entry; name of a role */ WT_I18N::translate('Visitor'), 'access'=> /* I18N: Listbox entry; name of a role */ WT_I18N::translate('Member'), 'edit' => /* I18N: Listbox entry; name of a role */ WT_I18N::translate('Editor'), 'accept'=> /* I18N: Listbox entry; name of a role */ WT_I18N::translate('Moderator'), 'admin' => /* I18N: Listbox entry; name of a role */ WT_I18N::translate('Manager') ); // Form actions $action =safe_GET('action', $ALL_ACTIONS, 'listusers'); $usrlang =safe_POST('usrlang', array_keys(WT_I18N::installed_languages())); $username =safe_POST('username', WT_REGEX_USERNAME); $filter =safe_POST('filter', WT_REGEX_NOSCRIPT); $ged =safe_POST('ged', WT_REGEX_NOSCRIPT); // Extract form variables $realname =safe_POST('realname' ); $pass1 =safe_POST('pass1', WT_REGEX_PASSWORD); $pass2 =safe_POST('pass2', WT_REGEX_PASSWORD); $emailaddress =safe_POST('emailaddress', WT_REGEX_EMAIL); $user_theme =safe_POST('user_theme', $ALL_THEME_DIRS); $user_language =safe_POST('user_language', array_keys(WT_I18N::installed_languages()), WT_LOCALE); $new_contact_method=safe_POST('new_contact_method'); $new_comment =safe_POST('new_comment', WT_REGEX_UNSAFE); $new_auto_accept =safe_POST_bool('new_auto_accept'); $canadmin =safe_POST_bool('canadmin'); $visibleonline =safe_POST_bool('visibleonline'); $editaccount =safe_POST_bool('editaccount'); $verified =safe_POST_bool('verified'); $verified_by_admin =safe_POST_bool('verified_by_admin'); // Load all available gedcoms $all_gedcoms = get_all_gedcoms(); //-- sorting by gedcom filename asort($all_gedcoms); switch ($action) { case 'deleteuser': // Delete a user - but don't delete ourselves! $username=safe_GET('username'); $user_id=get_user_id($username); if ($user_id && $user_id!=WT_USER_ID) { delete_user($user_id); AddToLog("deleted user ->{$username}<-", 'auth'); } $action='listusers'; break; case 'loadrows': // Generate an AJAX/JSON response for datatables to load a block of rows $sSearch=safe_GET('sSearch'); $WHERE=" WHERE u.user_id>0"; $ARGS=array(); if ($sSearch) { $WHERE.= " AND (". " user_name LIKE CONCAT('%', ?, '%') OR " . " real_name LIKE CONCAT('%', ?, '%') OR " . " email LIKE CONCAT('%', ?, '%'))"; $ARGS=array($sSearch, $sSearch, $sSearch); } else { } $iDisplayStart =(int)safe_GET('iDisplayStart'); $iDisplayLength=(int)safe_GET('iDisplayLength'); set_user_setting(WT_USER_ID, 'admin_users_page_size', $iDisplayLength); if ($iDisplayLength>0) { $LIMIT=" LIMIT " . $iDisplayStart . ',' . $iDisplayLength; } else { $LIMIT=""; } $iSortingCols=(int)safe_GET('iSortingCols'); if ($iSortingCols) { $ORDER_BY=' ORDER BY '; for ($i=0; $i<$iSortingCols; ++$i) { // Datatables numbers columns 0, 1, 2, ... // MySQL numbers columns 1, 2, 3, ... switch (safe_GET('sSortDir_'.$i)) { case 'asc': $ORDER_BY.=(1+(int)safe_GET('iSortCol_'.$i)).' ASC '; break; case 'desc': $ORDER_BY.=(1+(int)safe_GET('iSortCol_'.$i)).' DESC '; break; } if ($i<$iSortingCols-1) { $ORDER_BY.=','; } } } else { $ORDER_BY=''; } $sql= "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS '', u.user_id, user_name, real_name, email, '', us1.setting_value, us2.setting_value, us2.setting_value, us3.setting_value, us3.setting_value, us4.setting_value, us5.setting_value". " FROM `##user` u". " LEFT JOIN `##user_setting` us1 ON (u.user_id=us1.user_id AND us1.setting_name='language')". " LEFT JOIN `##user_setting` us2 ON (u.user_id=us2.user_id AND us2.setting_name='reg_timestamp')". " LEFT JOIN `##user_setting` us3 ON (u.user_id=us3.user_id AND us3.setting_name='sessiontime')". " LEFT JOIN `##user_setting` us4 ON (u.user_id=us4.user_id AND us4.setting_name='verified')". " LEFT JOIN `##user_setting` us5 ON (u.user_id=us5.user_id AND us5.setting_name='verified_by_admin')". $WHERE. $ORDER_BY. $LIMIT; // This becomes a JSON list, not array, so need to fetch with numeric keys. $aaData=WT_DB::prepare($sql)->execute($ARGS)->fetchAll(PDO::FETCH_NUM); // Reformat various columns for display foreach ($aaData as &$aData) { $aData[0]=' '; // $aData[1] is the user ID $user_id =$aData[1]; $user_name=$aData[2]; $aData[2]=edit_field_inline('user-user_name-'.$user_id, $aData[2]); $aData[3]=edit_field_inline('user-real_name-'.$user_id, $aData[3]); $aData[4]=edit_field_inline('user-email-'. $user_id, $aData[4]); // $aData[5] is a link to an email icon if ($user_id != WT_USER_ID) { $aData[5]=''; } $aData[6]=edit_field_language_inline('user_setting-'.$user_id.'-language', $aData[6]); // $aData[7] is the sortable registration timestamp $aData[8]=format_timestamp($aData[8]); if (date("U") - $aData[7] > 604800 && !$aData[11]) { $aData[8]=''.$aData[8].''; } // $aData[9] is the sortable last-login timestamp if ($aData[9]) { $aData[10]=format_timestamp($aData[9]).'
'.WT_I18N::time_ago(time() - $aData[9]); } else { $aData[10]=WT_I18N::translate('Never'); } $aData[11]=edit_field_yes_no_inline('user_setting-'.$user_id.'-verified-', $aData[11]); $aData[12]=edit_field_yes_no_inline('user_setting-'.$user_id.'-verified_by_admin-', $aData[12]); // Add extra column for "delete" action if ($user_id != WT_USER_ID) { $aData[13]='
'; } else { // Do not delete ourself! $aData[13]=''; } } // Total filtered/unfiltered rows $iTotalDisplayRecords=WT_DB::prepare("SELECT FOUND_ROWS()")->fetchOne(); $iTotalRecords=WT_DB::prepare("SELECT SQL_CACHE COUNT(*) FROM `##user` WHERE user_id>0")->fetchOne(); Zend_Session::writeClose(); header('Content-type: application/json'); echo json_encode(array( // See http://www.datatables.net/usage/server-side 'sEcho' =>(int)safe_GET('sEcho'), 'iTotalRecords' =>$iTotalRecords, 'iTotalDisplayRecords'=>$iTotalDisplayRecords, 'aaData' =>$aaData )); exit; case 'load1row': // Generate an AJAX response for datatables to load expanded row $user_id=(int)safe_GET('user_id'); Zend_Session::writeClose(); header('Content-type: text/html; charset=UTF-8'); echo '

', WT_I18N::translate('Details'), '

'; echo '
'; echo '
', WT_I18N::translate('Administrator'), '
'; echo '
', edit_field_yes_no_inline('user_setting-'.$user_id.'-canadmin', get_user_setting($user_id, 'canadmin')), '
'; echo '
', WT_I18N::translate('Password'), '
'; echo '
', edit_field_inline('user-password-'.$user_id, ''), '
'; echo '
', WT_I18N::translate('Preferred contact method'), '
'; echo '
', edit_field_contact_inline('user_setting-'.$user_id.'-contactmethod', get_user_setting($user_id, 'contactmethod')), '
'; echo '
', WT_I18N::translate('Allow this user to edit his account information'), '
'; echo '
', edit_field_yes_no_inline('user_setting-'.$user_id.'-editaccount', get_user_setting($user_id, 'editaccount')), '
'; echo '
', WT_I18N::translate('Automatically approve changes made by this user'), '
'; echo '
', edit_field_yes_no_inline('user_setting-'.$user_id.'-auto_accept', get_user_setting($user_id, 'auto_accept')), '
'; echo '
', WT_I18N::translate('Theme'), '
'; echo '
', select_edit_control_inline('user_setting-'.$user_id.'-theme', array_flip(get_theme_names()), WT_I18N::translate(''), get_user_setting($user_id, 'theme')), '
'; echo '
', WT_I18N::translate('Visible to other users when online'), '
'; echo '
', edit_field_yes_no_inline('user_setting-'.$user_id.'-visibleonline', get_user_setting($user_id, 'visibleonline')), '
'; echo '
', WT_I18N::translate('Comments'), '
'; echo '
', edit_field_inline('user_setting-'.$user_id.'-comment', get_user_setting($user_id, 'comment')), '
'; echo '
', WT_I18N::translate('My page'), '
'; echo '
', WT_I18N::translate('Change the blocks on this page'), '
'; echo '
'; // Column One - details echo '
', '

', WT_I18N::translate('Family tree access and settings'), '

', '', '', '', '', '', '', ''; foreach ($all_gedcoms as $ged_id=>$ged_name) { echo ''; } echo '
', WT_I18N::translate('Family tree'), '', WT_I18N::translate('Default individual'), help_link('default_individual'), '', WT_I18N::translate('Individual record'), help_link('useradmin_gedcomid'), '', WT_I18N::translate('Role'), help_link('role'), '', WT_I18N::translate('Restrict to immediate family'), help_link('RELATIONSHIP_PATH_LENGTH'), '
', WT_I18N::translate('%s', get_gedcom_setting($ged_id, 'title')), //Pedigree root person '', // TODO: autocomplete/find/etc. for this field edit_field_inline('user_gedcom_setting-'.$user_id.'-'.$ged_id.'-rootid', get_user_gedcom_setting($user_id, $ged_id, 'rootid')), '', // TODO: autocomplete/find/etc. for this field edit_field_inline('user_gedcom_setting-'.$user_id.'-'.$ged_id.'-gedcomid', get_user_gedcom_setting($user_id, $ged_id, 'gedcomid')), '', select_edit_control_inline('user_gedcom_setting-'.$user_id.'-'.$ged_id.'-canedit', $ALL_EDIT_OPTIONS, null, get_user_gedcom_setting($user_id, $ged_id, 'canedit', 'none')), '', select_edit_control_inline('user_gedcom_setting-'.$user_id.'-'.$ged_id.'-RELATIONSHIP_PATH_LENGTH', array(0=>WT_I18N::translate('no'), 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 10=>10), null, get_user_gedcom_setting($user_id, $ged_id, 'RELATIONSHIP_PATH_LENGTH', '0')), '
'; exit; } $controller->pageHeader(); // Pass 1 - perform action updates switch ($action) { case 'createuser': if (get_user_id($username)) { echo '
', WT_I18N::translate('Duplicate user name. A user with that user name already exists. Please choose another user name.'), '
'; $action='createform'; } elseif (get_user_by_email($emailaddress)) { echo '
', WT_I18N::translate('Duplicate email address. A user with that email already exists.'), '
'; $action='createform'; } elseif ($pass1!=$pass2) { echo '
', WT_I18N::translate('Passwords do not match.'), '
'; $action='createform'; } else { // Create new uers $user_id=create_user($username, $realname, $emailaddress, $pass1); set_user_setting($user_id, 'reg_timestamp', date('U')); set_user_setting($user_id, 'sessiontime', '0'); setUserFullName ($user_id, $realname); setUserEmail ($user_id, $emailaddress); set_user_setting($user_id, 'theme', $user_theme); set_user_setting($user_id, 'language', $user_language); set_user_setting($user_id, 'contactmethod', $new_contact_method); set_user_setting($user_id, 'comment', $new_comment); set_user_setting($user_id, 'auto_accept', $new_auto_accept); set_user_setting($user_id, 'canadmin', $canadmin); set_user_setting($user_id, 'visibleonline', $visibleonline); set_user_setting($user_id, 'editaccount', $editaccount); set_user_setting($user_id, 'verified', $verified); set_user_setting($user_id, 'verified_by_admin', $verified_by_admin); foreach ($all_gedcoms as $ged_id=>$ged_name) { set_user_gedcom_setting($user_id, $ged_id, 'gedcomid', safe_POST_xref('gedcomid'.$ged_id)); set_user_gedcom_setting($user_id, $ged_id, 'rootid', safe_POST_xref('rootid'.$ged_id)); set_user_gedcom_setting($user_id, $ged_id, 'canedit', safe_POST('canedit'.$ged_id, array_keys($ALL_EDIT_OPTIONS))); if (safe_POST_xref('gedcomid'.$ged_id)) { set_user_gedcom_setting($user_id, $ged_id, 'RELATIONSHIP_PATH_LENGTH', safe_POST_integer('RELATIONSHIP_PATH_LENGTH'.$ged_id, 0, 10, 0)); } else { // Do not allow a path length to be set if the individual ID is not set_user_gedcom_setting($user_id, $ged_id, 'RELATIONSHIP_PATH_LENGTH', null); } } AddToLog("User ->{$username}<- created", 'auth'); $action='listusers'; } } // Pass 2 - display page switch ($action) { case 'createform': if (get_gedcom_count()==1) { //Removed becasue it doesn't work here for multiple GEDCOMs. Can be reinstated when fixed (https://bugs.launchpad.net/webtrees/+bug/613235) $controller->addExternalJavascript(WT_STATIC_URL.'js/autocomplete.js'); } init_calendar_popup(); $controller->addInlineJavascript(' function checkform(frm) { if (frm.username.value=="") { alert("'.WT_I18N::translate('You must enter a user name.').'"); frm.username.focus(); return false; } if (frm.realname.value=="") { alert("'.WT_I18N::translate('You must enter a real name.').'"); frm.realname.focus(); return false; } if (frm.pass1.value=="") { alert("'.WT_I18N::translate('You must enter a password.').'"); frm.pass1.focus(); return false; } if (frm.emailaddress.value=="") { alert("'.WT_I18N::translate('You must enter an email address.').'"); frm.emailaddress.focus(); return false; } if (frm.pass2.value=="") { alert("'.WT_I18N::translate('You must confirm the password.').'"); frm.pass2.focus(); return false; } if (frm.pass1.value.length < 6) { alert("'.WT_I18N::translate('Passwords must contain at least 6 characters.').'"); frm.pass1.value = ""; frm.pass2.value = ""; frm.pass1.focus(); return false; } return true; } var pastefield; function paste_id(value) { pastefield.value=value; } jQuery(".relpath").change(function() { var fieldIDx = jQuery(this).attr("id"); var idNum = fieldIDx.replace("RELATIONSHIP_PATH_LENGTH",""); var newIDx = "gedcomid"+idNum; if (jQuery("#"+newIDx).val()=="") { alert("'.addslashes(WT_I18N::translate('You must specify an individual record before you can restrict the user to their immediate family.')).'"); jQuery(this).val(""); } }); '); ?>
$ged_name) { echo '', '', //Pedigree root person '', // GEDCOM INDI Record ID '', '', //Relationship path '', ''; } ?>
', WT_I18N::translate('%s', get_gedcom_setting($ged_id, 'title')), ''; $varname='rootid'.$ged_id; echo ' ', print_findindi_link($varname), ''; $varname='gedcomid'.$ged_id; echo ' ', print_findindi_link($varname), ''; $varname='canedit'.$ged_id; echo '', ''; $varname = 'RELATIONSHIP_PATH_LENGTH'.$ged_id; echo '', '
"; echo ""; ?> $user_name) { $userName = getUserFullName($user_id); if ((int)get_user_setting($user_id, 'sessiontime') == "0") $datelogin = (int)get_user_setting($user_id, 'reg_timestamp'); else $datelogin = (int)get_user_setting($user_id, 'sessiontime'); if ((mktime(0, 0, 0, (int)date("m")-$month, (int)date("d"), (int)date("Y")) > $datelogin) && get_user_setting($user_id, 'verified') && get_user_setting($user_id, 'verified_by_admin')) { ?>$user_name) { if (((date("U") - (int)get_user_setting($user_id, 'reg_timestamp')) > 604800) && !get_user_setting($user_id, 'verified')) { $userName = getUserFullName($user_id); ?>$user_name) { if (!get_user_setting($user_id, 'verified_by_admin') && get_user_setting($user_id, 'verified')) { $userName = getUserFullName($user_id); ?>"; } ?>
", WT_I18N::translate('Number of months since the last login for a user\'s account to be considered inactive: '), "
", $userName, "

", WT_I18N::translate('User\'s account has been inactive too long: '); echo timestamp_to_gedcom_date($datelogin)->Display(false); $ucnt++; ?>
" value="1">
" value="1">
" value="1">
"; echo WT_I18N::translate('Nothing found to cleanup'), "

0) { ?>  

$user_name) { $var = "del_".str_replace(array(".", "-", " "), array("_", "_", "_"), $user_name); if (safe_POST($var)=='1') { delete_user($user_id); AddToLog("deleted user ->{$user_name}<-", 'auth'); echo WT_I18N::translate('Deleted user: '); echo $user_name, "
"; } else { $tempArray = unserialize(get_user_setting($user_id, 'canedit')); if (is_array($tempArray)) { foreach ($tempArray as $gedid=>$data) { $var = "delg_".str_replace(array(".", "-", " "), "_", $gedid); if (safe_POST($var)=='1' && get_user_gedcom_setting($user_id, $gedid, 'canedit')) { set_user_gedcom_setting($user_id, $gedid, 'canedit', null); echo $gedid, ":  ", WT_I18N::translate('Unset GEDCOM rights for '), $user_name, "
"; } } } $tempArray = unserialize(get_user_setting($user_id, 'rootid')); if (is_array($tempArray)) { foreach ($tempArray as $gedid=>$data) { $var = "delg_".str_replace(array(".", "-", " "), "_", $gedid); if (safe_POST($var)=='1' && get_user_gedcom_setting($user_id, $gedid, 'rootid')) { set_user_gedcom_setting($user_id, $gedid, 'rootid', null); echo $gedid, ":  ", WT_I18N::translate('Unset root ID for '), $user_name, "
"; } } } $tempArray = unserialize(get_user_setting($user_id, 'gedcomid')); if (is_array($tempArray)) { foreach ($tempArray as $gedid=>$data) { $var = "delg_".str_replace(array(".", "-", " "), "_", $gedid); if (safe_POST($var)=='1' && get_user_gedcom_setting($user_id, $gedid, 'gedcomid')) { set_user_gedcom_setting($user_id, $gedid, 'gedcomid', null); echo $gedid, ":  ", WT_I18N::translate('Unset GEDCOM ID for '), $user_name, "
"; } } } } } break; case 'listusers': default: echo '', '', '', '', '', '', '', '', '', /* COLSPAN does not work? */ '', '', '', '', '', '', '', '', '', '', '', '', '
user-id ', WT_I18N::translate('Username'), '', WT_I18N::translate('Real name'), '', WT_I18N::translate('Email'), ' ', WT_I18N::translate('Language'), ' date_registered ', WT_I18N::translate('Date registered'), ' last_login ', WT_I18N::translate('Last logged in'), '', WT_I18N::translate('Verified'), '', WT_I18N::translate('Approved'), '
'; $controller ->addExternalJavascript(WT_STATIC_URL.'js/jquery/jquery.dataTables.min.js') ->addExternalJavascript(WT_STATIC_URL.'js/jquery/jquery.jeditable.min.js') ->addInlineJavascript(' var oTable = jQuery("#list").dataTable({ "sDom": \'<"H"pf<"dt-clear">irl>t<"F"pl>\', '.WT_I18N::datatablesI18N().', "bProcessing" : true, "bServerSide" : true, "sAjaxSource" : "'.WT_SCRIPT_NAME.'?action=loadrows", "bJQueryUI": true, "bAutoWidth":false, "iDisplayLength": '.get_user_setting(WT_USER_ID, 'admin_users_page_size', 10).', "sPaginationType": "full_numbers", "aaSorting": [[2,"asc"]], "aoColumns": [ /* details */ { bSortable:false, sClass:"icon-open" }, /* user-id */ { bVisible:false }, /* user_name */ null, /* real_name */ null, /* email */ null, /* email link */ { bSortable:false }, /* language */ null, /* registered (sort) */ { bVisible:false }, /* registered */ { iDataSort:7 }, /* last_login (sort) */ { bVisible:false }, /* last_login */ { iDataSort:9 }, /* verified */ { sClass:"center" }, /* approved */ { sClass:"center" }, /* delete */ { bSortable:false } ], "fnDrawCallback": function() { // Our JSON responses include Javascript as well as HTML. This does not get // executed (except for some versions of Firefox?). So, extract it, and add // it to its own DOM element jQuery("#list script").each(function() { var script=document.createElement("script"); jQuery("#list script").appendTo("body"); document.body.appendChild(script); }).remove(); } }); /* When clicking on the +/- icon, we expand/collapse the details block */ jQuery("#list tbody td.icon-close").live("click", function () { var nTr=this.parentNode; jQuery(this).removeClass("icon-close"); oTable.fnClose(nTr); jQuery(this).addClass("icon-open"); }); jQuery("#list tbody td.icon-open").live("click", function () { var nTr=this.parentNode; jQuery(this).removeClass("icon-open"); var aData=oTable.fnGetData(nTr); jQuery.get("'.WT_SCRIPT_NAME.'?action=load1row&user_id="+aData[1], function(data) { oTable.fnOpen(nTr, data, "details"); }); jQuery(this).addClass("icon-close"); }); oTable.fnFilter("'.safe_GET('filter', WT_REGEX_USERNAME).'"); '); break; }