Ejemplo n.º 1
0
 /**
  * Implement user searching with SQL
  *
  * NOTE: user with ID zero should never be returned
  *
  * @param string  The query string
  * @param integer How many results to return
  * @param integer What result to start at (0 == first result)
  * @param data    Filters the users searched by
  *                can contain:
  *             'group' => integer, // only users in this group
  *             'owner' => boolean  // include the group ownwer (only if group is set)
  *             'exclude'=> int     // excludes a user
  * @return array  A data structure containing results looking like ...
  *         $results = array(
  *               count   => integer, // total number of results
  *               limit   => integer, // how many results are returned
  *               offset  => integer, // starting from which result
  *               data    => array(   // the result records
  *                   array(
  *                       id            => integer,
  *                       username      => string,
  *                       institution   => string,
  *                       firstname     => string,
  *                       lastname      => string,
  *                       preferredname => string,
  *                       email         => string,
  *                   ),
  *                   array(
  *                       id            => integer,
  *                       username      => string,
  *                       institution   => string,
  *                       firstname     => string,
  *                       lastname      => string,
  *                       preferredname => string,
  *                       email         => string,
  *                   ),
  *                   array(...),
  *               ),
  *           );
  */
 public static function search_user($query_string, $limit, $offset = 0, $data = array())
 {
     safe_require('artefact', 'internal');
     $publicfields = array_keys(ArtefactTypeProfile::get_public_fields());
     if (empty($publicfields)) {
         $publicfields = array('preferredname');
     }
     if (is_postgres()) {
         return self::search_user_pg($query_string, $limit, $offset, $data, $publicfields);
     } else {
         if (is_mysql()) {
             return self::search_user_my($query_string, $limit, $offset, $data, $publicfields);
         } else {
             throw new SQLException('search_user() is not implemented for your database engine (' . get_config('dbtype') . ')');
         }
     }
 }
/**
 * Given a query string and limits, return an array of matching users using the
 * search plugin defined in config.php
 *
 * @param string  The query string
 * @param integer How many results to return
 * @param integer What result to start at (0 == first result)
 * @return array  A data structure containing results looking like ...
 *         $results = array(
 *               count   => integer, // total number of results
 *               limit   => integer, // how many results are returned
 *               offset  => integer, // starting from which result
 *               results => array(   // the result records
 *                   array(
 *                       id            => integer,
 *                       username      => string,
 *                       institution   => string,
 *                       firstname     => string,
 *                       lastname      => string,
 *                       preferredname => string,
 *                       email         => string,
 *                   ),
 *                   array(
 *                       id            => integer,
 *                       username      => string,
 *                       institution   => string,
 *                       firstname     => string,
 *                       lastname      => string,
 *                       preferredname => string,
 *                       email         => string,
 *                   ),
 *                   array(...),
 *               ),
 *           );
 */
function search_user($query_string, $limit, $offset = 0, $data = array())
{
    $plugin = get_config('searchplugin');
    safe_require('search', $plugin);
    safe_require('artefact', 'internal');
    $publicfields = array_keys(ArtefactTypeProfile::get_public_fields());
    if (empty($publicfields)) {
        $publicfields = array('preferredname');
    }
    $fieldlist = "('" . join("','", $publicfields) . "')";
    $results = call_static_method(generate_class_name('search', $plugin), 'search_user', $query_string, $limit, $offset, $data);
    if ($results['data']) {
        $userlist = '(' . join(',', array_map(create_function('$u', 'return (int)$u[\'id\'];'), $results['data'])) . ')';
        $public_fields = get_records_sql_array('
            SELECT 
                u.id, a.artefacttype, a.title
            FROM
                {usr} u
                LEFT JOIN {artefact} a ON u.id=a.owner AND a.artefacttype IN ' . $fieldlist . '
            WHERE
                u.id IN ' . $userlist . '
            ORDER BY u.firstname, u.lastname, u.id, a.artefacttype', array());
        $public_fields_byuser = array();
        if (!empty($public_fields)) {
            foreach ($public_fields as $field) {
                // This will be null if the user does not have a field marked public
                if ($field->artefacttype !== null) {
                    $public_fields_byuser[$field->id][$field->artefacttype] = $field->title;
                }
            }
        }
        foreach ($results['data'] as &$result) {
            $result['name'] = display_name($result);
            if (isset($public_fields_byuser[$result['id']])) {
                foreach ($public_fields_byuser[$result['id']] as $field => $value) {
                    $result[$field] = $value;
                }
            }
            if (isset($result['country'])) {
                $result['country'] = get_string('country.' . $result['country']);
            }
        }
    }
    return $results;
}
Ejemplo n.º 3
0
define('SECTION_PAGE', 'social');
define('INTERNAL_SUBPAGE', 'social');
require_once dirname(dirname(dirname(__FILE__))) . '/init.php';
define('TITLE', get_string('profile', 'artefact.internal'));
require_once 'pieforms/pieform.php';
safe_require('artefact', 'internal');
if (!get_record('blocktype_installed', 'active', 1, 'name', 'socialprofile')) {
    // This block type is not installed. The user is not allowed in this form.
    throw new AccessDeniedException(get_string('accessdenied', 'error'));
}
$id = param_integer('id', 0);
$delete = param_integer('delete', 0);
if ($delete) {
    // Check if social profile is a mandatory system field
    // and if this is the last field, they can't delete it.
    $mandatory_fields = ArtefactTypeProfile::get_mandatory_fields();
    if (isset($mandatory_fields['socialprofile'])) {
        $social_profiles = ArtefactTypeSocialprofile::get_social_profiles();
        if (count($social_profiles) <= 1) {
            // they can't delete.
            $SESSION->add_error_msg(get_string('socialprofilerequired', 'artefact.internal'));
            redirect('/artefact/internal/index.php?fs=social');
        }
    }
    $todelete = new ArtefactTypeSocialprofile($id);
    if (!$USER->can_edit_artefact($todelete)) {
        throw new AccessDeniedException(get_string('accessdenied', 'error'));
    }
    $deleteform = array('name' => 'deleteprofileform', 'plugintype' => 'artefact', 'pluginname' => 'internal', 'renderer' => 'div', 'elements' => array('submit' => array('type' => 'submitcancel', 'class' => 'btn-default', 'value' => array(get_string('deleteprofile', 'artefact.internal'), get_string('cancel')), 'goto' => get_config('wwwroot') . '/artefact/internal/index.php?fs=social')));
    $form = pieform($deleteform);
    $message = get_string('deleteprofileconfirm', 'artefact.internal');
Ejemplo n.º 4
0
 /**
  * Returns a snippet of an sql WHERE clause to filter users whose (visible)
  * names match the terms in a given query string.
  */
 function name_search_sql($query_string, $usralias = 'u', $usrprefalias = 'h')
 {
     safe_require('artefact', 'internal');
     // Get the list of searchable profile fields from the internal artefact
     $required = array_keys(ArtefactTypeProfile::get_always_searchable_fields());
     $optional = array_diff(array_keys(ArtefactTypeProfile::get_searchable_fields()), $required);
     $required[] = 'username';
     // Not a profile field, but used in the search query.
     // Get a list of match expressions to use in the WHERE clause
     $matches = new StdClass();
     foreach (array_merge($required, $optional) as $f) {
         $matches->{$f} = self::match_user_field_expression($f, $usralias);
     }
     $querydata = self::split_query_string(strtolower(trim($query_string)));
     $hidenameallowed = get_config('userscanhiderealnames') ? 'TRUE' : 'FALSE';
     $searchusernamesallowed = get_config('searchusernames') ? 'TRUE' : 'FALSE';
     $termsql = "{$matches->preferredname}\n                    OR (\n                        ({$usralias}.preferredname IS NULL OR {$usralias}.preferredname = '' OR NOT {$hidenameallowed} OR {$usrprefalias}.value != '1' OR {$usrprefalias}.value IS NULL)\n                        AND ({$matches->firstname} OR {$matches->lastname})\n                    )\n                    OR ({$searchusernamesallowed} AND {$matches->username})";
     if ($optional) {
         foreach ($optional as $f) {
             $termsql .= "\n                    OR {$matches->{$f}}";
         }
     }
     $where = '';
     $values = array();
     foreach ($querydata as $term) {
         $where .= '
             AND (
                 ' . $termsql . '
             )';
         $values = array_pad($values, count($values) + 4 + count($optional), $term);
     }
     return array($where, $values);
 }
function institution_submit(Pieform $form, $values)
{
    global $SESSION, $institution, $add, $instancearray, $USER, $authinstances;
    db_begin();
    // Update the basic institution record...
    $newinstitution = new StdClass();
    if ($add) {
        $institution = $newinstitution->name = strtolower($values['name']);
    }
    $newinstitution->displayname = $values['displayname'];
    $newinstitution->authplugin = empty($values['authplugin']) ? null : $values['authplugin'];
    if (get_config('usersuniquebyusername')) {
        // Registering absolutely not allowed when this setting is on, it's a
        // security risk. See the documentation for the usersuniquebyusername
        // setting for more information
        $newinstitution->registerallowed = 0;
    } else {
        $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0;
    }
    $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme'];
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null;
            $newinstitution->expiry = db_format_timestamp($values['expiry']);
        }
    }
    if (!empty($values['authplugin'])) {
        $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']);
        if (array_diff($allinstances, $instancearray)) {
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
        }
        if (array_diff($instancearray, $allinstances)) {
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
        }
        foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
                throw new SystemException('Attempt to update AND delete an auth instance');
            }
            $record = new StdClass();
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record, array('id' => $instanceid));
        }
        foreach ($values['authplugin']['deletearray'] as $instanceid) {
            // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record.
            $hostwwwroot = null;
            foreach ($authinstances as $ai) {
                if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') {
                    $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid));
                    if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) {
                        // Unfortunately, it's possible that this host record could belong to a different institution,
                        // so specify the institution here.
                        delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution);
                        // We really need to fix this, either by removing the institution from the host table, or refusing to allow the
                        // institution to be changed in the host record when another institution's authinstance is still pointing at it.
                    }
                    break;
                }
            }
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
        }
    }
    if ($add) {
        insert_record('institution', $newinstitution);
        // If registration has been turned on, then we automatically insert an
        // internal authentication authinstance
        if ($newinstitution->registerallowed) {
            $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal');
            insert_record('auth_instance', $authinstance);
        }
    } else {
        $where = new StdClass();
        $where->name = $institution;
        $oldtheme = get_field('institution', 'theme', 'name', $institution);
        update_record('institution', $newinstitution, $where);
    }
    delete_records('institution_locked_profile_field', 'name', $institution);
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
        if ($values[$field]) {
            $profilefield = new StdClass();
            $profilefield->name = $institution;
            $profilefield->profilefield = $field;
            insert_record('institution_locked_profile_field', $profilefield);
        }
    }
    db_commit();
    if ($add) {
        if ($newinstitution->registerallowed) {
            // If registration is not allowed, then an authinstance will not
            // have been created, and thus cause the institution page to add
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
        $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution);
    } else {
        $message = get_string('institutionupdatedsuccessfully', 'admin');
        if (isset($values['theme']) && $oldtheme != $values['theme'] && (!empty($oldtheme) || $values['theme'] != 'sitedefault')) {
            $USER->update_theme();
            $message .= '  ' . get_string('usersseenewthemeonlogin', 'admin');
        }
        $SESSION->add_ok_msg($message);
        $nexturl = '/admin/users/institutions.php';
    }
    redirect($nexturl);
}
Ejemplo n.º 6
0
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
 *
 */
