Enable oauth2 login
Replace openid provider with oauth2. Oauth2 provides more details about user profile and contains profile picture url. This patch contains the groups_oauth2 module, an oauth2 authorization implementation for Drupal written for openstackid.org provider. See module's readme for required variable settings. Change-Id: I30fc363d60a5f679194dfd0f9d6c6453f783f9aa
This commit is contained in:
parent
d86a9875ab
commit
b9db93a633
@ -152,6 +152,8 @@ dependencies[] = groups_footer
|
||||
dependencies[] = groups_homepage
|
||||
dependencies[] = groups_common
|
||||
dependencies[] = groups_auth
|
||||
dependencies[] = groups_oauth2
|
||||
dependencies[] = groups_oauth2_picture
|
||||
dependencies[] = groups_feeds
|
||||
dependencies[] = groups_events
|
||||
dependencies[] = groups_events_pages
|
||||
|
@ -181,6 +181,16 @@ function groups_update_7107() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable groups_oauth2 modules.
|
||||
*/
|
||||
function groups_update_7108() {
|
||||
if ((!module_exists('groups_oauth2')) && (!module_exists('groups_oauth2_picture'))) {
|
||||
module_enable(array('groups_oauth2', 'groups_oauth2_picture'));
|
||||
drupal_flush_all_caches();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add markdown filter with permissions.
|
||||
*/
|
||||
|
@ -36,6 +36,10 @@ function groups_auth_menu_alter(&$items) {
|
||||
$items['user/%user/openid']['page callback'] = 'groups_auth_user_identities';
|
||||
$items['user/%user/openid']['access callback'] = 'groups_auth_role_access';
|
||||
$items['user/%user/openid']['access arguments'] = array('administrator');
|
||||
$items['user/%user/edit-profile']['access arguments'] = array('administrator');
|
||||
$items['user/%user/edit-profile']['access callback'] = 'groups_auth_role_access';
|
||||
$items['user/%user/edit']['access arguments'] = array('administrator');
|
||||
$items['user/%user/edit']['access callback'] = 'groups_auth_role_access';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,10 +142,14 @@ function groups_auth_form_user_register_form_alter(&$form, &$form_state) {
|
||||
*/
|
||||
|
||||
function groups_auth_login() {
|
||||
$return_to = url('openid/authenticate',
|
||||
array('absolute' => TRUE, 'query' => array('destination' => '<front>')));
|
||||
$openid_url = variable_get('groups_openid_provider', 'https://openstackid-dev.openstack.org');
|
||||
openid_begin($openid_url, $return_to, array());
|
||||
if (module_exists('groups_oauth2')) {
|
||||
groups_oauth2_user_login_submit();
|
||||
} else {
|
||||
$return_to = url('openid/authenticate',
|
||||
array('absolute' => TRUE, 'query' => array('destination' => '<front>')));
|
||||
$openid_url = variable_get('groups_openid_provider', 'https://openstackid-dev.openstack.org');
|
||||
openid_begin($openid_url, $return_to, array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,6 +185,15 @@ function groups_auth_commons_utility_links_alter(&$links) {
|
||||
if (isset($links['signup'])) {
|
||||
$links['signup']['href'] = 'login';
|
||||
}
|
||||
if (isset($links['name'])) {
|
||||
$links['name']['title'] = t('View profile');
|
||||
}
|
||||
if (isset($links['logout'])) {
|
||||
$links['logout']['weight'] = 1000;
|
||||
}
|
||||
if (isset($links['settings'])) {
|
||||
unset($links['settings']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
28
modules/groups/groups_oauth2/README.txt
Normal file
28
modules/groups/groups_oauth2/README.txt
Normal file
@ -0,0 +1,28 @@
|
||||
Description
|
||||
-----------
|
||||
|
||||
This module provides a basic oauth2 authentication for openstackid.org provider. Supports
|
||||
fetching of first and family name, and fetch profile picture url. As openstackid provider
|
||||
requires https communication, and the profile image assets not available through ssl,
|
||||
the groups_auth2 module supports fetching of profile pictures into a local directory.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
Drupal 7.x
|
||||
Properly configured Oauth2 provider.
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
oauth2_fetch_profile_picture:boolean
|
||||
If set to TRUE, downloads profile picture during login into the public://profile-images
|
||||
directory. Default value is FALSE.
|
||||
|
||||
groups_oauth2_provider:string
|
||||
Contains the url of oauth2 provider. For openstackid, set it to https://openstackid.org
|
||||
|
||||
groups_oauth2_client_id:string
|
||||
The client id assigned for this specific application.
|
||||
|
||||
groups_oauth2_client_secret:string
|
||||
The client secret assigned for the client_id.
|
40
modules/groups/groups_oauth2/groups_oauth2.admin.inc
Normal file
40
modules/groups/groups_oauth2/groups_oauth2.admin.inc
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Menu callback: displays the groups_oauth2 module settings page.
|
||||
*
|
||||
* @ingroup forms
|
||||
*
|
||||
* @see groups_oauth2_admin_settings_validate()
|
||||
*/
|
||||
function groups_oauth2_admin_settings($form) {
|
||||
$form['groups_oauth2_provider'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('OAuth2 Provider URL'),
|
||||
'#default_value' => variable_get('groups_oauth2_provider'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['groups_oauth2_client_id'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('OAuth2 Client ID'),
|
||||
'#default_value' => variable_get('groups_oauth2_client_id'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['groups_oauth2_client_secret'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('OAuth2 Client Secret'),
|
||||
'#default_value' => variable_get('groups_oauth2_client_secret'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['#validate'][] = 'groups_oauth2_admin_settings_validate';
|
||||
return system_settings_form($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation handler for groups_oauth2_admin_settings().
|
||||
*/
|
||||
function groups_oauth2_admin_settings_validate($form, &$form_state) {
|
||||
if (valid_url($form_state['values']['groups_oauth2_provider'], TRUE) == FALSE) {
|
||||
form_set_error('allmyles_wsclient', t('The provider url value must be a valid url.'));
|
||||
}
|
||||
}
|
24
modules/groups/groups_oauth2/groups_oauth2.api.php
Normal file
24
modules/groups/groups_oauth2/groups_oauth2.api.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* This file contains API documentation for the Groups OAuth2 module. Note that
|
||||
* all of this code is merely for example purposes, it is never executed when
|
||||
* using the Groups OAuth2 module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hook to map account data to a Drupal user after connecting.
|
||||
*
|
||||
* This hook is fired after a user account is created by groups
|
||||
* oauth2 module.
|
||||
*
|
||||
* @param $account
|
||||
* A user account array.
|
||||
* @param $userinfo
|
||||
* A user profile returned by oauth2 provider.
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
function hook_oauth2_user_save(&$account, $userinfo) {
|
||||
|
||||
}
|
7
modules/groups/groups_oauth2/groups_oauth2.info
Normal file
7
modules/groups/groups_oauth2/groups_oauth2.info
Normal file
@ -0,0 +1,7 @@
|
||||
name = Groups OAuth2
|
||||
description = "Groups Authentication module - uses OAuth2. Handle authentication to openstackid.org service"
|
||||
core = 7.x
|
||||
package = Groups - Authentication
|
||||
|
||||
version = "7.x-1.0"
|
||||
project = "groups"
|
320
modules/groups/groups_oauth2/groups_oauth2.module
Normal file
320
modules/groups/groups_oauth2/groups_oauth2.module
Normal file
@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_menu()
|
||||
*/
|
||||
function groups_oauth2_menu() {
|
||||
$items['oauth2/response'] = array(
|
||||
'page callback' => 'groups_oauth2_response_handler',
|
||||
'access callback' => TRUE,
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items['admin/config/services/oauth2'] = array(
|
||||
'title' => 'Oauth2 Settings',
|
||||
'description' => 'OpenStackID Oauth2 settings',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('groups_oauth2_admin_settings'),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'file' => 'groups_oauth2.admin.inc',
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter()
|
||||
*
|
||||
* Add Login with OpenStackID button to login form.
|
||||
*/
|
||||
function groups_oauth2_form_user_login_alter(&$form, &$form_state, $form_id) {
|
||||
if ($form_id == 'user_login' || $form_id == 'user_login_block') {
|
||||
$form['submit_groups'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Login with OpenStackID'),
|
||||
'#submit' => array('groups_oauth2_user_login_submit'),
|
||||
'#limit_validation_errors' => array(),
|
||||
'#weight' => 1000,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle login form submit.
|
||||
*
|
||||
* Redirect to oauth2 site and request an authorization code.
|
||||
*/
|
||||
function groups_oauth2_user_login_submit() {
|
||||
if (!_groups_oauth2_validate_provider_settings()) {
|
||||
return FALSE;
|
||||
}
|
||||
if (isset($_GET['destination'])) {
|
||||
unset($_GET['destination']);
|
||||
}
|
||||
$redirect_uri = url('oauth2/response', array('https' => FALSE, 'absolute' => TRUE));
|
||||
$url = _groups_oauth2_authorize_url('code', $redirect_uri, 'auto', 'profile email');
|
||||
drupal_goto($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Oauth2 response handler callback.
|
||||
*
|
||||
* Process to authorization code, invoke token and login or create
|
||||
* a new user.
|
||||
*/
|
||||
function groups_oauth2_response_handler() {
|
||||
if (isset($_GET['code'])) {
|
||||
if (!_groups_oauth2_validate_provider_settings()) {
|
||||
return FALSE;
|
||||
}
|
||||
$redirect_uri = url('oauth2/response', array('https' => $GLOBALS['is_https'], 'absolute' => TRUE));
|
||||
$response = _groups_oauth2_request_token('authorization_code', $_GET['code'], $redirect_uri);
|
||||
if ($response->code == 200) {
|
||||
$data = json_decode($response->data);
|
||||
$userinfo = groups_oauth2_get_userinfo($data->access_token);
|
||||
if (!$userinfo) {
|
||||
drupal_set_message(t("Failed to retrieve user information"), 'error');
|
||||
drupal_goto();
|
||||
return;
|
||||
}
|
||||
$username = check_plain(strtolower($userinfo->name).'-'.strtolower($userinfo->family_name));
|
||||
$query = "SELECT uid FROM {users} WHERE name = :name";
|
||||
$uid = db_query($query, array(':name' => $username))->fetchField();
|
||||
$i = 0;
|
||||
while ($uid) {
|
||||
$i++;
|
||||
$uid = db_query($query, array(':name' => ($username . $i)))->fetchField();
|
||||
}
|
||||
if ($i > 0) {
|
||||
$username = $username . $i;
|
||||
}
|
||||
$account = groups_oauth2_find_existing_user($userinfo);
|
||||
if (!$account) {
|
||||
$edit = array(
|
||||
'name' => $username,
|
||||
'mail' => $userinfo->email,
|
||||
'init' => $userinfo->email,
|
||||
'status' => 1,
|
||||
'timezone' => variable_get('date_default_timezone'),
|
||||
'data' => array(
|
||||
'oauth2_fullname' => check_plain($userinfo->name.' '.$userinfo->family_name),
|
||||
),
|
||||
);
|
||||
$account = user_save(NULL, $edit);
|
||||
// Allow other modules to manipulate the user information after save.
|
||||
foreach (module_implements('oauth2_user_save') as $module) {
|
||||
$function = $module . '_oauth2_user_save';
|
||||
$function($account, $userinfo);
|
||||
}
|
||||
}
|
||||
$form_state['uid'] = $account->uid;
|
||||
user_login_submit(array(), $form_state);
|
||||
drupal_goto('user/' . $account->uid);
|
||||
} else {
|
||||
$data = json_decode($response->data);
|
||||
drupal_set_message(t("The account is not authenticated. Reason: @error",
|
||||
array('@error' => is_object($data) ? $data->error : 'Not known.')), 'error');
|
||||
}
|
||||
}
|
||||
drupal_goto();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch user info from oauth2 server.
|
||||
*/
|
||||
function groups_oauth2_get_userinfo($access_token) {
|
||||
$query = array('access_token' => $access_token);
|
||||
$request_url = url(variable_get('groups_oauth2_provider').'/api/v1/users/me', array('query' => $query));
|
||||
$response = drupal_http_request($request_url);
|
||||
if ($response->code == 200) {
|
||||
return json_decode($response->data);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a Drupal user by oauth2 user info.
|
||||
*/
|
||||
function groups_oauth2_find_existing_user($userinfo) {
|
||||
if ($user = user_load_by_mail($userinfo->email)) {
|
||||
return $user;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure groups oauth2 authentication variables.
|
||||
*
|
||||
* @return boolean
|
||||
* Return TRUE if groups_oauth2_provider, groups_oauth2_client_id and
|
||||
* groups_oauth2_client_secret are set, otherwise throw an error message.
|
||||
*/
|
||||
function _groups_oauth2_validate_provider_settings() {
|
||||
$provider_url = variable_get('groups_oauth2_provider');
|
||||
$client_id = variable_get('groups_oauth2_client_id');
|
||||
$client_secret = variable_get('groups_oauth2_client_secret');
|
||||
if ((!isset($provider_url)) || (!isset($client_id)) || (!isset($client_secret))) {
|
||||
drupal_set_message(t('Groups oauth2 provider not properly configured.'), 'warning');
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build oauth2 authorization url.
|
||||
*
|
||||
* @param string $response_type
|
||||
* Oauth2 response type, use code for basic flow
|
||||
* @param string $redirect_uri
|
||||
* Determines where the response will be sent
|
||||
* @param string $approval_prompt
|
||||
* Approval prompt, set to auto
|
||||
* @param string $scope
|
||||
* Aouth2 scope requesting access for
|
||||
* @return string
|
||||
* The full url for authorization code request.
|
||||
*/
|
||||
function _groups_oauth2_authorize_url($response_type, $redirect_uri, $approval_prompt, $scope) {
|
||||
$params = array(
|
||||
'response_type' => $response_type,
|
||||
'client_id' => variable_get('groups_oauth2_client_id'),
|
||||
'redirect_uri' => $redirect_uri,
|
||||
'approval_prompt' => $approval_prompt,
|
||||
'scope' => $scope,
|
||||
);
|
||||
$provider_url = variable_get('groups_oauth2_provider');
|
||||
return $provider_url.'/oauth2/auth?'.http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a token request based on authorization code to oauth2 provider.
|
||||
*
|
||||
* @param string $grant_type
|
||||
* Set to 'authorization_code'
|
||||
* @param string $code
|
||||
* Code received from authorization request.
|
||||
* @param string $redirect_uri
|
||||
* The redirect uri set for this application.
|
||||
* @return [type]
|
||||
* Http response of token request.
|
||||
*/
|
||||
function _groups_oauth2_request_token($grant_type, $code, $redirect_uri) {
|
||||
$params = array(
|
||||
'grant_type' => $grant_type,
|
||||
'code' => $code,
|
||||
'redirect_uri' => $redirect_uri,
|
||||
'client_id' => variable_get('groups_oauth2_client_id'),
|
||||
'client_secret' => variable_get('groups_oauth2_client_secret'),
|
||||
);
|
||||
$elements = array();
|
||||
foreach ($params as $k => $v) {
|
||||
$elements[] = "$k=$v";
|
||||
}
|
||||
$data = implode('&', $elements);
|
||||
$options = array(
|
||||
'method' => 'POST',
|
||||
'data' => $data,
|
||||
'timeout' => 15,
|
||||
'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'),
|
||||
);
|
||||
$provider_url = variable_get('groups_oauth2_provider');
|
||||
return drupal_http_request($provider_url.'/oauth2/token', $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the profile picture filename from url.
|
||||
*/
|
||||
function _groups_oauth2_get_profile_picture_filename($url) {
|
||||
$parts = parse_url($url);
|
||||
$basename = end(explode('/', $parts['path']));
|
||||
return 'public://profile-images/'.$basename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function groups_oauth2_theme() {
|
||||
return array(
|
||||
'groups_oauth2_user_picture_override' => array(
|
||||
'variables' => array(
|
||||
'account' => NULL,
|
||||
'picture_url' => NULL,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme_registry_alter(), override
|
||||
* @param [type] $theme_registry [description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
function groups_oauth2_theme_registry_alter(&$theme_registry) {
|
||||
// Re-register the original theme function under a new name.
|
||||
$theme_registry['groups_oauth2_user_picture_orig'] = $theme_registry['user_picture'];
|
||||
// Override theme username
|
||||
$theme_registry['user_picture'] = array(
|
||||
'arguments' => array('account' => NULL),
|
||||
'function' => 'groups_oauth2_theme_user_picture_override',
|
||||
'preprocess functions' => array(),
|
||||
'theme path' => drupal_get_path('module', 'groups_oauth2'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make rendering of Oauth2 user picture themeable
|
||||
*/
|
||||
function theme_groups_oauth2_user_picture_override($variables) {
|
||||
$picture_url = $variables['picture_url'];
|
||||
$account = $variables['account'];
|
||||
$image = theme('image', array('path' => $picture_url, 'alt' => $account->name));
|
||||
return '<div class="picture">' . $image . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Override user picture theme, and render oauth2 picture if available.
|
||||
*/
|
||||
function groups_oauth2_theme_user_picture_override($variables) {
|
||||
$account = $variables['account'];
|
||||
if (isset($account->data['oauth2_picture'])) {
|
||||
if (variable_get('oauth2_fetch_profile_picture', FALSE)) {
|
||||
$image_path = _groups_oauth2_get_profile_picture_filename($account->data['oauth2_picture']);
|
||||
$picture_url = file_create_url($image_path);
|
||||
} else {
|
||||
$picture_url = $account->data['oauth2_picture'];
|
||||
}
|
||||
$output = theme('groups_oauth2_user_picture_override', array('account' => $account, 'picture_url' => $picture_url));
|
||||
} else {
|
||||
$output = theme('groups_oauth2_user_picture_orig', array('account' => $account));
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_username_alter().
|
||||
*
|
||||
* @see realname_username_alter()
|
||||
*/
|
||||
function groups_oauth2_username_alter(&$name, $account) {
|
||||
static $in_username_alter = FALSE;
|
||||
if (empty($account->uid)) {
|
||||
// Don't alter anonymous users or objects that do not have any user ID.
|
||||
return;
|
||||
}
|
||||
// Name was loaded/generated via hook_user_load(), so re-use it.
|
||||
if (isset($account->data['oauth2_fullname'])) {
|
||||
if (drupal_strlen($account->data['oauth2_fullname'])) {
|
||||
$name = $account->data['oauth2_fullname'];
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Real name was not yet available for the account so we need to generate it.
|
||||
// Because tokens may call format_username() we need to prevent recursion.
|
||||
if (!$in_username_alter) {
|
||||
$in_username_alter = TRUE;
|
||||
// If $account->realname was undefined, then the user account object was
|
||||
// not properly loaded. We must enforce calling user_load().
|
||||
if ($oauth2_account = user_load($account->uid)) {
|
||||
groups_oauth2_username_alter($name, $oauth2_account);
|
||||
}
|
||||
$in_username_alter = FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
name = Groups OAuth2 Profile Picture
|
||||
description = "Profile Picture support for Groups OAuth2 authentication"
|
||||
core = 7.x
|
||||
package = Groups - Authentication
|
||||
|
||||
version = "7.x-1.0"
|
||||
project = "groups"
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*
|
||||
* Creates profile-images directory under site/default/files.
|
||||
*/
|
||||
function groups_oauth2_picture_install() {
|
||||
$destination = 'public://profile-images';
|
||||
if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
|
||||
throw new Exception("Unable to create directory $destination.");
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Implements hook_oauth2_user_save().
|
||||
*
|
||||
* Fetch profile picture from oauth2 provider and link it to
|
||||
* Drupal user account.
|
||||
*
|
||||
* @param $account
|
||||
* A user account array.
|
||||
* @param $userinfo
|
||||
* A user profile returned by oauth2 provider.
|
||||
* @return
|
||||
* None.
|
||||
*/
|
||||
function groups_oauth2_picture_oauth2_user_save(&$account, $userinfo) {
|
||||
if (variable_get('oauth2_fetch_profile_picture', FALSE)) {
|
||||
$image_path = _groups_oauth2_get_profile_picture_filename($userinfo->picture);
|
||||
$picture_result = drupal_http_request($userinfo->picture);
|
||||
$picture_file = file_save_data($picture_result->data, $image_path, FILE_EXISTS_REPLACE);
|
||||
$image_info = image_get_info($image_path);
|
||||
$file = new StdClass();
|
||||
$validators = array(
|
||||
'file_validate_is_image' => array(),
|
||||
);
|
||||
$errors = file_validate($picture_file, $validators);
|
||||
if (empty($errors)) {
|
||||
$picture_file->uid = $account->uid;
|
||||
$picture_file = file_save($picture_file);
|
||||
file_usage_add($picture_file, 'user', 'user', $account->uid);
|
||||
db_update('users')
|
||||
->fields(array(
|
||||
'picture' => $picture_file->fid,
|
||||
))
|
||||
->condition('uid', $account->uid)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
$account->data['oauth2_picture'] = $userinfo->picture;
|
||||
user_save($account);
|
||||
}
|
@ -49,7 +49,7 @@ function openstack_bootstrap_links__commons_utility_links(&$variables) {
|
||||
$variables['attributes']['class'][] = 'dropdown-menu-right';
|
||||
$output = '<div class="btn-group">';
|
||||
$output .= '<button class="btn dropdown-toggle" type="button" data-toggle="dropdown"><span class="glyphicon glyphicon-user"></span>
|
||||
'.$GLOBALS['user']->name.'<span class="caret"></span>
|
||||
'.format_username($user).'<span class="caret"></span>
|
||||
</button>';
|
||||
$output .= theme_links($variables);
|
||||
$output .= '</div>';
|
||||
|
Loading…
x
Reference in New Issue
Block a user