password_policy.install in Password Policy 7
Same filename and directory in other branches
Password Policy module installation and upgrade code.
File
password_policy.installView source
<?php
/**
* @file
* Password Policy module installation and upgrade code.
*/
/**
* Implements hook_schema().
*/
function password_policy_schema() {
return array(
'password_policy' => array(
'description' => 'Stores password policies.',
'fields' => array(
'pid' => array(
'description' => 'Primary Key: Unique password policy ID.',
'type' => 'serial',
'not null' => TRUE,
),
'name' => array(
'description' => 'The name of the policy.',
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'default' => '',
),
'description' => array(
'description' => 'The description of the policy.',
'type' => 'varchar',
'length' => 255,
'default' => '',
),
'enabled' => array(
'description' => 'Whether the policy is enabled.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
),
'constraints' => array(
'description' => 'The policy\'s serialized constraints.',
'type' => 'varchar',
'length' => 1024,
'not null' => TRUE,
'default' => '',
'serialize' => TRUE,
),
'created' => array(
'description' => 'Timestamp for when the policy was created.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'expiration' => array(
'description' => 'The passwords will expire after this number of days.',
'type' => 'int',
'default' => 0,
),
'warning' => array(
'description' => 'Comma separated list of days when warning is sent out.',
'type' => 'varchar',
'length' => 64,
),
'weight' => array(
'description' => 'Weight of the policy, used to order active policies.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array(
'pid',
),
'unique keys' => array(
'name' => array(
'name',
),
),
),
'password_policy_history' => array(
'description' => 'Stores user\'s old password hashes.',
'fields' => array(
'pid' => array(
'description' => 'Primary Key: Unique password policy users ID.',
'type' => 'serial',
'not null' => TRUE,
),
'uid' => array(
'description' => 'User\'s {users}.uid.',
'type' => 'int',
'not null' => TRUE,
),
'pass' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'User\'s password (hashed).',
),
'created' => array(
'description' => 'Timestamp for when the policy was created.',
'type' => 'int',
'not null' => TRUE,
),
),
'foreign keys' => array(
'password_policy' => array(
'table' => 'password_policy',
'columns' => array(
'pid' => 'pid',
),
),
'user' => array(
'table' => 'users',
'columns' => array(
'uid' => 'uid',
),
),
),
'indexes' => array(
'uid' => array(
'uid',
),
),
'primary key' => array(
'pid',
),
),
'password_policy_expiration' => array(
'description' => 'Stores users password expiration data.',
'fields' => array(
'pid' => array(
'description' => 'Primary Key: Unique password policy expirations ID.',
'type' => 'serial',
'not null' => TRUE,
),
'uid' => array(
'description' => 'User\'s {users}.uid.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'warning' => array(
'description' => 'Timestamp for when the warning was shown.',
'type' => 'int',
),
'blocked' => array(
'description' => 'Timestamp for when the user was blocked.',
'type' => 'int',
),
'unblocked' => array(
'description' => 'Timestamp for when the user was unblocked.',
'type' => 'int',
),
),
'primary key' => array(
'pid',
),
'foreign keys' => array(
'password_policy' => array(
'table' => 'password_policy',
'columns' => array(
'pid' => 'pid',
),
),
'role' => array(
'table' => 'role',
'columns' => array(
'rid' => 'rid',
),
),
),
'indexes' => array(
'uid' => array(
'uid',
),
),
),
'password_policy_force_change' => array(
'description' => 'Forced password reset status.',
'fields' => array(
'uid' => array(
'type' => 'int',
'not null' => TRUE,
),
'force_change' => array(
'type' => 'int',
'default' => 0,
),
),
'foreign keys' => array(
'user' => array(
'table' => 'users',
'columns' => array(
'uid' => 'uid',
),
),
),
'indexes' => array(
'uid' => array(
'uid',
),
),
'primary key' => array(
'uid',
),
),
'password_policy_role' => array(
'description' => 'Links policies with roles.',
'fields' => array(
'pid' => array(
'description' => 'Policy ID.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'rid' => array(
'description' => 'Role ID.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
),
'foreign keys' => array(
'password_policy' => array(
'table' => 'password_policy',
'columns' => array(
'pid' => 'pid',
),
),
'role' => array(
'table' => 'role',
'columns' => array(
'rid' => 'rid',
),
),
),
'primary key' => array(
'rid',
'pid',
),
),
'password_policy_excluded_authentication_modules' => array(
'description' => 'Authentication modules to be excluded from specified policies.',
'fields' => array(
'pid' => array(
'description' => 'Policy ID.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'module' => array(
'description' => 'Module.',
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
),
),
'foreign keys' => array(
'password_policy' => array(
'table' => 'password_policy',
'columns' => array(
'pid' => 'pid',
),
),
'module' => array(
'table' => 'authmap',
'columns' => array(
'module' => 'module',
),
),
),
'primary key' => array(
'module',
'pid',
),
),
);
}
/**
* Implements hook_enable().
*/
function password_policy_enable() {
drupal_set_message(t('Password policy module successfully installed. Please review the available <a href="@settings">configuration settings</a>.', array(
'@settings' => url('admin/config/people/password_policy'),
)));
}
/**
* Implements hook_install().
*/
function password_policy_install() {
$query = db_select('users', 'u')
->fields('u', array(
'uid',
))
->distinct()
->condition('u.uid', 0, '>');
db_insert('password_policy_force_change')
->fields(array(
'uid',
))
->from($query)
->execute();
}
/**
* Implements hook_uninstall().
*/
function password_policy_uninstall() {
variable_del('password_policy_admin');
variable_del('password_policy_begin');
variable_del('password_policy_block');
variable_del('password_policy_show_restrictions');
variable_del('password_policy_warning_subject');
variable_del('password_policy_warning_body');
variable_del('password_policy_new_login_change');
variable_del('password_policy_force_change_reset');
variable_del('password_policy_force_change_by_mail');
variable_del('password_policy_force_change_path');
variable_del('password_policy_force_change_extra_allowed_paths');
variable_del('password_policy_expired_account_entries');
}
/**
* Remove unused 'name' column from {password_policy_role}.
*/
function password_policy_update_7000() {
db_drop_field('password_policy_role', 'name');
db_drop_unique_key('password_policy_role', 'name');
}
/**
* The implementation of password_policy_update_7001() has been removed.
*
* Do not re-implement it. hook_update_N() functions should not be renumbered.
*/
/**
* The implementation of password_policy_update_7002() has been removed.
*
* Do not re-implement it. hook_update_N() functions should not be renumbered.
*/
/**
* Notify of change to username constraint behavior.
*/
function password_policy_update_7100() {
return t('The username constraint has changed to disallow passwords containing the username in addition to passwords matching the username.');
}
/**
* Update schema left unchanged from D6 -> D7 migration.
*/
function password_policy_update_7101() {
db_change_field('password_policy', 'expiration', 'expiration', array(
'description' => 'The passwords will expire after this number of days.',
'type' => 'int',
'default' => 0,
), array());
db_change_field('password_policy_history', 'pass', 'pass', array(
'description' => 'User\'s password (hashed).',
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
), array());
}
/**
* Convert any D6 password hashes in history to D7 format.
*
* This may be a lengthy process, and is performed batch-wise.
*
* Code mostly copied from user_update_7000(), which updates user password
* hashes upon D6 -> D7 migration.
*
* @see user_update_7000()
*/
function password_policy_update_7102(&$sandbox) {
// Ignore Coder warning to minimize differences versus user_update_7000().
// @ignore sniffer_commenting_inlinecomment_spacingbefore:function
// @codingStandardsIgnoreStart
$sandbox['#finished'] = 0;
// Multi-part update.
if (!isset($sandbox['password_from'])) {
$sandbox['password_from'] = 0;
$sandbox['password_count'] = db_query('SELECT COUNT(pid) FROM {password_policy_history}')
->fetchField();
}
else {
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
// Hash again all current hashed passwords.
$has_rows = FALSE;
// Update this many per page load.
$count = 1000;
$result = db_query_range('SELECT pid, pass FROM {password_policy_history} ORDER BY pid', $sandbox['password_from'], $count);
foreach ($result as $row) {
$has_rows = TRUE;
// If the $row->pass value is not a MD5 hash (a 32 character
// hexadecimal string) then skip it.
if (!preg_match('/^[0-9a-f]{32}$/', $row->pass)) {
continue;
}
$new_hash = user_hash_password($row->pass);
if ($new_hash) {
// Indicate an updated password.
$new_hash = 'U' . $new_hash;
db_update('password_policy_history')
->fields(array(
'pass' => $new_hash,
))
->condition('pid', $row->pid)
->execute();
}
}
$sandbox['#finished'] = $sandbox['password_count'] == 0 ? 1 : $sandbox['password_from'] / $sandbox['password_count'];
$sandbox['password_from'] += $count;
if (!$has_rows) {
$sandbox['#finished'] = 1;
return t('User passwords in Password Policy history rehashed to improve security');
}
}
// @codingStandardsIgnoreEnd
}
/**
* Convert expiration warning e-mail tokens to Drupal 7 format.
*/
function password_policy_update_7103() {
$variables = array(
'password_policy_warning_subject',
'password_policy_warning_body',
);
foreach ($variables as $variable) {
_password_policy_convert_variable_tokens_d6_to_d7($variable);
}
}
/**
* Converts tokens in a Password Policy string variable to Drupal 7 format.
*
* @param string $variable
* Variable name.
*/
function _password_policy_convert_variable_tokens_d6_to_d7($variable) {
$value = variable_get($variable, FALSE);
if ($value) {
$value = _password_policy_replace_d6_with_d7_tokens($value);
variable_set($variable, $value);
}
}
/**
* Replaces D6 tokens in a Password Policy string with D7 tokens.
*/
function _password_policy_replace_d6_with_d7_tokens($subject) {
$d6_to_d7_tokens = _password_policy_get_d6_to_d7_tokens_mapping();
$d6_tokens = array_keys($d6_to_d7_tokens);
$d7_tokens = array_values($d6_to_d7_tokens);
return str_replace($d6_tokens, $d7_tokens, $subject);
}
/**
* Gets D6-to-D7 mapping for tokens used by the Password Policy module.
*
* @see user_update_7017()
*/
function _password_policy_get_d6_to_d7_tokens_mapping() {
// D6-to-D7 mapping for tokens that are used by User module e-mails. Copied
// from user_update_7017().
$user_email_tokens = array(
'!site' => '[site:name]',
'!username' => '[user:name]',
'!mailto' => '[user:mail]',
'!login_uri' => '[site:login-url]',
'!uri_brief' => '[site:url-brief]',
'!login_url' => '[user:one-time-login-url]',
'!uri' => '[site:url]',
'!date' => '[date:medium]',
'!password' => '',
);
// D6-to-D7 mapping for Password Policy tokens.
$password_policy_email_tokens = array(
'!days_left' => '[password-policy:days-left]',
'!edit_uri' => '[password-policy:password-edit-url]',
);
// Combined D6-to-D7 mapping for tokens.
$tokens = array_merge($user_email_tokens, $password_policy_email_tokens);
return $tokens;
}
/**
* Preserve "Admin (UID=1) password expires" setting.
*
* For increased security, the admin (UID=1) password is no longer exempt from
* password expiration by default. That is, "Admin (UID=1) password expires" is
* now checked by default.
*
* This database update will keep the current setting so that the change in the
* default will have no effect on existing installations.
*/
function password_policy_update_7104() {
$current_setting = variable_get('password_policy_admin', 0);
variable_set('password_policy_admin', $current_setting);
}
/**
* Improve naming of database field.
*
* Rename "policy" of {password_policy} to "constraints".
*/
function password_policy_update_7106() {
$table_name = 'password_policy';
$old_field_name = 'policy';
$new_field_name = 'constraints';
$field_spec = array(
'description' => 'The policy\'s serialized constraints.',
'type' => 'varchar',
'length' => 1024,
'not null' => TRUE,
'default' => '',
'serialize' => TRUE,
);
db_change_field($table_name, $old_field_name, $new_field_name, $field_spec);
}
/**
* Add primary key to {password_policy_force_change}.
*/
function password_policy_update_7107() {
db_add_primary_key('password_policy_force_change', array(
'uid',
));
}
/**
* Rename "Complexity" constraint to "Character Types".
*/
function password_policy_update_7108() {
$result = db_query('SELECT pid, constraints FROM {password_policy}');
foreach ($result as $row) {
$pid = $row->pid;
$constraints = $row->constraints;
$constraints = unserialize($constraints);
if (isset($constraints['complexity'])) {
$constraints['character_types'] = $constraints['complexity'];
unset($constraints['complexity']);
$constraints = serialize($constraints);
db_update('password_policy')
->fields(array(
'constraints' => $constraints,
))
->condition('pid', $pid)
->execute();
}
}
}
/**
* Add {password_policy_excluded_authentication_modules} table.
*/
function password_policy_update_7109() {
$schema['password_policy_excluded_authentication_modules'] = array(
'description' => 'Authentication modules to be excluded from specified policies.',
'fields' => array(
'pid' => array(
'description' => 'Policy ID.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
'module' => array(
'description' => 'Module.',
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
),
),
'foreign keys' => array(
'password_policy' => array(
'table' => 'password_policy',
'columns' => array(
'pid' => 'pid',
),
),
'module' => array(
'table' => 'authmap',
'columns' => array(
'module' => 'module',
),
),
),
'primary key' => array(
'module',
'pid',
),
);
db_create_table('password_policy_excluded_authentication_modules', $schema['password_policy_excluded_authentication_modules']);
}
/**
* Clear schema cache to prevent Features errors.
*
* When a site is using the Features module and is upgraded from a version of
* Password Policy before 7.x-1.10, it is possible that Features will attempt
* to define some functions twice, resulting in PHP errors. Clearing the schema
* cache prevents that from occurring.
*/
function password_policy_update_7110() {
cache_clear_all('schema', 'cache', TRUE);
}
Functions
Name | Description |
---|---|
password_policy_enable | Implements hook_enable(). |
password_policy_install | Implements hook_install(). |
password_policy_schema | Implements hook_schema(). |
password_policy_uninstall | Implements hook_uninstall(). |
password_policy_update_7000 | Remove unused 'name' column from {password_policy_role}. |
password_policy_update_7100 | Notify of change to username constraint behavior. |
password_policy_update_7101 | Update schema left unchanged from D6 -> D7 migration. |
password_policy_update_7102 | Convert any D6 password hashes in history to D7 format. |
password_policy_update_7103 | Convert expiration warning e-mail tokens to Drupal 7 format. |
password_policy_update_7104 | Preserve "Admin (UID=1) password expires" setting. |
password_policy_update_7106 | Improve naming of database field. |
password_policy_update_7107 | Add primary key to {password_policy_force_change}. |
password_policy_update_7108 | Rename "Complexity" constraint to "Character Types". |
password_policy_update_7109 | Add {password_policy_excluded_authentication_modules} table. |
password_policy_update_7110 | Clear schema cache to prevent Features errors. |
_password_policy_convert_variable_tokens_d6_to_d7 | Converts tokens in a Password Policy string variable to Drupal 7 format. |
_password_policy_get_d6_to_d7_tokens_mapping | Gets D6-to-D7 mapping for tokens used by the Password Policy module. |
_password_policy_replace_d6_with_d7_tokens | Replaces D6 tokens in a Password Policy string with D7 tokens. |