define('INTERNAL', 1);
define('MENUITEM', 'profile/edit');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'internal');
define('SECTION_PAGE', 'index');
require dirname(dirname(dirname(__FILE__))) . '/init.php';
define('TITLE', get_string('editprofile', 'artefact.internal'));
require_once 'pieforms/pieform.php';
safe_require('artefact', 'internal');
$fieldset = param_alpha('fs', 'aboutme');
$element_list = call_static_method('ArtefactTypeProfile', 'get_all_fields');
$element_data = ArtefactTypeProfile::get_field_element_data();
$element_required = call_static_method('ArtefactTypeProfile', 'get_mandatory_fields');
// load existing profile information
$profilefields = array();
$profile_data = get_records_select_array('artefact', "owner=? AND artefacttype IN (" . join(",", array_map(create_function('$a', 'return db_quote($a);'), array_keys($element_list))) . ")", array($USER->get('id')));
if ($profile_data) {
    foreach ($profile_data as $field) {
        $profilefields[$field->artefacttype] = $field->title;
    }
}
$lockedfields = locked_profile_fields();
$profilefields['email'] = array();
$profilefields['email']['all'] = get_records_array('artefact_internal_profile_email', 'owner', $USER->get('id'));
$profilefields['email']['validated'] = array();
$profilefields['email']['unvalidated'] = array();
$profilefields['email']['unsent'] = array();
Ejemplo n.º 7
0
/**
 * Checks that all the required fields are set, and handles setting them if required.
 *
 * Checks whether the current user needs to change their password, and handles
 * the password changing if it's required.
 */
function auth_check_required_fields()
{
    global $USER, $SESSION;
    if (defined('NOCHECKREQUIREDFIELDS')) {
        return;
    }
    $changepassword = true;
    $elements = array();
    if (!$USER->get('passwordchange') || $USER->get('parentuser') && $USER->get('loginanyway') || defined('NOCHECKPASSWORDCHANGE')) {
        $changepassword = false;
    }
    // Check if the user wants to log in anyway
    if ($USER->get('passwordchange') && $USER->get('parentuser') && isset($_GET['loginanyway'])) {
        $USER->loginanyway = true;
        $changepassword = false;
    }
    // Do not force password change on JSON request.
    if (defined('JSON') && JSON == true) {
        $changepassword = false;
    }
    if ($changepassword) {
        $authobj = AuthFactory::create($USER->authinstance);
        if ($authobj->changepasswordurl) {
            redirect($authobj->changepasswordurl);
            exit;
        }
        if (method_exists($authobj, 'change_password')) {
            if ($SESSION->get('resetusername')) {
                $elements['username'] = array('type' => 'text', 'defaultvalue' => $USER->get('username'), 'title' => get_string('changeusername', 'account'), 'description' => get_string('changeusernamedesc', 'account', hsc(get_config('sitename'))));
            }
            $elements['password1'] = array('type' => 'password', 'title' => get_string('newpassword') . ':', 'description' => get_string('yournewpassword'), 'rules' => array('required' => true));
            $elements['password2'] = array('type' => 'password', 'title' => get_string('confirmpassword') . ':', 'description' => get_string('yournewpasswordagain'), 'rules' => array('required' => true));
            $elements['country'] = array('type' => 'select', 'title' => "Country", 'options' => array("ca" => "Canada", "us" => "United States"), 'defaultvalue' => "us", 'description' => "Country", 'rules' => array('required' => true));
            $elements['state'] = array('type' => 'select', 'title' => "State", 'options' => array('AL' => "Alabama", 'AK' => "Alaska", 'AZ' => "Arizona", 'AR' => "Arkansas", 'CA' => "California", 'CO' => "Colorado", 'CT' => "Connecticut", 'DE' => "Delaware", 'DC' => "District of Columbia", 'FL' => "Florida", 'GA' => "Georgia", 'HI' => "Hawaii", 'ID' => "Idaho", 'IL' => "Illinois", 'IN' => "Indiana", 'IA' => "Iowa", 'KS' => "Kansas", 'KY' => "Kentucky", 'LA' => "Louisiana", 'ME' => "Maine", 'MD' => "Maryland", 'MA' => "Massachusetts", 'MI' => "Michigan", 'MN' => "Minnesota", 'MS' => "Mississippi", 'MO' => "Missouri", 'MT' => "Montana", 'NE' => "Nebraska", 'NV' => "Nevada", 'NH' => "New Hampshire", 'NJ' => "New Jersey", 'NM' => "New Mexico", 'NY' => "New York", 'NC' => "North Carolina", 'ND' => "North Dakota", 'OH' => "Ohio", 'OK' => "Oklahoma", 'OR' => "Oregon", 'PA' => "Pennsylvania", 'RI' => "Rhode Island", 'SC' => "South Carolina", 'SD' => "South Dakota", 'TN' => "Tennessee", 'TX' => "Texas", 'UT' => "Utah", 'VT' => "Vermont", 'VA' => "Virginia", 'WA' => "Washington", 'WV' => "West Virginia", 'WI' => "Wisconsin", 'WY' => "Wyoming", 'AB' => "Alberta", 'BC' => "British Columbia", 'MB' => "Manitoba", 'NB' => "New Brunswick", 'NL' => "Newfoundland and Labrador", 'NT' => "Northwest Territories", 'NS' => "Nova Scotia", 'NU' => "Nunavut", 'ON' => "Ontario", 'PE' => "Prince Edward Island", 'QC' => "Quebec", 'SK' => "Saskatchewan", 'YT' => "Yukon"), 'description' => "State", 'rules' => array('required' => true));
            $elements['email'] = array('type' => 'text', 'title' => get_string('principalemailaddress', 'artefact.internal'), 'ignore' => trim($USER->get('email')) != '' && !preg_match('/@example\\.org$/', $USER->get('email')), 'rules' => array('required' => true, 'email' => true));
        }
    } else {
        if (defined('JSON')) {
            // Don't need to check this for json requests
            return;
        }
    }
    safe_require('artefact', 'internal');
    require_once 'pieforms/pieform.php';
    $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields());
    foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) {
        // Always mandatory fields are stored in the usr table, so are part of
        // the user session object. We can save a query by grabbing them from
        // the session.
        if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) {
            continue;
        }
        // Not cached? Get value the standard way.
        if (get_profile_field($USER->get('id'), $field) != null) {
            continue;
        }
        if ($field == 'email') {
            if (isset($elements['email'])) {
                continue;
            }
            // Use a text field for their first e-mail address, not the
            // emaillist element
            $type = 'text';
        }
        $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true));
        if ($field == 'socialprofile') {
            $elements[$field] = ArtefactTypeSocialprofile::get_new_profile_elements();
            // add an element to flag that socialprofile is in the list of fields.
            $elements['socialprofile_hidden'] = array('type' => 'hidden', 'value' => 1);
        }
        // @todo ruthlessly stolen from artefact/internal/index.php, could be merged
        if ($type == 'wysiwyg') {
            $elements[$field]['rows'] = 10;
            $elements[$field]['cols'] = 60;
        }
        if ($type == 'textarea') {
            $elements[$field]['rows'] = 4;
            $elements[$field]['cols'] = 60;
        }
        if ($field == 'country') {
            $elements[$field]['options'] = getoptions_country();
            $elements[$field]['defaultvalue'] = get_config('country');
        }
        if ($field == 'email') {
            // Check if a validation email has been sent
            if (record_exists('artefact_internal_profile_email', 'owner', $USER->get('id'))) {
                $elements['email']['type'] = 'html';
                $elements['email']['value'] = get_string('validationprimaryemailsent', 'auth');
                $elements['email']['disabled'] = true;
                $elements['email']['rules'] = array('required' => false);
            } else {
                $elements[$field]['rules']['email'] = true;
                $elements[$field]['description'] = get_string('primaryemaildescription', 'auth');
            }
        }
    }
    if (empty($elements)) {
        // No mandatory fields that aren't set
        return;
    }
    if (count($elements) == 1 && isset($elements['email']) && $elements['email']['type'] == 'html') {
        // Display a message if there is only 1 required field and this field is email whose validation has been sent
        $elements['submit'] = array('type' => 'submit', 'value' => get_string('continue', 'admin'));
        $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => get_config('wwwroot') . '?logout', 'elements' => $elements));
    } else {
        $elements['submit'] = array('type' => 'submit', 'value' => get_string('submit'));
        $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements));
    }
    $smarty = smarty();
    if ($USER->get('parentuser')) {
        $smarty->assign('loginasoverridepasswordchange', get_string('loginasoverridepasswordchange', 'admin', '<a class="btn" href="' . get_config('wwwroot') . '?loginanyway">', '</a>'));
    }
    $smarty->assign('changepassword', $changepassword);
    $smarty->assign('changeusername', $SESSION->get('resetusername'));
    $smarty->assign('form', $form);
    $smarty->display('requiredfields.tpl');
    exit;
}
Ejemplo n.º 8
0
define('INSTITUTIONALADMIN', 1);
define('MENUITEM', 'configusers/uploadcsv');
require dirname(dirname(dirname(__FILE__))) . '/init.php';
define('TITLE', get_string('uploadcsv', 'admin'));
require_once 'pieforms/pieform.php';
require_once 'institution.php';
require_once 'phpmailer/class.phpmailer.php';
safe_require('artefact', 'internal');
raise_memory_limit("512M");
// Turn on autodetecting of line endings, so mac newlines (\r) will work
ini_set('auto_detect_line_endings', 1);
$FORMAT = array();
$specialcases = array('username', 'password', 'remoteuser');
// Don't upload social profiles for now. A user can have multiple profiles. Not sure how to put that in a csv.
$notallowed = array('socialprofile');
$ALLOWEDKEYS = array_keys(ArtefactTypeProfile::get_all_fields());
$ALLOWEDKEYS = array_diff($ALLOWEDKEYS, $notallowed);
$maildisabled = array_search('maildisabled', $ALLOWEDKEYS);
unset($ALLOWEDKEYS[$maildisabled]);
$ALLOWEDKEYS = array_merge($ALLOWEDKEYS, $specialcases);
$UPDATES = array();
// During validation, remember which users already exist
$INSTITUTIONNAME = array();
// Mapping from institution id to display name
if ($USER->get('admin')) {
    $authinstances = auth_get_auth_instances();
} else {
    $admininstitutions = $USER->get('admininstitutions');
    $authinstances = auth_get_auth_instances_for_institutions($admininstitutions);
    if (empty($authinstances)) {
        $SESSION->add_info_msg(get_string('configureauthplugin', 'admin'));
Ejemplo n.º 9
0
 public static function rebuild_users()
 {
     log_debug('Starting rebuild_users()');
     self::delete_bytype('user');
     $users = get_recordset('usr', 'deleted', '0');
     safe_require('artefact', 'internal');
     $publicfields = array_keys(ArtefactTypeProfile::get_public_fields());
     while ($user = $users->FetchRow()) {
         if ($user['id'] == 0) {
             continue;
         }
         self::index_user($user);
     }
     $users->close();
     log_debug('Completed rebuild_users()');
 }
Ejemplo n.º 10
0
/**
 * Checks that all the required fields are set, and handles setting them if required.
 */
function auth_check_required_fields()
{
    global $USER;
    if (defined('JSON')) {
        // Don't need to check this for json requests
        return;
    }
    safe_require('artefact', 'internal');
    require_once 'pieforms/pieform.php';
    $elements = array();
    $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields());
    foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) {
        // Always mandatory fields are stored in the usr table, so are part of
        // the user session object. We can save a query by grabbing them from
        // the session.
        if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) {
            continue;
        }
        // Not cached? Get value the standard way.
        if (get_profile_field($USER->get('id'), $field) != null) {
            continue;
        }
        if ($field == 'email') {
            // Use a text field for their first e-mail address, not the
            // emaillist element
            $type = 'text';
        }
        $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true));
        // @todo ruthlessly stolen from artefact/internal/index.php, could be merged
        if ($type == 'wysiwyg') {
            $elements[$field]['rows'] = 10;
            $elements[$field]['cols'] = 60;
        }
        if ($type == 'textarea') {
            $elements[$field]['rows'] = 4;
            $elements[$field]['cols'] = 60;
        }
        if ($field == 'country') {
            $elements[$field]['options'] = getoptions_country();
            $elements[$field]['defaultvalue'] = 'nz';
        }
        if ($field == 'email') {
            $elements[$field]['rules']['email'] = true;
        }
    }
    if (empty($elements)) {
        // No mandatory fields that aren't set
        return;
    }
    $elements['submit'] = array('type' => 'submit', 'value' => get_string('submit'));
    $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements));
    $smarty = smarty();
    $smarty->assign('form', $form);
    $smarty->display('requiredfields.tpl');
    exit;
}
Ejemplo n.º 11
0
/**
 * Checks that all the required fields are set, and handles setting them if required.
 *
 * Checks whether the current user needs to change their password, and handles
 * the password changing if it's required.
 */
