/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { global $is_https; // Read Settings. $settings = \social_login_get_settings(); $title = $settings['login_page_caption']; $containerid = 'social_login_providers_' . rand(99999, 9999999); \social_login_add_js_plugin($form, $settings['api_subdomain']); $current_uri = \social_login_get_current_url($is_https); $callback_uri = Url::fromRoute('social_login.core', [], array('absolute' => TRUE, 'query' => array('origin' => $current_uri)))->toString(); $provider_string = "\"". implode("\",\"", $settings['enabled_providers']) ."\""; $form['social_login_' . $containerid] = array( '#label' => $title, '#weight' => 0, // render the TWIG template, with it's variables and JS: '#theme' => 'provider_container', '#containerid' => $containerid, '#plugintype' => 'social_login', '#providers' => $provider_string, '#token' => '', '#callbackuri' => $callback_uri, // Caching: the cache tag is the callback uri (so we can redirect to the same page), so the url context is suitable: '#cache' => array( 'contexts' => array('url'), ), ); $renderer = \Drupal::service('renderer'); $renderer->addCacheableDependency($form, $callback_uri); return $form; }
public function buildForm(array $form, FormStateInterface $form_state) { $form['#attached'] = array ( 'library' => array ('social_login/configuration') ); // Read Settings. $settings = \social_login_get_settings(); // API Connection. $form['social_login_api_connection'] = [ '#type' => 'fieldset', '#title' => t('API Communication'), '#id' => 'social_login_api_connection', ]; // Default value for handler. if ($form_state->getValue(['http_handler'])) { $default = $form_state->getValue(['http_handler']); } elseif (!empty($settings['http_handler'])) { $default = $settings['http_handler']; } else { $default = 'curl'; } $form['social_login_api_connection']['http_handler'] = [ '#type' => 'select', '#title' => t('API Communication Handler'), '#description' => t('Either <a href="@link_curl" target="_blank">PHP cURL</a> or the <a href="@link_fsockopen" target="_blank">Drupal Guzzle client</a> must be available on your server.', [ '@link_curl' => 'http://www.php.net/manual/en/book.curl.php', '@link_fsockopen' => 'http://docs.guzzlephp.org/en/latest/', ]), '#options' => [ 'curl' => t('PHP cURL library'), 'fsockopen' => t('Drupal Guzzle client'), ], '#default_value' => $default, ]; // Default value for protocol. if ($form_state->getValue([ 'http_protocol' ])) { $default = $form_state->getValue(['http_protocol']); } elseif (!empty($settings['http_protocol'])) { $default = $settings['http_protocol']; } else { $default = 'https'; } $form['social_login_api_connection']['http_protocol'] = [ '#type' => 'select', '#title' => t('API Communication Protocol'), '#description' => t('Your firewall must allow outbound requests either on port 443/HTTPS or on port 80/HTTP.'), '#options' => [ 'https' => t('Port 443/HTTPS'), 'http' => t('Port 80/HTTP'), ], '#default_value' => $default, ]; // AutoDetect Button. $form['social_login_api_connection']['autodetect'] = [ '#type' => 'button', '#value' => t('Autodetect communication settings'), '#weight' => 30, '#ajax' => [ 'callback' => 'Drupal\social_login\Form\ajax_api_connection_autodetect', 'wrapper' => 'social_login_api_connection', 'method' => 'replace', 'effect' => 'fade', ], ]; // API Settings. $form['social_login_api_settings'] = [ '#type' => 'fieldset', '#title' => t('API Settings'), '#id' => 'social_login_api_settings', '#description' => t('<a href="@setup_social_login" target="_blank">Click here to create and view your API Credentials</a>', [ '@setup_social_login' => 'https://app.oneall.com/applications/' ]), ]; // API Subdomain. $form['social_login_api_settings']['api_subdomain'] = [ '#id' => 'api_subdomain', '#type' => 'textfield', '#title' => t('API Subdomain'), '#default_value' => (!empty($settings['api_subdomain']) ? $settings['api_subdomain'] : ''), '#size' => 60, '#maxlength' => 60, ]; // API Public Key. $form['social_login_api_settings']['api_key'] = [ '#id' => 'api_key', '#type' => 'textfield', '#title' => t('API Public Key'), '#default_value' => (!empty($settings['api_key']) ? $settings['api_key'] : ''), '#size' => 60, '#maxlength' => 60, ]; // API Private Key. $form['social_login_api_settings']['api_secret'] = [ '#id' => 'api_secret', '#type' => 'textfield', '#title' => t('API Private Key'), '#default_value' => (!empty($settings['api_secret']) ? $settings['api_secret'] : ''), '#size' => 60, '#maxlength' => 60, ]; // API Verify Settings Button. $form['social_login_api_settings']['verify'] = [ '#id' => 'social_login_check_api_button', '#type' => 'button', '#value' => t('Verify API Settings'), '#weight' => 1, '#ajax' => [ 'callback' => 'Drupal\social_login\Form\ajax_check_api_connection_settings', 'wrapper' => 'social_login_api_settings', 'method' => 'replace', 'effect' => 'fade', ], ]; // Side panel settings. // In D8, adding the user login block to side panel places the login form, and triggers the form hook. // For customization: need a OneAll block, that can be placed independently of the login block. /* $form['social_login_settings_side_panel'] = [ '#type' => 'fieldset', '#title' => t('Side Panel Settings'), ]; $form['social_login_settings_side_panel']['side_panel_icons'] = [ '#type' => 'select', '#title' => t('Social Login Icons'), '#description' => t('Allows the users to login/register with their social network account or with their already existing account.'), '#options' => [ 'above' => t('Show the Social Login icons above the existing login form'), 'below' => t('Show the Social Login icons below the existing login form (Default, recommended)'), 'disable' => t('Do not show the Social Login icons in the side panel'), ], '#default_value' => (empty($settings['side_panel_icons']) ? 'above' : $settings['side_panel_icons']), ]; $form['social_login_settings_side_panel']['side_panel_caption'] = [ '#type' => 'textfield', '#title' => t('Social Login Icons: Caption [Leave empty for none]'), '#default_value' => (!isset($settings['side_panel_caption']) ? t('Register/Login with:') : $settings['side_panel_caption']), '#size' => 60, '#maxlength' => 60, '#description' => t('This is the title displayed above the social network icons.'), ]; */ // Login page settings. $form['social_login_settings_login_page'] = [ '#type' => 'fieldset', '#title' => t('Login Page Settings'), ]; $form['social_login_settings_login_page']['login_page_icons'] = [ '#type' => 'select', '#title' => t('Social Login Icons'), '#description' => t('Allows the users to login either with their social network account or with their already existing account.'), '#options' => [ 'above' => t('Show the Social Login icons above the existing login form'), 'below' => t('Show the Social Login icons below the existing login form (Default, recommended)'), 'disable' => t('Do not show the Social Login icons on the login page'), ], '#default_value' => (empty($settings['login_page_icons']) ? 'below' : $settings['login_page_icons']), ]; $form['social_login_settings_login_page']['login_page_caption'] = [ '#type' => 'textfield', '#title' => t('Social Login Icons: Caption [Leave empty for none]'), '#default_value' => (!isset($settings['login_page_caption']) ? t('Login with:') : $settings['login_page_caption']), '#size' => 60, '#maxlength' => 60, '#description' => t('This is the title displayed above the social network icons.'), ]; // Registration page settings. $form['social_login_settings_registration_page'] = [ '#type' => 'fieldset', '#title' => t('Registration Page Settings'), ]; $form['social_login_settings_registration_page']['registration_page_icons'] = [ '#type' => 'select', '#title' => t('Social Login Icons'), '#description' => t('Allows the users to register by using either their social network account or by creating a new account.'), '#options' => [ 'above' => t('Show the Social Login icons above the existing login form (Default, recommended)'), 'below' => t('Show the Social Login icons below the existing login form'), 'disable' => t('Do not show the Social Login icons on the registration page'), ], '#default_value' => (empty($settings['registration_page_icons']) ? 'above' : $settings['registration_page_icons']), ]; $form['social_login_settings_registration_page']['registration_page_caption'] = [ '#type' => 'textfield', '#title' => t('Social Login Icons: Caption [Leave empty for none]'), '#default_value' => (!isset($settings['registration_page_caption']) ? t('Instantly register with:') : $settings['registration_page_caption']), '#size' => 60, '#maxlength' => 60, '#description' => t('This is the title displayed above the social network icons.'), ]; // Edit profile page settings. $form['social_login_settings_profile_page'] = [ '#type' => 'fieldset', '#title' => t('Edit Profile Page Settings'), ]; $form['social_login_settings_profile_page']['profile_page_icons'] = [ '#type' => 'select', '#title' => t('Social Login Icons'), '#description' => t('Allows the users to link a social network account to their regular account.'), '#options' => [ 'above' => t('Show the Social Login icons above the profile settings'), 'below' => t('Show the Social Login icons below the profile settings (Default, recommended)'), 'disable' => t('Do not show the Social Login icons on the profile page'), ], '#default_value' => (empty($settings['profile_page_icons']) ? 'below' : $settings['profile_page_icons']), ]; $form['social_login_settings_profile_page']['profile_page_caption'] = [ '#type' => 'textfield', '#title' => t('Social Login Icons: Caption [Leave empty for none]'), '#default_value' => (!isset($settings['profile_page_caption']) ? t('Link your account to a social network:') : $settings['profile_page_caption']), '#size' => 60, '#maxlength' => 60, '#description' => t('This is the title displayed above the social network icons.'), ]; // Block Settings. /* $form['social_login_settings_block'] = [ '#type' => 'fieldset', '#title' => t('Block Settings'), '#description' => t('Use the Structure\Blocks menu to add Social Login to any region of your theme.'), ]; $form['social_login_settings_block']['block_icons_loggedin'] = [ '#type' => 'select', '#title' => t('If the user is already logged in:'), '#options' => [ 'hide' => t('Hide the Social Login Block (Default, recommended)'), 'show' => t('Show the Social Login Block'), ], '#default_value' => (empty($settings['block_icons_loggedin']) ? 'hide' : $settings['block_icons_loggedin']), ]; */ // Account creation settings. $form['social_login_settings_account_creation'] = [ '#type' => 'fieldset', '#title' => t('Account creation settings'), ]; $form['social_login_settings_account_creation']['registration_approval'] = [ '#type' => 'select', '#title' => t('Do user that register with Social Login have to be approved by an administrator?'), '#description' => t('Manual approval should not be required as Social Login eliminates SPAM issues almost entirely.'), '#options' => [ 'inherit' => t('Use the system-wide setting from the Drupal account settings (Default)'), 'disable' => t('Automatically approve users that register with Social Login'), 'enable' => t(' Always require administrators to approve users that register with Social Login'), ], '#default_value' => (empty($settings['registration_approval']) ? 'inherit' : $settings['registration_approval']), ]; $form['social_login_settings_account_creation']['registration_retrieve_avatars'] = [ '#type' => 'select', '#title' => t('Retrieve the user picture from the social network when a user registers with Social Login?'), '#description' => t('Social Login grabs the user picture from the social network, saves it locally and uses it as avatar for the new account.'), '#options' => [ 'enable' => t('Yes, retrieve the user picture from the social network an use it as avatar for the user (Default)'), 'disable' => t('No, do not retrieve the user picture from the social network'), ], '#default_value' => (empty($settings['registration_retrieve_avatars']) ? 'enable' : $settings['registration_retrieve_avatars']), ]; $form['social_login_settings_account_creation']['registration_method'] = [ '#type' => 'select', '#title' => t('Automatically create a new user account when a user registers with Social Login?'), '#description' => t('If a user registers for example with Facebook, Social Login grabs his Facebook profile data and uses it to simply the user registration.'), '#options' => [ 'manual' => t('Do not create new accounts automatically, just pre-populate the default registration form and let users complete the registration manually (Default)'), 'auto_random_email' => t('Automatically create new user accounts and generate a bogus email address if the social network provides no email address'), 'auto_manual_email' => t('Automatically create new user accounts BUT fall back to the default registration form when the social network provides no email address'), ], '#default_value' => (empty($settings['registration_method']) ? 'manual' : $settings['registration_method']), ]; // Enable the social networks/identity providers. $form['social_login_providers'] = [ '#type' => 'fieldset', '#title' => t('Enable the social networks/identity providers of your choice'), ]; // Include the list of providers. $social_login_available_providers = \social_login_get_available_providers(); // Add providers. foreach ($social_login_available_providers as $key => $provider_data) { $form['social_login_providers']['social_login_icon_' . $key] = [ '#title' => \Drupal\Component\Utility\SafeMarkup::checkPlain($provider_data['name']), '#type' => 'container', '#attributes' => [ 'class' => [ 'social_login_provider', 'social_login_provider_' . $key, ], 'style' => [ 'float: left;', 'margin: 5px;', ], ], ]; $form['social_login_providers']['provider_' . $key] = [ '#type' => 'checkbox', '#title' => \Drupal\Component\Utility\SafeMarkup::checkPlain($provider_data['name']), '#default_value' => (empty($settings['provider_' . $key]) ? 0 : 1), '#attributes' => [ 'style' => [ 'margin: 15px;' ] ], ]; $form['social_login_providers']['clear_' . $key] = [ '#type' => 'container', '#attributes' => [ 'style' => [ 'clear: both;' ] ], ]; } $form['actions']['#type'] = 'actions'; $form['actions']['submit'] = [ '#type' => 'submit', '#value' => t('Save Settings'), ]; return $form; }
/** * This is the callback handler (referenced by routing.yml). */ public function callback_handler() { // Read Settings. $settings = \social_login_get_settings(); // No need to do anything if we haven't received these arguments. if (isset($_POST) && !empty($_POST['connection_token']) && !empty($_POST['oa_action']) && in_array($_POST['oa_action'], array('social_login', 'social_link'))) { // Clear session. \social_login_clear_session(); // API Connection Credentials. $api_subdomain = (!empty($settings['api_subdomain']) ? $settings['api_subdomain'] : ''); $api_key = (!empty($settings['api_key']) ? $settings['api_key'] : ''); $api_secret = (!empty($settings['api_secret']) ? $settings['api_secret'] : ''); // API Connection Handler. $handler = (!empty($settings['http_handler']) ? $settings['http_handler'] : 'curl'); $handler = ($handler == 'fsockopen' ? 'fsockopen' : 'curl'); // API Connection Protocol. $protocol = (!empty($settings['http_protocol']) ? $settings['http_protocol'] : 'https'); $protocol = ($protocol == 'http' ? 'http' : 'https'); // Automatic or manual registration? $registration_method = (!empty($settings['registration_method']) ? $settings['registration_method'] : ''); $registration_method = (in_array($registration_method, array( 'manual', 'auto_random_email', 'auto_manual_email', )) ? $registration_method : 'manual'); // Require approval? $registration_approval = (!empty($settings['registration_approval']) ? $settings['registration_approval'] : ''); $registration_approval = (in_array($registration_approval, array( 'inherit', 'disable', 'enable', )) ? $registration_approval : 'inherit'); // Retrieved connection_token. $token = trim($_POST['connection_token']); // Settings missing. if (empty($api_subdomain) || empty($api_key) || empty($api_secret)) { drupal_set_message(t('OneAll Social Login is not setup correctly, please request the administrator to verify the API Settings'), 'error'); \Drupal::logger('social_login')->notice('The API Settings are not filled out correctly', array()); } // Settings filled out. else { // Request identity details API. $data = \social_login_do_api_request($handler, $protocol . '://' . $api_subdomain . '.api.oneall.com/connections/' . $token . '.json', array( 'api_key' => $api_key, 'api_secret' => $api_secret, )); if (is_array($data) && !empty($data['http_data'])) { $social_data = @\Drupal\Component\Serialization\Json::decode($data['http_data']); // Everything seems to be ok. if (is_array($social_data) && isset($social_data['response']) && isset($social_data['response']['request']['status']['code']) && $social_data['response']['request']['status']['code'] == 200) { // The plugin that has been uses social_login/social_link. $data = $social_data['response']['result']['data']; // Save the social network data in a session. $_SESSION['social_login_session_open'] = 1; $_SESSION['social_login_session_time'] = time(); $_SESSION['social_login_social_data'] = serialize($social_data); $_SESSION['social_login_origin'] = (!empty($_GET['origin']) ? $_GET['origin'] : ''); // Unique user_token. $user_token = $data['user']['user_token']; // Extract identity. $identity = $data['user']['identity']; // Unique identity_token. $identity_token = $identity['identity_token']; // Social Network that has been used to connect. $provider_name = (!empty($identity['source']['name']) ? $identity['source']['name'] : t('Unkown')); // Try restoring the user for the token. $user_for_token = \social_login_get_user_for_user_token($user_token); // Existing user. if (is_object($user_for_token) && !empty($user_for_token->id())) { // Social Login Plugin used? if ($data['plugin']['key'] == 'social_login') { // Make sure that the user has not been blocked. $name = $user_for_token->get('name')->value; // $user_for_token->getAccountName(); if (!user_is_blocked($name)) { user_login_finalize($user_for_token); } else { drupal_set_message(t('Your account is blocked.'), 'error'); // Clear session. \social_login_clear_session(); } } // Social Link Plugin used? elseif ($data['plugin']['key'] == 'social_link') { // The user should be logged in. $user = \Drupal::currentUser(); // User is logged in. if (is_object($user) && $user->isAuthenticated()) { // The existing token does not match the current user! if ($user_for_token->id() <> $user->id()) { drupal_set_message(t('This @social_network account is already linked to another user.', array( '@social_network' => $provider_name, )), 'error'); } // The existing token matches the current user! else { // Link identity. if ($data['plugin']['data']['action'] == 'link_identity') { \social_login_map_identity_token_to_user_token($user, $identity_token, $user_token, $provider_name); drupal_set_message(t('The @social_network account has been linked to your account.', array( '@social_network' => $provider_name, )), 'status'); } // Unlink identity. else { \social_login_unmap_identity_token($identity_token); drupal_set_message(t('The social network account has been unlinked from your account.'), 'status'); } // Clear session. \social_login_clear_session(); // Redirect to profile. \Drupal::logger('social_login')->notice('- '. __FUNCTION__ .'@'. __LINE__ .' redirecting to '. \Drupal::url('user.page')); return new RedirectResponse(\Drupal::url('user.page')); } } // User is not logged in. else { drupal_set_message(t('You must be logged in to perform this action.'), 'error'); // Clear session. \social_login_clear_session(); // Redirect to home. return new RedirectResponse(\Drupal::url('<front>')); } } } // New user. else { \Drupal::logger('social_login')->notice('- '. __FUNCTION__ .'@'. __LINE__ .' new user'); // New users may register. if (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) { // Extract the user's email address. $user_email = ''; $user_email_is_verified = NULL; $user_email_is_random = NULL; if (isset($identity['emails']) && is_array($identity['emails'])) { while (!$user_email_is_verified && (list(, $email) = each($identity['emails']))) { $user_email = $email['value']; $user_email_is_verified = (!empty($email['is_verified'])); } } // The admin has chosen the automatic registration. if ($registration_method <> 'manual') { // No email address / Email address already exists. if (empty($user_email) || \social_login_get_uid_for_email($user_email) !== FALSE) { // The admin wants users to fill out their email manually. if ($registration_method == 'auto_manual_email') { // We have to fall back to the default registration. $registration_method = 'manual'; } // The admin has enabled the usage of random email addresses. else { // Create a bogus email. $user_email = \social_login_create_random_email(); // Flag - is used further down. $user_email_is_random = TRUE; } } } // Automatic registration is still enabled. if ($registration_method <> 'manual') { // If something goes wrong fall back to manual registration. $registration_method = 'manual'; // Extract User Firstname. $user_first_name = (!empty($identity['name']['givenName']) ? $identity['name']['givenName'] : ''); // Extract User Lastname. $user_last_name = (!empty($identity['name']['familyName']) ? $identity['name']['familyName'] : ''); // Forge User Login. $user_login = ''; if (!empty($identity['preferredUsername'])) { $user_login = $identity['preferredUsername']; } elseif (!empty($identity['displayName'])) { $user_login = $identity['displayName']; } elseif (!empty($identity['name']['formatted'])) { $user_login = $identity['name']['formatted']; } else { $user_login = trim($user_first_name . ' ' . $user_last_name); } // We absolutely need a unique username. if (strlen(trim($user_login)) == 0 || \social_login_get_uid_for_name(trim($user_login)) !== FALSE) { $i = 1; $user_login = $provider_name . t('User'); while (\social_login_get_uid_for_name($user_login) !== FALSE) { $user_login = $provider_name . t('User') . $i++; } } // We also need a password. $user_password = user_password(8); // Check the approval setting. switch ($registration_approval) { // No approval required. case 'disable': $user_status = 1; break; // Manual approval required. case 'enable': $user_status = 0; break; // Use the system-wide setting. default: $user_status = \Drupal::config('user.settings')->get('register') == USER_REGISTER_VISITORS ? 1 : 0; break; } $user_roles = array(); // real user accounts get the authenticated user role. // Make sure at least one module implements our hook. if (count(\Drupal::moduleHandler()->getImplementations('social_login_default_user_roles')) > 0) { // Call modules that implements the hook. $user_roles = \Drupal::moduleHandler()->invokeAll('social_login_default_user_roles', $user_roles); } // Setup the user fields. $user_fields = array( 'name' => $user_login, 'mail' => $user_email, 'pass' => $user_password, 'status' => $user_status, 'init' => $user_email, 'roles' => $user_roles, ); // Create a new user. $account = User::create($user_fields); $account->save(); // The new account has been created correctly. if ($account !== FALSE) { // Disable Drupal legacy registration. $registration_method = 'auto'; // Log the new user in. if (($uid = \Drupal::service("user.auth")->authenticate($user_login, $user_password)) !== FALSE) { // Loads a user object. $user = User::load($uid); user_login_finalize($user); // Send email if it's not a random email. if ($user_email_is_random !== TRUE) { // No approval required. if ($user_status == 1) { _user_mail_notify('register_no_approval_required', $user); drupal_set_message(t('You have succesfully created an account and linked it with your @social_network account.', array( '@social_network' => $provider_name, )), 'status'); } // Approval required. else { $a = _user_mail_notify('register_pending_approval', $user); drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />You will receive an email once your account has been approved and you can then login with your @social_network account.', array( '@social_network' => $provider_name, )), 'status'); } } // Random email used. else { drupal_set_message(t('You have succesfully created an account and linked it with your @social_network account.', array( '@social_network' => $provider_name, )), 'status'); } } // For some reason we could not log the user in. else { // Redirect to login page (login manually). drupal_set_message(t('Error while logging you in, please try to login manually.'), 'error'); \Drupal::logger('social_login')->error('- '. __FUNCTION__ .'@'. __LINE__ .' auto login, redirecting to '. \Drupal::url('user.login')); return new RedirectResponse(\Drupal::url('user.login')); } } // An error occured during user->save(). else { // Redirect to registration page (register manually). drupal_set_message(t('Error while creating your user account, please try to register manually.'), 'error'); \Drupal::logger('social_login')->error('- '. __FUNCTION__ .'@'. __LINE__ .' auto register, redirecting to '. \Drupal::url('user.register')); return new RedirectResponse(\Drupal::url('user.register')); } } // Use the legacy registration form? if ($registration_method == 'manual') { // Redirect to the registration page (+ prepopulate form with SESSION data). \Drupal::logger('social_login')->notice('- '. __FUNCTION__ .'@'. __LINE__ .' manual register, redirecting to '. \Drupal::url('user.register')); return new RedirectResponse(\Drupal::url('user.register')); } } // Registration disabled. else { drupal_set_message(t('Only site administrators can create new user accounts.'), 'error'); return new RedirectResponse(\Drupal::url('<front>')); } } } } else { \Drupal::logger('social_login')->error('- '. __FUNCTION__ .'@'. __LINE__ .' invalid JSON received from resource'); } } } // Return to the front page. return new RedirectResponse(\Drupal::url('<front>')); }