'Force password change', 'page callback' => 'drupal_get_form', 'page arguments' => array('force_password_change_settings'), 'access arguments' => array('Administer force password change'), 'file' => 'force_password_change_pages.inc', ); $menu['force_password_change/list/%'] = array ( 'title' => 'dummy title. Does not need translation', 'page callback' => 'force_password_change_list', 'page arguments' => array(2), 'access arguments' => array('Administer force password change'), 'file' => 'force_password_change_pages.inc', 'type' => MENU_CALLBACK, ); return $menu; } /** * Implementation of hook_init() */ function force_password_change_init() { global $user; $change_password_url = preg_replace('/!uid/', $user->uid, variable_get('change_password_url', 'user/!uid/edit')); if($user->uid && $_GET['q'] != $change_password_url && $_GET['q'] != drupal_get_path_alias('logout')) { $redirect = FALSE; if(variable_get('force_password_change_login_or_init', 0)) { $pending_users = variable_get('force_password_change_pending_login_users', array()); if(isset($pending_users[$user->uid])) { $type = $pending_users[$user->uid]['type']; $destination = ''; $redirect = TRUE; } } else { $pending_change = force_password_change_check(); if(strlen($pending_change)) { $type = $pending_change; $destination = 'destination=' . $_GET['q']; $redirect = TRUE; } } if($redirect) { if($type == 1) { drupal_set_message(t('An administrator has required that you change your password. Please change your password to proceed.'), 'error', FALSE); } else { drupal_set_message(t('This site requires that you change your password every !time_period. Please change your password to proceed.', array('!time_period' => $type))); } drupal_goto($change_password_url, $destination); } } } function force_password_change_check() { global $user; $change_password_url = preg_replace('/!uid/', $user->uid, variable_get('change_password_url', 'user/!uid/edit')); if($user->force_password_change) { return '1'; } elseif(variable_get('expire_password', TRUE)) { $expiry_data = db_result ( db_query_range ( 'SELECT fpce.expiry ' . 'FROM {force_password_change_expiry} AS fpce ' . 'LEFT JOIN {users_roles} AS ur ' . 'ON ur.rid = fpce.rid ' . 'WHERE ur.uid = %d OR fpce.rid = 2 ' . 'ORDER BY fpce.weight ', $user->uid, 0, 1 ) ); if($expiry_data) { $pass_change_data = db_fetch_array ( db_query ( 'SELECT fpcu.last_password_change, u.created ' . 'FROM {force_password_change_users} AS fpcu ' . 'JOIN {users} AS u ' . 'ON u.uid = fpcu.uid ' . 'WHERE u.uid = %d ', $user->uid ) ); if(($pass_change_data['last_password_change'] != '' && (time() - $expiry_data) > $pass_change_data['last_password_change']) || ($pass_change_data['last_password_change'] == '' && (time() - $expiry_data) > $pass_change_data['created'])) { $expires = $expiry_data; $year = 60 * 60 * 24 * 365; if($expires % $year === 0) { $time_period = $expires / $year; $time_period = ($time_period > 1) ? $time_period . ' ' . t('years') : t('year'); } else { $week = 60 * 60 * 24 * 7; if($expires % $week === 0) { $time_period = $expires / $week; $time_period = ($time_period > 1) ? $time_period . ' ' . t('weeks') : t('week'); } else { $day = 60 * 60 * 24; if($expires % $day === 0) { $time_period = $expires / $day; $time_period = ($time_period > 1) ? $time_period . ' ' . t('days') : t('day'); } else { $hour = 60 * 60; if($expires % $hour === 0) { $time_period = $expires / $hour; $time_period = ($time_period > 1) ? $time_period . ' ' . t('hours') : t('hour'); } } } } db_query('UPDATE {users} SET force_password_change = 1 WHERE uid = %d', $user->uid); return $time_period; } } } return FALSE; } /** * Implementation of hook_user() */ function force_password_change_user($op, &$edit, &$account, $category = NULL) { global $user; switch($op) { case 'login': if(variable_get('force_password_change_login_or_init', 0)) { $pending_change = force_password_change_check(); if(strlen($pending_change)) { $pending_users = variable_get('force_password_change_pending_login_users', array()); $pending_users[$account->uid] = array ( 'destination' => $_GET['q'], 'type' => $pending_change, ); variable_set('force_password_change_pending_login_users', $pending_users); } } break; case 'validate': if($account->force_password_change && $account->uid == $user->uid) { if($edit['pass'] == '') { form_set_error('password', t('You must choose a new password')); } } if(md5($edit['pass']) == $account->pass) { form_set_error('pass', t('You cannot use your current password. Please choose a different password.')); } break; case 'register': $form = array(); if(!variable_get('first_time_login_password_change', FALSE)) { $form['force_password_change'] = array ( '#type' => 'checkbox', '#title' => t('Force password change on first-time login'), '#description' => t('If this box is checked, the user will be forced to change their password on their first login.'), ); } return $form; break; case 'update': if(trim($edit['pass']) != '' && $edit['pass'] != $account->pass) { db_query ( 'UPDATE {force_password_change_users} SET last_password_change = %d WHERE uid = %d', time(), $account->uid ); } if($account->force_password_change && $user->uid == $account->uid && isset($edit['pending_force_password_change'])) { db_query ( 'UPDATE {users} SET force_password_change = 0 WHERE uid = %d', $account->uid ); $forced_uids = variable_get('force_password_change_first_time_uids', array()); if(count($forced_uids)) { unset($forced_uids[$account->uid]); variable_set('force_password_change_first_time_uids', $forced_uids); } $pending_users = variable_get('force_password_change_pending_login_users', array()); if(isset($pending_users[$account->uid])) { $destination = $pending_users[$account->uid]['destination']; unset($pending_users[$account->uid]); variable_set('force_password_change_pending_login_users', $pending_users); $_REQUEST['destination'] = $destination; } } if($edit['force_password_change']) { db_query ( 'UPDATE {users} SET force_password_change = 1 WHERE uid = %d', $account->uid ); db_query ( 'UPDATE {force_password_change_users} SET last_force = %d WHERE uid = %d', time(), $account->uid ); unset($edit['force_password_change']); } break; case 'insert': db_query('INSERT INTO {force_password_change_users} (uid) VALUES (%d)', $account->uid); if(variable_get('first_time_login_password_change', 0)) { db_query('UPDATE {users} SET force_password_change = 1 WHERE uid = %d', $account->uid); } elseif($edit['force_password_change']) { db_query('UPDATE {users} SET force_password_change = 1 WHERE uid = %d', $account->uid); $forced_uids = variable_get('force_password_change_first_time_uids', array()); $forced_uids[$account->uid] = $account->uid; variable_set('force_password_change_first_time_uids', $forced_uids); } unset($edit['force_password_change']); break; case 'delete': db_query('DELETE FROM {force_password_change_users} WHERE uid = %d', $account->uid); break; } } /** * Implementation of hook_form_alter() */ function force_password_change_form_alter(&$form, &$form_state, $form_id) { if($form_id == 'user_admin_new_role') { $form['#submit'][] = 'force_password_change_add_role'; $form['#theme'][] = 'force_password_change_new_role_form'; } elseif($form_id == 'user_admin_role') { $form['force_password_change'] = array ( '#type' => 'checkbox', '#title' => t('Force users in this role to change their password'), '#description' => t('Users who are not signed in will be required to change their password immediately upon sign in. Users who are currently signed in will be required to change their password upon their next page click, but after changing their password will be redirected back to the page they were attempting to access.') . '
' . t('Note: When you return to this page, this box will be unchecked. This is because this setting is a trigger, not a persistant state.'), '#weight' => -1, ); $form['name']['#weight'] = -2; $form['#submit'][] = 'force_password_change_administer_role'; } elseif($form_id == 'user_profile_form') { global $user; if(user_access('Administer force password change', $user)) { $form['account']['name']['#weight'] = -2; $form['account']['mail']['#weight'] = -1; $form['account']['password']['#weight'] = -1; $form['account']['password']['pass'] = $form['account']['pass']; unset($form['account']['pass']); if($user->uid != $form['_account']['#value']->uid) { $form['account']['password']['force_password_change'] = array ( '#type' => 'checkbox', '#title' => t('Force this user to change their password'), '#description' => t('If this box is checked, the user will be forced to change their password. If the user is signed in, they will be forced to change their password on their next page load. If they are not signed in, they will be forced to change their password the next time they log in.') . '
' . t('Note: This box will be unchecked each time the page is loaded, as it is a trigger, not a persistent state.'), ); } $force_password_data = db_fetch_array(db_query('SELECT last_password_change, last_force FROM {force_password_change_users} WHERE uid = %d', $form['_account']['#value']->uid)); $password_stats = '

' . t('Password Stats:') . '

'; $password_stats .= ''; $form['account']['password']['password_stats'] = array ( '#value' => $password_stats, ); } $form['pending_force_password_change'] = array ( '#type' => 'value', '#value' => $form['_account']['#value']->force_password_change ); } if($form_id == 'user_register') { if ($form['account']) { $use_form = &$form['account']; } else { $use_form = &$form; } $use_form['name']['#weight'] = -2; $use_form['mail']['#weight'] = -1; $use_form['password']['#weight'] = -1; $use_form['password']['pass'] = $form['account']['pass']; $use_form['password']['force_password_change'] = $form['force_password_change']; unset($use_form['pass']); unset($form['force_password_change']); } } /** * Implementation of hook_theme() */ function force_password_change_theme() { return array ( 'force_password_change_new_role_form' => array ( 'arguments' => array ( 'form' => NULL, ), 'file' => 'force_password_change_pages.inc', ), 'force_password_change_settings' => array ( 'arguments' => array ( 'form' => NULL, ), 'file' => 'force_password_change_pages.inc', ), 'force_password_change_expiry' => array ( 'arguments' => array ( 'form' => NULL, ), 'file' => 'force_password_change_pages.inc', ), ); } /** * This function is called after a new role has been added to the system. * It creates a new row in the {force_password_change_roles} table for the role that has been created */ function force_password_change_add_role($form, &$form_state) { $rid = db_result(db_query('SELECT rid FROM {role} WHERE name = "%s"', $form_state['values']['name'])); db_query('INSERT INTO {force_password_change_roles} (rid) VALUES (%d)', $rid); } /** * This function is called on the role edit page, and serves one of two functions: * 1) It deletes the relevant row from the {force_password_changes_roles} table for the role that has been deleted * Or * 2) Forces the users in that role to chage their password if the applicable checkbox is checked. */ function force_password_change_administer_role($form, &$form_state) { if($form_state['values']['op'] == $form_state['values']['delete']) { db_query('DELETE FROM {force_password_change_roles} WHERE rid = %d', $form_state['values']['rid']); } elseif($form_state['values']['op'] == $form_state['values']['submit'] && $form_state['values']['force_password_change']) { $uids = array(); $db_uids = db_query ( 'SELECT uid ' . 'FROM {users_roles} ' . 'WHERE rid = %d', $form_state['values']['rid'] ); while($uid = db_fetch_array($db_uids)) { $uids[] = $uid['uid']; } $uid_list = implode(', ', $uids); if(strlen($uid_list)) { db_query ( 'UPDATE {users} ' . 'SET force_password_change = 1 ' . 'WHERE uid IN (%s)', $uid_list ); db_query ( 'UPDATE {force_password_change_users} ' . 'SET last_force = %d ' . 'WHERE uid IN (%s)', time(), $uid_list ); } db_query ( 'UPDATE {force_password_change_roles} ' . 'SET last_force = %d ' . 'WHERE rid = %d ', time(), $form_state['values']['rid'] ); drupal_set_message(t('Users in this role will be required to immediately change their password')); } }