function auth_check_required_fields()
{
    global $USER, $SESSION;
    $changepassword = true;
    $elements = array();
    if (!$USER->get('passwordchange') || $USER->get('parentuser') && $USER->get('loginanyway') || defined('NOCHECKPASSWORDCHANGE')) {
        $changepassword = false;
    }
    // Check if the user wants to log in anyway
    if ($USER->get('passwordchange') && $USER->get('parentuser') && isset($_GET['loginanyway'])) {
        $USER->loginanyway = true;
        $changepassword = false;
    }
    if ($changepassword) {
        $authobj = AuthFactory::create($USER->authinstance);
        if ($authobj->changepasswordurl) {
            redirect($authobj->changepasswordurl);
            exit;
        }
        if (method_exists($authobj, 'change_password')) {
            if ($SESSION->get('resetusername')) {
                $elements['username'] = array('type' => 'text', 'defaultvalue' => $USER->get('username'), 'title' => get_string('changeusername', 'account'), 'description' => get_string('changeusernamedesc', 'account', hsc(get_config('sitename'))));
            }
            $elements['password1'] = array('type' => 'password', 'title' => get_string('newpassword') . ':', 'description' => get_string('yournewpassword'), 'rules' => array('required' => true));
            $elements['password2'] = array('type' => 'password', 'title' => get_string('confirmpassword') . ':', 'description' => get_string('yournewpasswordagain'), 'rules' => array('required' => true));
            $elements['email'] = array('type' => 'text', 'title' => get_string('principalemailaddress', 'artefact.internal'), 'ignore' => trim($USER->get('email')) != '' && !preg_match('/@example\\.org$/', $USER->get('email')), 'rules' => array('required' => true, 'email' => true));
        }
    } else {
        if (defined('JSON')) {
            // Don't need to check this for json requests
            return;
        }
    }
    safe_require('artefact', 'internal');
    require_once 'pieforms/pieform.php';
    $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields());
    foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) {
        // Always mandatory fields are stored in the usr table, so are part of
        // the user session object. We can save a query by grabbing them from
        // the session.
        if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) {
            continue;
        }
        // Not cached? Get value the standard way.
        if (get_profile_field($USER->get('id'), $field) != null) {
            continue;
        }
        if ($field == 'email') {
            if (isset($elements['email'])) {
                continue;
            }
            // Use a text field for their first e-mail address, not the
            // emaillist element
            $type = 'text';
        }
        $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true));
        // @todo ruthlessly stolen from artefact/internal/index.php, could be merged
        if ($type == 'wysiwyg') {
            $elements[$field]['rows'] = 10;
            $elements[$field]['cols'] = 60;
        }
        if ($type == 'textarea') {
            $elements[$field]['rows'] = 4;
            $elements[$field]['cols'] = 60;
        }
        if ($field == 'country') {
            $elements[$field]['options'] = getoptions_country();
            $elements[$field]['defaultvalue'] = get_config('country');
        }
        if ($field == 'email') {
            $elements[$field]['rules']['email'] = true;
        }
    }
    if (empty($elements)) {
        // No mandatory fields that aren't set
        return;
    }
    $elements['submit'] = array('type' => 'submit', 'value' => get_string('submit'));
    $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements));
    $smarty = smarty();
    if ($USER->get('parentuser')) {
        $smarty->assign('loginasoverridepasswordchange', get_string('loginasoverridepasswordchange', 'admin', '<a href="' . get_config('wwwroot') . '?loginanyway">', '</a>'));
    }
    $smarty->assign('changepassword', $changepassword);
    $smarty->assign('changeusername', $SESSION->get('resetusername'));
    $smarty->assign('form', $form);
    $smarty->display('requiredfields.tpl');
    exit;
}
Ejemplo n.º 12
0
/**
 * The CSV file is parsed here so validation errors can be returned to the
 * user. The data from a successful parsing is stored in the <var>$CVSDATA</var>
 * array so it can be accessed by the submit function
 *
 * @param Pieform  $form   The form to validate
 * @param array    $values The values submitted
 */
function uploadcsv_validate(Pieform $form, $values)
{
    global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER;
    // Don't even start attempting to parse if there are previous errors
    if ($form->has_errors()) {
        return;
    }
    if ($values['file']['size'] == 0) {
        $form->set_error('file', $form->i18n('rule', 'required', 'required', array()));
        return;
    }
    require_once 'pear/File.php';
    require_once 'pear/File/CSV.php';
    // Don't be tempted to use 'explode' here. There may be > 1 underscore.
    $break = strpos($values['authinstance'], '_');
    $authinstance = substr($values['authinstance'], 0, $break);
    $institution = substr($values['authinstance'], $break + 1);
    if (!$USER->can_edit_institution($institution)) {
        $form->set_error('authinstance', get_string('notadminforinstitution', 'admin'));
        return;
    }
    $usernames = array();
    $emails = array();
    $conf = File_CSV::discoverFormat($values['file']['tmp_name']);
    $i = 0;
    while ($line = File_CSV::readQuoted($values['file']['tmp_name'], $conf)) {
        $i++;
        if (!is_array($line)) {
            // Note: the CSV parser returns true on some errors and false on
            // others! Yes that's retarded. No I didn't write it :(
            $form->set_error('file', get_string('uploadcsverrorincorrectnumberoffields', 'admin', $i));
            return;
        }
        // Get the format of the file
        if ($i == 1) {
            foreach ($line as &$potentialkey) {
                $potentialkey = trim($potentialkey);
                if (!in_array($potentialkey, $ALLOWEDKEYS)) {
                    $form->set_error('file', get_string('uploadcsverrorinvalidfieldname', 'admin', $potentialkey));
                    return;
                }
            }
            // Now we know all of the field names are valid, we need to make
            // sure that the required fields are included
            $mandatoryfields = array('username', 'password');
            $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields()));
            if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) {
                $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields);
            }
            // Add in the locked profile fields for this institution
            foreach ($mandatoryfields as $field) {
                if (!in_array($field, $line)) {
                    $form->set_error('file', get_string('uploadcsverrorrequiredfieldnotspecified', 'admin', $field));
                    return;
                }
            }
            // The format line is valid
            $FORMAT = $line;
            log_info('FORMAT:');
            log_info($FORMAT);
        } else {
            // Trim non-breaking spaces -- they get left in place by File_CSV
            foreach ($line as &$field) {
                $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field);
            }
            // We have a line with the correct number of fields, but should validate these fields
            // Note: This validation should really be methods on each profile class, that way
            // it can be used in the profile screen as well.
            $formatkeylookup = array_flip($FORMAT);
            $username = $line[$formatkeylookup['username']];
            $password = $line[$formatkeylookup['password']];
            $email = $line[$formatkeylookup['email']];
            $authobj = AuthFactory::create($authinstance);
            if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) {
                $form->set_error('file', get_string('uploadcsverrorinvalidusername', 'admin', $i));
                return;
            }
            if (record_exists_select('usr', 'LOWER(username) = ?', strtolower($username)) || isset($usernames[strtolower($username)])) {
                $form->set_error('file', get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username));
                return;
            }
            if (record_exists('usr', 'email', $email) || isset($emails[$email])) {
                $form->set_error('file', get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
            }
            // Note: only checks for valid form are done here, none of the checks
            // like whether the password is too easy. The user is going to have to
            // change their password on first login anyway.
            if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
                $form->set_error('file', get_string('uploadcsverrorinvalidpassword', 'admin', $i));
                return;
            }
            $usernames[strtolower($username)] = 1;
            $emails[$email] = 1;
            // All OK!
            $CSVDATA[] = $line;
        }
    }
    if ($i == 1) {
        // There was only the title row :(
        $form->set_error('file', get_string('uploadcsverrornorecords', 'admin'));
        return;
    }
    if ($CSVDATA === null) {
        // Oops! Couldn't get CSV data for some reason
        $form->set_error('file', get_string('uploadcsverrorunspecifiedproblem', 'admin'));
    }
}
Ejemplo n.º 13
0
function institution_submit(Pieform $form, $values)
{
    global $SESSION, $institution, $add, $instancearray, $USER;
    db_begin();
    // Update the basic institution record...
    $newinstitution = new StdClass();
    if ($add) {
        $institution = $newinstitution->name = strtolower($values['name']);
    }
    $newinstitution->displayname = $values['displayname'];
    $newinstitution->expiry = db_format_timestamp($values['expiry']);
    $newinstitution->authplugin = empty($values['authplugin']) ? null : $values['authplugin'];
    if (get_config('usersuniquebyusername')) {
        // Registering absolutely not allowed when this setting is on, it's a
        // security risk. See the documentation for the usersuniquebyusername
        // setting for more information
        $newinstitution->registerallowed = 0;
    } else {
        $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0;
    }
    $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme'];
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null;
        }
    }
    if (!empty($values['authplugin'])) {
        $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']);
        if (array_diff($allinstances, $instancearray)) {
            // TODO wrong exception type
            throw new Exception('Attempt to delete or update another institution\'s auth instance');
        }
        if (array_diff($instancearray, $allinstances)) {
            // TODO wrong exception type
            throw new Exception('One of your instances is unaccounted for in this transaction');
        }
        foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
                // TODO wrong exception type
                throw new Exception('Attempt to update AND delete an auth instance');
            }
            $record = new StdClass();
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record, array('id' => $instanceid));
        }
        foreach ($values['authplugin']['deletearray'] as $instanceid) {
            execute_sql('UPDATE {usr} SET lastauthinstance = NULL WHERE lastauthinstance = ?', array($instanceid));
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
        }
    }
    if ($add) {
        insert_record('institution', $newinstitution);
        // If registration has been turned on, then we automatically insert an
        // internal authentication authinstance
        if ($newinstitution->registerallowed) {
            $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal');
            insert_record('auth_instance', $authinstance);
        }
    } else {
        $where = new StdClass();
        $where->name = $institution;
        $oldtheme = get_field('institution', 'theme', 'name', $institution);
        update_record('institution', $newinstitution, $where);
    }
    delete_records('institution_locked_profile_field', 'name', $institution);
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
        if ($values[$field]) {
            $profilefield = new StdClass();
            $profilefield->name = $institution;
            $profilefield->profilefield = $field;
            insert_record('institution_locked_profile_field', $profilefield);
        }
    }
    db_commit();
    if ($add) {
        if ($newinstitution->registerallowed) {
            // If registration is not allowed, then an authinstance will not
            // have been created, and thus cause the institution page to add
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
        $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution);
    } else {
        $message = get_string('institutionupdatedsuccessfully', 'admin');
        if (isset($values['theme']) && $oldtheme != $values['theme'] && (!empty($oldtheme) || $values['theme'] != 'sitedefault')) {
            $message .= '  ' . get_string('usersseenewthemeonlogin', 'admin');
        }
        $SESSION->add_ok_msg($message);
        $nexturl = '/admin/users/institutions.php';
    }
    redirect($nexturl);
}
Ejemplo n.º 14
0
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
 *
 */
define('INTERNAL', 1);
define('MENUITEM', 'content/profile');
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'internal');
define('SECTION_PAGE', 'index');
require dirname(dirname(dirname(__FILE__))) . '/init.php';
define('TITLE', get_string('profile', 'artefact.internal'));
require_once 'pieforms/pieform.php';
safe_require('artefact', 'internal');
$fieldset = param_alpha('fs', 'aboutme');
$element_list = ArtefactTypeProfile::get_all_fields();
$element_data = ArtefactTypeProfile::get_field_element_data();
$element_required = ArtefactTypeProfile::get_mandatory_fields();
// load existing profile fields
$profilefields = array();
$profile_data = get_records_select_array('artefact', "owner=? AND artefacttype IN (" . join(",", array_map(create_function('$a', 'return db_quote($a);'), array_keys($element_list))) . ")", array($USER->get('id')));
if ($profile_data) {
    foreach ($profile_data as $field) {
        $profilefields[$field->artefacttype] = $field->title;
    }
}
$lockedfields = locked_profile_fields();
$profilefields['email'] = array();
$profilefields['email']['all'] = get_records_array('artefact_internal_profile_email', 'owner', $USER->get('id'));
$profilefields['email']['validated'] = array();
$profilefields['email']['unvalidated'] = array();
$profilefields['email']['unsent'] = array();
if ($profilefields['email']['all']) {
Ejemplo n.º 15
0
 /**
  * Implement user searching with SQL
  *
  * NOTE: user with ID zero should never be returned
  *
  * @param string  The query string
  * @param integer How many results to return
  * @param integer What result to start at (0 == first result)
  * @param data    Filters the users searched by
  *                can contain:
  *             'group' => integer, // only users in this group
  *             'owner' => boolean  // include the group ownwer (only if group is set)
  *             'exclude'=> int     // excludes a user
  * @return array  A data structure containing results looking like ...
  *         $results = array(
  *               count   => integer, // total number of results
  *               limit   => integer, // how many results are returned
  *               offset  => integer, // starting from which result
  *               data    => array(   // the result records
  *                   array(
  *                       id            => integer,
  *                       username      => string,
  *                       institution   => string,
  *                       firstname     => string,
  *                       lastname      => string,
  *                       preferredname => string,
  *                       email         => string,
  *                   ),
  *                   array(
  *                       id            => integer,
  *                       username      => string,
  *                       institution   => string,
  *                       firstname     => string,
  *                       lastname      => string,
  *                       preferredname => string,
  *                       email         => string,
  *                   ),
  *                   array(...),
  *               ),
  *           );
  */
 public static function search_user($query_string, $limit, $offset = 0, $data = array())
 {
     safe_require('artefact', 'internal');
     $publicfields = array_keys(ArtefactTypeProfile::get_public_fields());
     if (empty($publicfields)) {
         $publicfields = array('preferredname');
     }
     $fieldlist = '(' . join(',', array_map('db_quote', $publicfields)) . ')';
     $ilike = db_ilike();
     $data = self::prepare_search_user_options($data);
     $sql = '
         SELECT
             COUNT(DISTINCT u.id)
         FROM {artefact} a
             INNER JOIN {usr} u ON u.id = a.owner';
     if (isset($data['group'])) {
         $groupadminsql = '';
         if (isset($data['includeadmins']) and !$data['includeadmins']) {
             $groupadminsql = " AND gm.role != 'admin'";
         }
         $groupjoin = '
             INNER JOIN {group_member} gm ON
                 (gm.member = u.id AND gm.group = ' . (int) $data['group'] . $groupadminsql . ")\n";
         $sql .= $groupjoin;
     }
     $sql .= "\n                LEFT OUTER JOIN {usr_account_preference} h ON (u.id = h.usr AND h.field = 'hiderealname')";
     $querydata = split(' ', preg_replace('/\\s\\s+/', ' ', strtolower(trim($query_string))));
     $hidenameallowed = get_config('userscanhiderealnames') ? 'TRUE' : 'FALSE';
     $searchusernamesallowed = get_config('searchusernames') ? 'TRUE' : 'FALSE';
     $namesql = "(u.preferredname {$ilike} '%' || ? || '%')\n                    OR ((u.preferredname IS NULL OR u.preferredname = '' OR NOT {$hidenameallowed} OR h.value != '1')\n                        AND (u.firstname {$ilike} '%' || ? || '%' OR u.lastname {$ilike} '%' || ? || '%'))\n                    OR ({$searchusernamesallowed} AND u.username {$ilike} '%' || ? || '%')\n                    OR (a.artefacttype IN {$fieldlist}\n                        AND ( a.title {$ilike} '%' || ? || '%'))";
     $namesql = join('
                 OR ', array_fill(0, count($querydata), $namesql));
     $values = array();
     foreach ($querydata as $w) {
         $values = array_pad($values, count($values) + 5, $w);
     }
     $where = '
         WHERE
             u.id <> 0 AND u.active = 1 AND u.deleted = 0
             AND (
                 ' . $namesql . '
             )
             ' . (isset($data['exclude']) ? 'AND u.id != ' . $data['exclude'] : '') . '
         ';
     $sql .= $where;
     $count = count_records_sql($sql, $values);
     $result = array('count' => $count, 'limit' => $limit, 'offset' => $offset, 'data' => false);
     if ($count < 1) {
         return $result;
     }
     if (is_postgres()) {
         $sql = '
         SELECT DISTINCT ON (' . $data['orderby'] . ')
             u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.staff
         FROM {artefact} a
             INNER JOIN {usr} u ON u.id = a.owner';
     } else {
         if (is_mysql()) {
             // @todo This is quite possibly not correct. See the postgres
             // query. It should be DISTINCT ON the fields as specified by the
             // postgres query. There is a workaround by using SELECT * followed
             // by GROUP BY 1, 2, 3, but it's not really valid SQL. The other
             // way is to rewrite the query using a self join on the usr table.
             $sql = '
         SELECT DISTINCT
             u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.staff
         FROM {artefact} a
             INNER JOIN {usr} u ON u.id = a.owner';
         } else {
             throw new SQLException('search_user() not implemented for your database engine (' . get_config('dbtype') . ')');
         }
     }
     if (isset($data['group'])) {
         $sql .= $groupjoin;
     }
     $sql .= "\n                LEFT OUTER JOIN {usr_account_preference} h ON (u.id = h.usr AND h.field = 'hiderealname')";
     $sql .= $where . '
         ORDER BY ' . $data['orderby'];
     $result['data'] = get_records_sql_array($sql, $values, $offset, $limit);
     if ($result['data']) {
         foreach ($result['data'] as &$item) {
             $item = (array) $item;
         }
     }
     return $result;
 }
Ejemplo n.º 16
0
/**
 * Checks that all the required fields are set, and handles setting them if required.
 *
 * Checks whether the current user needs to change their password, and handles
 * the password changing if it's required.
 */
function auth_check_required_fields()
{
    global $USER, $SESSION;
    if (defined('NOCHECKREQUIREDFIELDS')) {
        return;
    }
    $changepassword = true;
    $elements = array();
    if (!$USER->get('passwordchange') || $USER->get('parentuser') && $USER->get('loginanyway') || defined('NOCHECKPASSWORDCHANGE')) {
        $changepassword = false;
    }
    // Check if the user wants to log in anyway
    if ($USER->get('passwordchange') && $USER->get('parentuser') && isset($_GET['loginanyway'])) {
        $USER->loginanyway = true;
        $changepassword = false;
    }
    // Do not force password change on JSON request.
    if (defined('JSON') && JSON == true) {
        $changepassword = false;
    }
    if ($changepassword) {
        $authobj = AuthFactory::create($USER->authinstance);
        if ($authobj->changepasswordurl) {
            redirect($authobj->changepasswordurl);
            exit;
        }
        if (method_exists($authobj, 'change_password')) {
            if ($SESSION->get('resetusername')) {
                $elements['username'] = array('type' => 'text', 'defaultvalue' => $USER->get('username'), 'title' => get_string('changeusername', 'account'), 'description' => get_string('changeusernamedesc', 'account', hsc(get_config('sitename'))));
            }
            $elements['password1'] = array('type' => 'password', 'title' => get_string('newpassword') . ':', 'description' => get_string('yournewpassword'), 'rules' => array('required' => true));
            $elements['password2'] = array('type' => 'password', 'title' => get_string('confirmpassword') . ':', 'description' => get_string('yournewpasswordagain'), 'rules' => array('required' => true));
            $elements['email'] = array('type' => 'text', 'title' => get_string('principalemailaddress', 'artefact.internal'), 'ignore' => trim($USER->get('email')) != '' && !preg_match('/@example\\.org$/', $USER->get('email')), 'rules' => array('required' => true, 'email' => true));
        }
    } else {
        if (defined('JSON')) {
            // Don't need to check this for json requests
            return;
        }
    }
    safe_require('artefact', 'internal');
    require_once 'pieforms/pieform.php';
    $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields());
    foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) {
        // Always mandatory fields are stored in the usr table, so are part of
        // the user session object. We can save a query by grabbing them from
        // the session.
        if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) {
            continue;
        }
        // Not cached? Get value the standard way.
        if (get_profile_field($USER->get('id'), $field) != null) {
            continue;
        }
        if ($field == 'email') {
            if (isset($elements['email'])) {
                continue;
            }
            // Use a text field for their first e-mail address, not the
            // emaillist element
            $type = 'text';
        }
        $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true));
        if ($field == 'socialprofile') {
            $elements[$field] = ArtefactTypeSocialprofile::get_new_profile_elements();
            // add an element to flag that socialprofile is in the list of fields.
            $elements['socialprofile_hidden'] = array('type' => 'hidden', 'value' => 1);
        }
        // @todo ruthlessly stolen from artefact/internal/index.php, could be merged
        if ($type == 'wysiwyg') {
            $elements[$field]['rows'] = 10;
            $elements[$field]['cols'] = 60;
        }
        if ($type == 'textarea') {
            $elements[$field]['rows'] = 4;
            $elements[$field]['cols'] = 60;
        }
        if ($field == 'country') {
            $elements[$field]['options'] = getoptions_country();
            $elements[$field]['defaultvalue'] = get_config('country');
        }
        if ($field == 'email') {
            // Check if a validation email has been sent
            if (record_exists('artefact_internal_profile_email', 'owner', $USER->get('id'))) {
                $elements['email']['type'] = 'html';
                $elements['email']['value'] = get_string('validationprimaryemailsent', 'auth');
                $elements['email']['disabled'] = true;
                $elements['email']['rules'] = array('required' => false);
            } else {
                $elements[$field]['rules']['email'] = true;
                $elements[$field]['description'] = get_string('primaryemaildescription', 'auth');
            }
        }
    }
    if (empty($elements)) {
        // No mandatory fields that aren't set
        return;
    }
    if (count($elements) == 1 && isset($elements['email']) && $elements['email']['type'] == 'html') {
        // Display a message if there is only 1 required field and this field is email whose validation has been sent
        $elements['submit'] = array('type' => 'submit', 'value' => get_string('continue', 'admin'));
        $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => get_config('wwwroot') . '?logout', 'elements' => $elements));
    } else {
        $elements['submit'] = array('type' => 'submit', 'class' => 'btn-success', 'value' => get_string('submit'));
        $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements, 'dieaftersubmit' => FALSE, 'backoutaftersubmit' => TRUE));
    }
    // Has the form been successfully submitted? Back out and let the requested URL continue.
    if ($form === FALSE) {
        return;
    }
    $smarty = smarty();
    if ($USER->get('parentuser')) {
        $smarty->assign('loginasoverridepasswordchange', get_string('loginasoverridepasswordchange', 'admin', '<a class="" href="' . get_config('wwwroot') . '?loginanyway">', '</a>'));
    }
    $smarty->assign('changepassword', $changepassword);
    $smarty->assign('changeusername', $SESSION->get('resetusername'));
    $smarty->assign('form', $form);
    $smarty->display('requiredfields.tpl');
    exit;
}
Ejemplo n.º 17
0
function institution_submit(Pieform $form, $values)
{
    global $SESSION, $institution, $add, $instancearray, $USER, $authinstances, $customthemedefaults;
    db_begin();
    // Update the basic institution record...
    if ($add) {
        $newinstitution = new Institution();
        $newinstitution->initialise($values['name'], $values['displayname']);
        $institution = $newinstitution->name;
    } else {
        $newinstitution = new Institution($institution);
        $newinstitution->displayname = $values['displayname'];
        $oldinstitution = get_record('institution', 'name', $institution);
        // Clear out any cached menus for this institution
        clear_menu_cache($institution);
    }
    $newinstitution->showonlineusers = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers'];
    if (get_config('usersuniquebyusername')) {
        // Registering absolutely not allowed when this setting is on, it's a
        // security risk. See the documentation for the usersuniquebyusername
        // setting for more information
        $newinstitution->registerallowed = 0;
    } else {
        $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0;
        $newinstitution->registerconfirm = $values['registerconfirm'] ? 1 : 0;
    }
    if (!empty($values['lang'])) {
        if ($values['lang'] == 'sitedefault') {
            $newinstitution->lang = null;
        } else {
            $newinstitution->lang = $values['lang'];
        }
    }
    $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme'];
    $newinstitution->dropdownmenu = !empty($values['dropdownmenu']) ? 1 : 0;
    $newinstitution->skins = !empty($values['skins']) ? 1 : 0;
    require_once get_config('docroot') . 'artefact/comment/lib.php';
    $commentoptions = ArtefactTypeComment::get_comment_options();
    $newinstitution->commentsortorder = empty($values['commentsortorder']) ? $commentoptions->sort : $values['commentsortorder'];
    $newinstitution->commentthreaded = !empty($values['commentthreaded']) ? 1 : 0;
    if ($newinstitution->theme == 'custom') {
        if (!empty($oldinstitution->style)) {
            $styleid = $oldinstitution->style;
            delete_records('style_property', 'style', $styleid);
        } else {
            $record = (object) array('title' => get_string('customstylesforinstitution', 'admin', $newinstitution->displayname));
            $styleid = insert_record('style', $record, 'id', true);
        }
        $properties = array();
        $record = (object) array('style' => $styleid);
        foreach (array_keys($customthemedefaults) as $name) {
            $record->field = $name;
            $record->value = $values[$name];
            insert_record('style_property', $record);
            $properties[$name] = $values[$name];
        }
        // Cache the css
        $smarty = smarty_core();
        $smarty->assign('data', $properties);
        set_field('style', 'css', $smarty->fetch('customcss.tpl'), 'id', $styleid);
        $newinstitution->style = $styleid;
    } else {
        $newinstitution->style = null;
    }
    if (get_config('licensemetadata')) {
        $newinstitution->licensemandatory = !empty($values['licensemandatory']) ? 1 : 0;
        $newinstitution->licensedefault = isset($values['licensedefault']) ? $values['licensedefault'] : '';
    }
    if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) {
        $newinstitution->style = null;
    }
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
        if (!empty($values['updateuserquotas']) && !empty($values['defaultquota'])) {
            execute_sql("UPDATE {usr} SET quota = ? WHERE id IN (SELECT usr FROM {usr_institution} WHERE institution = ?)", array($values['defaultquota'], $institution));
            // get all the users from the institution and make sure that they are still below
            // their quota threshold
            if ($users = get_records_sql_array('SELECT * FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr AND ui.institution = ?', array($institution))) {
                $quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit');
                if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) {
                    $quotanotifylimit = 100;
                }
                foreach ($users as $user) {
                    $user->quota = $values['defaultquota'];
                    // check if the user has gone over the quota notify limit
                    $user->quotausedpercent = $user->quotaused / $user->quota * 100;
                    $overlimit = false;
                    if ($quotanotifylimit <= $user->quotausedpercent) {
                        $overlimit = true;
                    }
                    $notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $user->id);
                    if ($overlimit && '1' !== $notified) {
                        require_once get_config('docroot') . 'artefact/file/lib.php';
                        ArtefactTypeFile::notify_users_threshold_exceeded(array($user), false);
                        // no need to email admin as we can alert them right now
                        $SESSION->add_error_msg(get_string('useroverquotathreshold', 'artefact.file', display_name($user)));
                    } else {
                        if ($notified && !$overlimit) {
                            set_account_preference($user->id, 'quota_exceeded_notified', false);
                        }
                    }
                }
            }
        }
        $newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota'];
    }
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null;
            $newinstitution->expiry = db_format_timestamp($values['expiry']);
        }
    }
    $newinstitution->allowinstitutionpublicviews = isset($values['allowinstitutionpublicviews']) && $values['allowinstitutionpublicviews'] ? 1 : 0;
    // TODO: Move handling of authentication instances within the Institution class as well?
    if (!empty($values['authplugin'])) {
        $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']);
        if (array_diff($allinstances, $instancearray)) {
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
        }
        if (array_diff($instancearray, $allinstances)) {
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
        }
        foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
                throw new SystemException('Attempt to update AND delete an auth instance');
            }
            $record = new StdClass();
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record, array('id' => $instanceid));
        }
        foreach ($values['authplugin']['deletearray'] as $instanceid) {
            // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record.
            $hostwwwroot = null;
            foreach ($authinstances as $ai) {
                if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') {
                    $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid));
                    if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) {
                        // Unfortunately, it's possible that this host record could belong to a different institution,
                        // so specify the institution here.
                        delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution);
                        // We really need to fix this, either by removing the institution from the host table, or refusing to allow the
                        // institution to be changed in the host record when another institution's authinstance is still pointing at it.
                    }
                    break;
                }
            }
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
            // Make it no longer be the parent authority to any auth instances
            delete_records('auth_instance_config', 'field', 'parent', 'value', $instanceid);
        }
    }
    // Store plugin settings.
    plugin_institution_prefs_submit($form, $values, $newinstitution);
    // Save the changes to the DB
    $newinstitution->commit();
    if ($add) {
        // Automatically create an internal authentication authinstance
        $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal');
        insert_record('auth_instance', $authinstance);
        // We need to add the default lines to the site_content table for this institution
        // We also need to set the institution to be using default static pages to begin with
        // so that using custom institution pages is an opt-in situation
        $pages = site_content_pages();
        $now = db_format_timestamp(time());
        foreach ($pages as $name) {
            $page = new stdClass();
            $page->name = $name;
            $page->ctime = $now;
            $page->mtime = $now;
            $page->content = get_string($page->name . 'defaultcontent', 'install', get_string('staticpageconfiginstitution', 'install'));
            $page->institution = $newinstitution->name;
            insert_record('site_content', $page);
            $institutionconfig = new stdClass();
            $institutionconfig->institution = $newinstitution->name;
            $institutionconfig->field = 'sitepages_' . $name;
            $institutionconfig->value = 'mahara';
            insert_record('institution_config', $institutionconfig);
        }
    }
    if (is_null($newinstitution->style) && !empty($oldinstitution->style)) {
        delete_records('style_property', 'style', $oldinstitution->style);
        delete_records('style', 'id', $oldinstitution->style);
    }
    // Set the logo after updating the institution, because the institution
    // needs to exist before it can own the logo artefact.
    if (!empty($values['logo'])) {
        safe_require('artefact', 'file');
        // Entry in artefact table
        $data = (object) array('institution' => $institution, 'title' => 'logo', 'description' => 'Institution logo', 'note' => $values['logo']['name'], 'size' => $values['logo']['size']);
        $imageinfo = getimagesize($values['logo']['tmp_name']);
        $data->width = $imageinfo[0];
        $data->height = $imageinfo[1];
        $data->filetype = $imageinfo['mime'];
        $artefact = new ArtefactTypeProfileIcon(0, $data);
        if (preg_match("/\\.([^\\.]+)\$/", $values['logo']['name'], $saved)) {
            $artefact->set('oldextension', $saved[1]);
        }
        $artefact->commit();
        $id = $artefact->get('id');
        // Move the file into the correct place.
        $directory = get_config('dataroot') . 'artefact/file/profileicons/originals/' . $id % 256 . '/';
        check_dir_exists($directory);
        move_uploaded_file($values['logo']['tmp_name'], $directory . $id);
        // Delete the old logo
        if (!empty($oldinstitution->logo)) {
            $oldlogo = new ArtefactTypeProfileIcon($oldinstitution->logo);
            $oldlogo->delete();
        }
        set_field('institution', 'logo', $id, 'name', $institution);
    }
    if (!empty($values['deletelogo'])) {
        execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution));
    }
    delete_records('institution_locked_profile_field', 'name', $institution);
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
        if ($values[$field]) {
            $profilefield = new StdClass();
            $profilefield->name = $institution;
            $profilefield->profilefield = $field;
            insert_record('institution_locked_profile_field', $profilefield);
        }
    }
    db_commit();
    if ($add) {
        if (!$newinstitution->registerallowed) {
            // If registration is not allowed, then an authinstance will not
            // have been created, and thus cause the institution page to add
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
        $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution);
    } else {
        $message = get_string('institutionupdatedsuccessfully', 'admin');
        if (isset($values['theme'])) {
            $changedtheme = $oldinstitution->theme != $values['theme'] && (!empty($oldinstitution->theme) || $values['theme'] != 'sitedefault');
            if ($changedtheme || $values['theme'] == 'custom') {
                $message .= '  ' . get_string('usersseenewthemeonlogin', 'admin');
            }
            $USER->reset_institutions();
        }
        $SESSION->add_ok_msg($message);
        $nexturl = '/admin/users/institutions.php';
    }
    redirect($nexturl);
}
Ejemplo n.º 18
0
 public function render_profile_element()
 {
     $data = self::get_social_profiles();
     // Build pagination for 'socialprofile' artefacts table
     $baseurl = get_config('wwwroot') . 'artefact/internal/index.php' . '?' . http_build_query(array('fs' => 'social'));
     $count = count($data);
     $limit = 500;
     $offset = 0;
     $pagination = build_pagination(array('id' => 'socialprofiles_pagination', 'url' => $baseurl, 'datatable' => 'socialprofilelist', 'count' => $count, 'limit' => $limit, 'offset' => $offset));
     // User may delete social profile if:
     //  - there is more than 1 social profile and 'socialprofile' is a mandatory field.
     //  - 'socialprofile' is not mandatory.
     $candelete = true;
     $mandatory_fields = ArtefactTypeProfile::get_mandatory_fields();
     if (isset($mandatory_fields['socialprofile']) && count($data) <= 1) {
         $candelete = false;
     }
     $smarty = smarty_core();
     $smarty->assign('controls', true);
     $smarty->assign('rows', $data);
     $smarty->assign('candelete', $candelete);
     $smarty->assign('pagination', $pagination);
     return array('type' => 'html', 'value' => $smarty->fetch('artefact:internal:socialprofiles.tpl'));
 }
Ejemplo n.º 19
0
/**
 * The CSV file is parsed here so validation errors can be returned to the
 * user. The data from a successful parsing is stored in the <var>$CVSDATA</var>
 * array so it can be accessed by the submit function
 *
 * @param Pieform  $form   The form to validate
 * @param array    $values The values submitted
 */
function uploadcsv_validate(Pieform $form, $values)
{
    global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER, $INSTITUTIONNAME, $UPDATES;
    // Don't even start attempting to parse if there are previous errors
    if ($form->has_errors()) {
        return;
    }
    if ($values['file']['size'] == 0) {
        $form->set_error('file', $form->i18n('rule', 'required', 'required', array()));
        return;
    }
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
        $maxquotaenabled = get_config_plugin('artefact', 'file', 'maxquotaenabled');
        $maxquota = get_config_plugin('artefact', 'file', 'maxquota');
        if ($maxquotaenabled && $values['quota'] > $maxquota) {
            $form->set_error('quota', get_string('maxquotaexceededform', 'artefact.file', display_size($maxquota)));
        }
    }
    require_once 'csvfile.php';
    $authinstance = (int) $values['authinstance'];
    $institution = get_field('auth_instance', 'institution', 'id', $authinstance);
    if (!$USER->can_edit_institution($institution)) {
        $form->set_error('authinstance', get_string('notadminforinstitution', 'admin'));
        return;
    }
    //OVERWRITE 2: add
    $authname = get_field('auth_instance', 'authname', 'id', $authinstance);
    if ($authname != 'internal') {
        $form->set_error('authinstance', get_string('notadminforinstitution', 'admin'));
        return;
    }
    //END OVERWRITE 2
    $authobj = AuthFactory::create($authinstance);
    $csvusers = new CsvFile($values['file']['tmp_name']);
    $csvusers->set('allowedkeys', $ALLOWEDKEYS);
    // Now we know all of the field names are valid, we need to make
    // sure that the required fields are included
    $mandatoryfields = array('username');
    if (!$values['updateusers']) {
        $mandatoryfields[] = 'password';
    }
    $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields()));
    if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) {
        $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields);
    }
    $csvusers->set('mandatoryfields', $mandatoryfields);
    $csvdata = $csvusers->get_data();
    if (!empty($csvdata->errors['file'])) {
        $form->set_error('file', $csvdata->errors['file']);
        return;
    }
    $csverrors = new CSVErrors();
    $formatkeylookup = array_flip($csvdata->format);
    // First pass validates usernames & passwords in the file, and builds
    // up a list indexed by username.
    $emails = array();
    if (isset($formatkeylookup['remoteuser'])) {
        $remoteusers = array();
    }
    $maxcsvlines = get_config('maxusercsvlines');
    if ($maxcsvlines && $maxcsvlines < count($csvdata->data)) {
        $form->set_error('file', get_string('uploadcsverrortoomanyusers', 'admin', get_string('nusers', 'mahara', $maxcsvlines)));
        return;
    }
    foreach ($csvdata->data as $key => $line) {
        // If headers exists, increment i = key + 2 for actual line number
        $i = $csvusers->get('headerExists') ? $key + 2 : $key + 1;
        // Trim non-breaking spaces -- they get left in place by File_CSV
        foreach ($line as &$field) {
            $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field);
        }
        if (count($line) != count($csvdata->format)) {
            $csverrors->add($i, get_string('uploadcsverrorwrongnumberoffields', 'admin', $i));
            continue;
        }
        // We have a line with the correct number of fields, but should validate these fields
        // Note: This validation should really be methods on each profile class, that way
        // it can be used in the profile screen as well.
        $username = $line[$formatkeylookup['username']];
        $password = isset($formatkeylookup['password']) ? $line[$formatkeylookup['password']] : null;
        $email = $line[$formatkeylookup['email']];
        if (isset($remoteusers)) {
            $remoteuser = strlen($line[$formatkeylookup['remoteuser']]) ? $line[$formatkeylookup['remoteuser']] : null;
        }
        if (method_exists($authobj, 'is_username_valid_admin')) {
            if (!$authobj->is_username_valid_admin($username)) {
                $csverrors->add($i, get_string('uploadcsverrorinvalidusername', 'admin', $i));
            }
        } else {
            if (method_exists($authobj, 'is_username_valid')) {
                if (!$authobj->is_username_valid($username)) {
                    $csverrors->add($i, get_string('uploadcsverrorinvalidusername', 'admin', $i));
                }
            }
        }
        if (!$values['updateusers']) {
            // Note: only checks for valid form are done here, none of the checks
            // like whether the password is too easy. The user is going to have to
            // change their password on first login anyway.
            if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
                $csverrors->add($i, get_string('uploadcsverrorinvalidpassword', 'admin', $i));
            }
        }
        // OVERWRITE 3: replacement, changed from:
        //if (isset($emails[$email])) {
        //    // Duplicate email within this file.
        //    $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
        //}
        //else if (!PHPMailer::ValidateAddress($email)) {
        //    $csverrors->add($i, get_string('uploadcsverrorinvalidemail', 'admin', $i, $email));
        //}
        //else if (!$values['updateusers']) {
        //    // The email address must be new
        //    if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email, 'verified', 1)) {
        //        $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
        //    }
        //}
        //$emails[$email] = 1;
        // TO:
        if (isset($emails[strtolower($email)])) {
            // Duplicate email within this file.
            $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
        } else {
            if (!PHPMailer::ValidateAddress($email)) {
                $csverrors->add($i, get_string('uploadcsverrorinvalidemail', 'admin', $i, $email));
            } else {
                if (!$values['updateusers']) {
                    // The email address must be new
                    if (GcrInstitutionTable::isEmailAddressUsed($email)) {
                        $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
                    }
                }
            }
        }
        $emails[strtolower($email)] = 1;
        // END OVERWRITE 3
        if (isset($remoteusers) && $remoteuser) {
            if (isset($remoteusers[$remoteuser])) {
                $csverrors->add($i, get_string('uploadcsverrorduplicateremoteuser', 'admin', $i, $remoteuser));
            } else {
                if (!$values['updateusers']) {
                    if ($remoteuserowner = get_record_sql('
                    SELECT u.username
                    FROM {auth_remote_user} aru JOIN {usr} u ON aru.localusr = u.id
                    WHERE aru.remoteusername = ? AND aru.authinstance = ?', array($remoteuser, $authinstance))) {
                        $csverrors->add($i, get_string('uploadcsverrorremoteusertaken', 'admin', $i, $remoteuser, $remoteuserowner->username));
                    }
                }
            }
            $remoteusers[$remoteuser] = true;
        }
        // If we didn't even get a username, we can't check for duplicates, so move on.
        if (strlen($username) < 1) {
            continue;
        }
        if (isset($usernames[strtolower($username)])) {
            // Duplicate username within this file.
            $csverrors->add($i, get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username));
        } else {
            if (!$values['updateusers'] && record_exists_select('usr', 'LOWER(username) = ?', strtolower($username))) {
                $csverrors->add($i, get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username));
            }
            $usernames[strtolower($username)] = array('username' => $username, 'password' => $password, 'email' => $email, 'lineno' => $i, 'raw' => $line);
            if (!empty($remoteuser) && !empty($remoteusers[$remoteuser])) {
                $usernames[strtolower($username)]['remoteuser'] = $remoteuser;
            }
        }
    }
    // If the admin is trying to overwrite existing users, identified by username,
    // this second pass performs some additional checks
    if ($values['updateusers']) {
        foreach ($usernames as $lowerusername => $data) {
            $line = $data['lineno'];
            $username = $data['username'];
            $password = $data['password'];
            $email = $data['email'];
            // If the user already exists, they must already be in this institution.
            $userinstitutions = get_records_sql_assoc("\n                SELECT COALESCE(ui.institution, 'mahara') AS institution, u.id\n                FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr\n                WHERE LOWER(u.username) = ?", array($lowerusername));
            if ($userinstitutions) {
                if (!isset($userinstitutions[$institution])) {
                    if ($institution == 'mahara') {
                        $institutiondisplay = array();
                        foreach ($userinstitutions as $i) {
                            $institutiondisplay[] = $INSTITUTIONNAME[$i->institution];
                        }
                        $institutiondisplay = join(', ', $institutiondisplay);
                        $message = get_string('uploadcsverroruserinaninstitution', 'admin', $line, $username, $institutiondisplay);
                    } else {
                        $message = get_string('uploadcsverrorusernotininstitution', 'admin', $line, $username, $INSTITUTIONNAME[$institution]);
                    }
                    $csverrors->add($line, $message);
                } else {
                    // Remember that this user is being updated
                    $UPDATES[$username] = 1;
                }
            } else {
                // New user, check the password
                if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
                    $csverrors->add($line, get_string('uploadcsverrorinvalidpassword', 'admin', $line));
                }
            }
            // Check if the email already exists and if it's owned by this user.  This query can return more
            // than one row when there are duplicate emails already on the site.  If that happens, things are
            // already a bit out of hand, and we'll just allow an update if this user is one of the users who
            // owns the email.
            $emailowned = get_records_sql_assoc('
                SELECT LOWER(u.username) AS lowerusername, ae.principal FROM {usr} u
                LEFT JOIN {artefact_internal_profile_email} ae ON u.id = ae.owner AND ae.verified = 1 AND ae.email = ?
                WHERE ae.owner IS NOT NULL OR u.email = ?', array($email, $email));
            // If the email is owned by someone else, it could still be okay provided
            // that other user's email is also being changed in this csv file.
            if ($emailowned && !isset($emailowned[$lowerusername])) {
                foreach ($emailowned as $e) {
                    // Only primary emails can be set in uploadcsv, so it's an error when someone else
                    // owns the email as a secondary.
                    if (!$e->principal) {
                        $csverrors->add($line, get_string('uploadcsverroremailaddresstaken', 'admin', $line, $email));
                        break;
                    }
                    // It's also an error if the email owner is not being updated in this file
                    if (!isset($usernames[$e->lowerusername])) {
                        $csverrors->add($line, get_string('uploadcsverroremailaddresstaken', 'admin', $line, $email));
                        break;
                    }
                    // If the other user is being updated in this file, but isn't changing their
                    // email address, it's ok, we've already notified duplicate emails within the file.
                }
            }
            if (isset($remoteusers) && !empty($data['remoteuser'])) {
                $remoteuser = $data['remoteuser'];
                $remoteuserowner = get_field_sql('
                    SELECT LOWER(u.username)
                    FROM {usr} u JOIN {auth_remote_user} aru ON u.id = aru.localusr
                    WHERE aru.remoteusername = ? AND aru.authinstance = ?', array($remoteuser, $authinstance));
                if ($remoteuserowner && $remoteuserowner != $lowerusername && !isset($usernames[$remoteuserowner])) {
                    // The remote username is owned by some other user who is not being updated in this file
                    $csverrors->add($line, get_string('uploadcsverrorremoteusertaken', 'admin', $line, $remoteuser, $remoteuserowner));
                }
            }
        }
    }
    if ($errors = $csverrors->process()) {
        $form->set_error('file', clean_html($errors));
        return;
    }
    $FORMAT = $csvdata->format;
    $CSVDATA = $csvdata->data;
}
Ejemplo n.º 20
0
/**
 * The CSV file is parsed here so validation errors can be returned to the
 * user. The data from a successful parsing is stored in the <var>$CVSDATA</var>
 * array so it can be accessed by the submit function
 *
 * @param Pieform  $form   The form to validate
 * @param array    $values The values submitted
 */
function uploadcsv_validate(Pieform $form, $values)
{
    global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER, $CSVERRORS;
    // Don't even start attempting to parse if there are previous errors
    if ($form->has_errors()) {
        return;
    }
    if ($values['file']['size'] == 0) {
        $form->set_error('file', $form->i18n('rule', 'required', 'required', array()));
        return;
    }
    require_once 'csvfile.php';
    $authinstance = (int) $values['authinstance'];
    $institution = get_field('auth_instance', 'institution', 'id', $authinstance);
    if (!$USER->can_edit_institution($institution)) {
        $form->set_error('authinstance', get_string('notadminforinstitution', 'admin'));
        return;
    }
    $usernames = array();
    $emails = array();
    $csvusers = new CsvFile($values['file']['tmp_name']);
    $csvusers->set('allowedkeys', $ALLOWEDKEYS);
    // Now we know all of the field names are valid, we need to make
    // sure that the required fields are included
    $mandatoryfields = array('username', 'password');
    $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields()));
    if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) {
        $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields);
    }
    $csvusers->set('mandatoryfields', $mandatoryfields);
    $csvdata = $csvusers->get_data();
    if (!empty($csvdata->errors['file'])) {
        $form->set_error('file', $csvdata->errors['file']);
        return;
    }
    foreach ($csvdata->data as $key => $line) {
        // If headers exists, increment i = key + 2 for actual line number
        $i = $csvusers->get('headerExists') ? $key + 2 : $key + 1;
        // Trim non-breaking spaces -- they get left in place by File_CSV
        foreach ($line as &$field) {
            $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field);
        }
        // We have a line with the correct number of fields, but should validate these fields
        // Note: This validation should really be methods on each profile class, that way
        // it can be used in the profile screen as well.
        $formatkeylookup = array_flip($csvdata->format);
        $username = $line[$formatkeylookup['username']];
        $password = $line[$formatkeylookup['password']];
        $email = $line[$formatkeylookup['email']];
        $authobj = AuthFactory::create($authinstance);
        if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) {
            $CSVERRORS[] = get_string('uploadcsverrorinvalidusername', 'admin', $i);
        }
        if (record_exists_select('usr', 'LOWER(username) = ?', strtolower($username)) || isset($usernames[strtolower($username)])) {
            $CSVERRORS[] = get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username);
        }
        if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email) || isset($emails[$email])) {
            $CSVERRORS[] = get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email);
        }
        // Note: only checks for valid form are done here, none of the checks
        // like whether the password is too easy. The user is going to have to
        // change their password on first login anyway.
        if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
            $CSVERRORS[] = get_string('uploadcsverrorinvalidpassword', 'admin', $i);
        }
        $usernames[strtolower($username)] = 1;
        $emails[$email] = 1;
    }
    if (!empty($CSVERRORS)) {
        $form->set_error('file', implode("<br />\n", $CSVERRORS));
        return;
    }
    $FORMAT = $csvdata->format;
    $CSVDATA = $csvdata->data;
}
Ejemplo n.º 21
0
function institution_submit(Pieform $form, $values)
{
    global $SESSION, $institution, $add, $instancearray, $USER, $authinstances, $customthemedefaults;
    db_begin();
    // Update the basic institution record...
    $newinstitution = new StdClass();
    if ($add) {
        $institution = $newinstitution->name = strtolower($values['name']);
    } else {
        $oldinstitution = get_record('institution', 'name', $institution);
    }
    $newinstitution->displayname = $values['displayname'];
    $newinstitution->authplugin = empty($values['authplugin']) ? null : $values['authplugin'];
    $newinstitution->showonlineusers = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers'];
    if (get_config('usersuniquebyusername')) {
        // Registering absolutely not allowed when this setting is on, it's a
        // security risk. See the documentation for the usersuniquebyusername
        // setting for more information
        $newinstitution->registerallowed = 0;
    } else {
        $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0;
        $newinstitution->registerconfirm = $values['registerconfirm'] ? 1 : 0;
    }
    $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme'];
    $newinstitution->dropdownmenu = !empty($values['dropdownmenu']) ? 1 : 0;
    $newinstitution->skins = !empty($values['skins']) ? 1 : 0;
    if ($newinstitution->theme == 'custom') {
        if (!empty($oldinstitution->style)) {
            $styleid = $oldinstitution->style;
            delete_records('style_property', 'style', $styleid);
        } else {
            $record = (object) array('title' => get_string('customstylesforinstitution', 'admin', $newinstitution->displayname));
            $styleid = insert_record('style', $record, 'id', true);
        }
        $properties = array();
        $record = (object) array('style' => $styleid);
        foreach (array_keys($customthemedefaults) as $name) {
            $record->field = $name;
            $record->value = $values[$name];
            insert_record('style_property', $record);
            $properties[$name] = $values[$name];
        }
        // Cache the css
        $smarty = smarty_core();
        $smarty->assign('data', $properties);
        set_field('style', 'css', $smarty->fetch('customcss.tpl'), 'id', $styleid);
        $newinstitution->style = $styleid;
    } else {
        $newinstitution->style = null;
    }
    if (get_config('licensemetadata')) {
        $newinstitution->licensemandatory = !empty($values['licensemandatory']) ? 1 : 0;
        $newinstitution->licensedefault = isset($values['licensedefault']) ? $values['licensedefault'] : '';
    }
    if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) {
        $newinstitution->style = null;
    }
    if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) {
        if (!empty($values['updateuserquotas']) && !empty($values['defaultquota'])) {
            execute_sql("UPDATE {usr} SET quota = ? WHERE id IN (SELECT usr FROM {usr_institution} WHERE institution = ?)", array($values['defaultquota'], $institution));
        }
        $newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota'];
    }
    if ($institution != 'mahara') {
        $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null;
        if ($USER->get('admin')) {
            $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null;
            $newinstitution->expiry = db_format_timestamp($values['expiry']);
        }
    }
    $newinstitution->allowinstitutionpublicviews = isset($values['allowinstitutionpublicviews']) && $values['allowinstitutionpublicviews'] ? 1 : 0;
    if (!empty($values['authplugin'])) {
        $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']);
        if (array_diff($allinstances, $instancearray)) {
            throw new ConfigException('Attempt to delete or update another institution\'s auth instance');
        }
        if (array_diff($instancearray, $allinstances)) {
            throw new ConfigException('One of your instances is unaccounted for in this transaction');
        }
        foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) {
            if (in_array($instanceid, $values['authplugin']['deletearray'])) {
                // Should never happen:
                throw new SystemException('Attempt to update AND delete an auth instance');
            }
            $record = new StdClass();
            $record->priority = $priority;
            $record->id = $instanceid;
            update_record('auth_instance', $record, array('id' => $instanceid));
        }
        foreach ($values['authplugin']['deletearray'] as $instanceid) {
            // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record.
            $hostwwwroot = null;
            foreach ($authinstances as $ai) {
                if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') {
                    $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid));
                    if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) {
                        // Unfortunately, it's possible that this host record could belong to a different institution,
                        // so specify the institution here.
                        delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution);
                        // We really need to fix this, either by removing the institution from the host table, or refusing to allow the
                        // institution to be changed in the host record when another institution's authinstance is still pointing at it.
                    }
                    break;
                }
            }
            delete_records('auth_remote_user', 'authinstance', $instanceid);
            delete_records('auth_instance_config', 'instance', $instanceid);
            delete_records('auth_instance', 'id', $instanceid);
            // Make it no longer be the parent authority to any auth instances
            delete_records('auth_instance_config', 'field', 'parent', 'value', $instanceid);
        }
    }
    if ($add) {
        insert_record('institution', $newinstitution);
        // If registration has been turned on, then we automatically insert an
        // internal authentication authinstance
        // OVERWRITE 4: deletion
        //if ($newinstitution->registerallowed) {
        // END OVERWRITE 4
        $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal');
        insert_record('auth_instance', $authinstance);
        // OVERWRITE 5: deletion
        //}
        // END OVERWRITE 5
    } else {
        $where = new StdClass();
        $where->name = $institution;
        update_record('institution', $newinstitution, $where);
    }
    if (is_null($newinstitution->style) && !empty($oldinstitution->style)) {
        delete_records('style_property', 'style', $oldinstitution->style);
        delete_records('style', 'id', $oldinstitution->style);
    }
    // Set the logo after updating the institution, because the institution
    // needs to exist before it can own the logo artefact.
    if (!empty($values['logo'])) {
        safe_require('artefact', 'file');
        // Entry in artefact table
        $data = (object) array('institution' => $institution, 'title' => 'logo', 'description' => 'Institution logo', 'note' => $values['logo']['name'], 'size' => $values['logo']['size']);
        $imageinfo = getimagesize($values['logo']['tmp_name']);
        $data->width = $imageinfo[0];
        $data->height = $imageinfo[1];
        $data->filetype = $imageinfo['mime'];
        $artefact = new ArtefactTypeProfileIcon(0, $data);
        if (preg_match("/\\.([^\\.]+)\$/", $values['logo']['name'], $saved)) {
            $artefact->set('oldextension', $saved[1]);
        }
        $artefact->commit();
        $id = $artefact->get('id');
        // Move the file into the correct place.
        $directory = get_config('dataroot') . 'artefact/file/profileicons/originals/' . $id % 256 . '/';
        check_dir_exists($directory);
        move_uploaded_file($values['logo']['tmp_name'], $directory . $id);
        // Delete the old logo
        if (!empty($oldinstitution->logo)) {
            $oldlogo = new ArtefactTypeProfileIcon($oldinstitution->logo);
            $oldlogo->delete();
        }
        set_field('institution', 'logo', $id, 'name', $institution);
    }
    if (!empty($values['deletelogo'])) {
        execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution));
    }
    delete_records('institution_locked_profile_field', 'name', $institution);
    foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) {
        if ($values[$field]) {
            $profilefield = new StdClass();
            $profilefield->name = $institution;
            $profilefield->profilefield = $field;
            insert_record('institution_locked_profile_field', $profilefield);
        }
    }
    db_commit();
    if ($add) {
        // OVERWRITE 7: insert
        global $CFG;
        $current_user = $CFG->current_app->getCurrentUser();
        $mhr_usr_institution = $current_user->addMhrInstitutionMembership($newinstitution);
        $CFG->current_app->updateMhrTable('usr_institution', array('admin' => 1), array('usr' => $current_user->getObject()->id));
        // END OVERWRITE 7
        if ($newinstitution->registerallowed) {
            // If registration is not allowed, then an authinstance will not
            // have been created, and thus cause the institution page to add
            // its own error message on the next page load
            $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin'));
        }
        $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution);
    } else {
        $message = get_string('institutionupdatedsuccessfully', 'admin');
        if (isset($values['theme'])) {
            $changedtheme = $oldinstitution->theme != $values['theme'] && (!empty($oldinstitution->theme) || $values['theme'] != 'sitedefault');
            if ($changedtheme || $values['theme'] == 'custom') {
                $message .= '  ' . get_string('usersseenewthemeonlogin', 'admin');
            }
            $USER->reset_institutions();
        }
        $SESSION->add_ok_msg($message);
        $nexturl = '/admin/users/institutions.php';
    }
    redirect($nexturl);
}