Parent Directory
|
Revision Log
|
Revision Graph
Update member role settings, better AES login cookie encryption support
| 1 | <?php |
| 2 | // $Id: netforum_authentication.module,v 1.13 2009/07/11 13:42:47 jamesmichaelhill Exp $ |
| 3 | |
| 4 | //TODO: There are two places still calling GetQuery w/o regard to OD or Enterprise. One for the forgot password section, |
| 5 | // and one for the load section. The load section needs to be rewritten to use the data from the login (if possible) or |
| 6 | // to use a separate function to get user data. Maybe not load data on login? |
| 7 | |
| 8 | // This is used for the shared SSO, since the user redirects after login we have to pause a beat before |
| 9 | // including the magic link in the page |
| 10 | if ($_SESSION['netforum_auth_link']) { |
| 11 | drupal_add_link($_SESSION['netforum_auth_link']); |
| 12 | unset($_SESSION['netforum_auth_link']); |
| 13 | } |
| 14 | |
| 15 | |
| 16 | /** |
| 17 | * Implementation of hook_menu() |
| 18 | */ |
| 19 | function netforum_authentication_menu($may_cache) { |
| 20 | $items = array(); |
| 21 | global $user; |
| 22 | |
| 23 | if ($may_cache) { |
| 24 | $items[] = array( |
| 25 | 'path' => 'admin/user/netforum-authentication', |
| 26 | 'title' => t('netFORUM user authentication'), |
| 27 | 'description' => t('Set the authentication settings for netFORUM customers'), |
| 28 | 'callback' => 'drupal_get_form', |
| 29 | 'callback arguments' => array('netforum_auth_admin_settings'), |
| 30 | 'access' => user_access('administer site configuration'), |
| 31 | ); |
| 32 | |
| 33 | $items[] = array( |
| 34 | 'path' => 'admin/user/netforum-roles', |
| 35 | 'title' => t('netFORUM user roles'), |
| 36 | 'description' => t('Choose what site roles are given to netFORUM users'), |
| 37 | 'callback' => 'drupal_get_form', |
| 38 | 'callback arguments' => array('netforum_auth_role_settings'), |
| 39 | 'access' => user_access('administer site configuration') || user_access('administer access control'), |
| 40 | ); |
| 41 | |
| 42 | $items[] = array('path' => 'admin/settings/netforum/clearcache', |
| 43 | 'title' => t('Clear menu cache'), |
| 44 | 'callback' => 'netforum_auth_cache_clear', |
| 45 | 'access' => user_access('administer site configuration'), |
| 46 | 'type' => MENU_CALLBACK, |
| 47 | ); |
| 48 | |
| 49 | $items[] = array('path' => 'user/netforum_sso_check', |
| 50 | 'title' => t('netFORM Authentication Shared SSO Check'), |
| 51 | 'callback' => 'netforum_auth_shared_sso_check', |
| 52 | 'access' => true, |
| 53 | 'type' => MENU_CALLBACK, |
| 54 | ); |
| 55 | |
| 56 | $items[] = array('path' => 'user/netforum_sso_share', |
| 57 | 'title' => t('netFORM Authentication Shared SSO'), |
| 58 | 'callback' => 'netforum_auth_shared_sso_login', |
| 59 | 'access' => true, |
| 60 | 'type' => MENU_CALLBACK, |
| 61 | ); |
| 62 | |
| 63 | $items[] = array('path' => 'nf_od_sso_transfer', |
| 64 | 'title' => t('Transfer to netFORUM OD w/ SSO'), |
| 65 | 'callback' => 'netforum_auth_od_sso_transfer', |
| 66 | 'access' => true, |
| 67 | 'type' => MENU_CALLBACK, |
| 68 | ); |
| 69 | |
| 70 | |
| 71 | //here we will overwrite some special user URLs if we want to alter the behavior, if this isn't working check the load |
| 72 | // order of the modules to make sure netFORUM loads AFTER the user module. Load order is determined by weight in the |
| 73 | //system table and it should be set automatically on installation |
| 74 | if (strtolower(variable_get('netforum_auth_forgotten_password', '<drupal>')) != '<drupal>' || variable_get('netforum_auth_forgot_password_add', 0) == 1) { |
| 75 | $items[] = array('path' => 'user/password', 'title' => t('Request new password'), |
| 76 | 'callback' => 'netforum_auth_forgotten_password_redirect', 'callback arguments' => array('user_pass'), 'access' => !$user->uid, 'type' => MENU_LOCAL_TASK); |
| 77 | } |
| 78 | |
| 79 | if (strtolower(variable_get('netforum_auth_user_register', '<drupal>')) != '<drupal>') { |
| 80 | $items[] = array('path' => 'user/register', 'title' => t('Create new account'), |
| 81 | 'callback' => 'netforum_auth_user_register_redirect', 'callback arguments' => '', 'access' => !$user->uid && variable_get('user_register', 1), 'type' => MENU_LOCAL_TASK); |
| 82 | } |
| 83 | |
| 84 | } |
| 85 | else{ |
| 86 | if ( (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) && $user !== FALSE) { |
| 87 | if (strtolower(variable_get('netforum_auth_user_editing', '<drupal>')) != '<drupal>') { |
| 88 | $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('Edit'), |
| 89 | 'callback' => 'netforum_auth_user_editing_redirect', 'callback arguments' => '', |
| 90 | 'access' => user_access('administer users') || $user->uid == arg(1), 'type' => MENU_LOCAL_TASK); |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | return $items; |
| 95 | } |
| 96 | |
| 97 | /** |
| 98 | * direct the user to the correct edit info page |
| 99 | * |
| 100 | * called by the user/ID/edit url if drupal is set to use an external site for editing user info |
| 101 | */ |
| 102 | function netforum_auth_user_editing_redirect() { |
| 103 | global $user; |
| 104 | if (netforum_is_empty_guid($user->cst_key) === false && strtolower(variable_get('netforum_auth_user_editing', '<drupal>')) != '<drupal>') { |
| 105 | $loc = variable_get('netforum_auth_user_editing', ''); |
| 106 | if (netforum_is_team() && stristr($loc, "netforumondemand.com")) { |
| 107 | netforum_auth_od_sso_transfer($loc); |
| 108 | } |
| 109 | else { |
| 110 | drupal_goto($loc); |
| 111 | } |
| 112 | } |
| 113 | else { |
| 114 | return drupal_get_form('user_edit'); |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * direct the user to the correct forgot password page |
| 120 | * |
| 121 | * called by the user/password url if we're overwriting the default drupal behavior |
| 122 | */ |
| 123 | function netforum_auth_forgotten_password_redirect() { |
| 124 | if (strtolower(variable_get('netforum_auth_forgotten_password', '<drupal>')) != '<drupal>') { |
| 125 | drupal_goto(variable_get('netforum_auth_forgotten_password', '')); |
| 126 | } |
| 127 | elseif (variable_get('netforum_auth_forgot_password_add', 0) == 1) { |
| 128 | return drupal_get_form('netforum_auth_user_pass'); |
| 129 | } |
| 130 | else { |
| 131 | return drupal_get_form('user_pass'); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * direct the user to the correct registration page |
| 137 | * |
| 138 | * called by the user/register url if we're overwriting the default drupal behavior |
| 139 | */ |
| 140 | function netforum_auth_user_register_redirect() { |
| 141 | if (strtolower(variable_get('netforum_auth_user_register', '<drupal>')) != '<drupal>') { |
| 142 | drupal_goto(variable_get('netforum_auth_user_register', '')); |
| 143 | } |
| 144 | else { |
| 145 | return drupal_get_form('user_register'); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | |
| 150 | /** |
| 151 | * The user password form |
| 152 | * |
| 153 | * This is called by the netforum_auth_forgotten_password_redirect function if they want to allow users who have |
| 154 | * not logged in to request a password. Really we overwrite it because we want our own validation form. |
| 155 | * @ingroup forms |
| 156 | */ |
| 157 | function netforum_auth_user_pass() { |
| 158 | $form = user_pass() ; |
| 159 | $form['#validate'] = array('netforum_auth_user_pass_validate' => array()); |
| 160 | $form['#submit'] = array('user_pass_submit' => array()); |
| 161 | return $form; |
| 162 | } |
| 163 | |
| 164 | /** |
| 165 | * Add the user if they exist in netFORUM when validating the login form |
| 166 | * |
| 167 | * This is a modified version of the regular user_pass_validate function that |
| 168 | * does the additional step of checking to see if the user exists in netFORUM, and if they do |
| 169 | * then it creates a new drupal user and declares netforum_authentication to be the authentication |
| 170 | * module. That way they can reset their password if using drupal's password reset function |
| 171 | */ |
| 172 | function netforum_auth_user_pass_validate($form_id, $form_values) { |
| 173 | $name = $form_values['name']; |
| 174 | $account = user_load(array('mail' => $name, 'status' => 1)); |
| 175 | if (!$account) { |
| 176 | $account = user_load(array('name' => $name, 'status' => 1)); |
| 177 | } |
| 178 | if (!$account) { |
| 179 | $eml_field = _netforum_auth_get_email_field('Customer'); |
| 180 | $query = array('szObjectName' => 'Customer @TOP 1', |
| 181 | 'szColumnList' => 'cst_type, cst_web_login, '. $eml_field, |
| 182 | 'szWhereClause' => "(". $eml_field ." = '$name' OR cst_web_login = '$name')", |
| 183 | 'szOrderBy' => ''); |
| 184 | $response = netforum_xweb_request('GetQuery', $query); |
| 185 | if ($response && $response->attributes()->recordReturn == 1) { |
| 186 | $cst_obj = $response->CustomerObject; |
| 187 | $cst_name = (string)$cst_obj->cst_web_login; |
| 188 | $cst_mail = (string)$cst_obj->{$eml_field}; |
| 189 | $cst_type = (string)$cst_obj->cst_type; |
| 190 | $cst_key = (string)$cst_obj->cst_key; |
| 191 | |
| 192 | if (empty($cst_name)) { |
| 193 | $cst_name = $cst_mail; |
| 194 | } |
| 195 | //adapted from user_authenticate in the user module to add a new user |
| 196 | $userinfo = array('name' => $cst_name, 'mail' => $cst_mail, 'pass' => user_password(), 'cst_key' => $cst_key, 'cst_type' => $cst_type, 'init' => $name, 'status' => 1 ); |
| 197 | $userinfo["authname_netforum_authentication"] = $name; |
| 198 | $account = user_save('', $userinfo); |
| 199 | watchdog('user', t('New external user: %user using module %module.', array('%user' => $name, '%module' => 'netforum_authentication')), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $user->uid .'/edit')); |
| 200 | } |
| 201 | } |
| 202 | if ($account->uid) { |
| 203 | form_set_value(array('#parents' => array('account')), $account); |
| 204 | } |
| 205 | else { |
| 206 | form_set_error('name', t('Sorry, %name is not recognized as a user name or an email address.', array('%name' => $name))); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | |
| 211 | /** |
| 212 | * Define the admin settings form |
| 213 | * @ingroup forms |
| 214 | */ |
| 215 | function netforum_auth_admin_settings() { |
| 216 | $form['settings'] = array( |
| 217 | '#title' => "User authentication settings", |
| 218 | '#type' => 'fieldset', |
| 219 | '#description' => t("Determine what parts of user authentication and information drupal is responsible for."), |
| 220 | ); |
| 221 | |
| 222 | $form['settings']['netforum_auth_user_register'] = array( |
| 223 | '#title' => t('New User Registration'), |
| 224 | '#type' => 'textfield', |
| 225 | '#description' => t('Enter the URL users should be redirected to when they click on create new account. This can be an external URL or a drupal node, such as node/newuserinfo. Enter <drupal> to use the defaul drupal new user screen'), |
| 226 | '#size' => 40, |
| 227 | '#required' => TRUE, |
| 228 | '#default_value' => variable_get('netforum_auth_user_register', '<drupal>'), |
| 229 | ); |
| 230 | |
| 231 | $form['settings']['netforum_auth_forgotten_password'] = array( |
| 232 | '#title' => t('Forgotten Passwords'), |
| 233 | '#type' => 'textfield', |
| 234 | '#description' => t('Enter the URL users should be redirected to to reset their password, or <drupal> to use built in functionality at user/password.'), |
| 235 | '#size' => 40, |
| 236 | '#required' => TRUE, |
| 237 | '#default_value' => variable_get('netforum_auth_forgotten_password', '<drupal>'), |
| 238 | ); |
| 239 | |
| 240 | $form['settings']['netforum_auth_forgot_password_add'] = array( |
| 241 | '#title' => t('Search netFORUM for users with forgotten passwords'), |
| 242 | '#type' => 'checkbox', |
| 243 | '#description' => t('If using drupal for forgotten passwords, should Drupal check both local users and netFORUM when looking for usernames? If this is not checked only users who have already logged in can reset their password with Drupal. '), |
| 244 | '#size' => 40, |
| 245 | '#default_value' => variable_get('netforum_auth_forgot_password_add', 0), |
| 246 | ); |
| 247 | |
| 248 | $form['settings']['netforum_auth_user_editing'] = array( |
| 249 | '#title' => t('Edit User info'), |
| 250 | '#type' => 'textfield', |
| 251 | '#description' => t('Enter the URL users should be redirected to to edit their information, or <drupal> to use built in functionality. Note that this includes setting passwords and email addresses by default. '), |
| 252 | '#size' => 40, |
| 253 | '#required' => TRUE, |
| 254 | '#default_value' => variable_get('netforum_auth_user_editing', '<drupal>'), |
| 255 | ); |
| 256 | |
| 257 | if (netforum_is_team()) { |
| 258 | $form['settings']['netforum_auth_user_text'] = array( |
| 259 | '#title' => t('Edit User notes'), |
| 260 | '#type' => 'textarea', |
| 261 | '#description' => t('If the edit user info URL above is set to <drupal>, this block of text will appear at the top of the user edit info form instead of the username and password. Use this space to provide notes and links to locations where users should edit their username and password if desired.'), |
| 262 | '#default_value' => variable_get('netforum_auth_user_text',''), |
| 263 | ); |
| 264 | |
| 265 | $form['settings']['netforum_auth_user_editing']['#description'] .= t('<b>Note:</b> netFORUM On Demand cannot update user information, no changes to user name or password will be allowed on the drupal form.'); |
| 266 | $form['settings']['netforum_auth_forgot_password_add']['#description'] .= t('<b>Note:</b> netFORUM On Demand cannot update user information, no changes to user name or password will be allowed on the drupal form.'); |
| 267 | } |
| 268 | |
| 269 | $form['settings']['cache_clear'] = array( |
| 270 | '#title' => 'Menu troubleshooting', |
| 271 | '#type' => 'item', |
| 272 | '#description' => t('If the settings above are not working properly try '. l(t('clearing the menu cache'), 'admin/settings/netforum/clearcache')), |
| 273 | ); |
| 274 | |
| 275 | //Enterprise only |
| 276 | if (netforum_is_enterprise()) { |
| 277 | $form['sso'] = array( |
| 278 | '#title' => "Single Sign On settings", |
| 279 | '#type' => 'fieldset', |
| 280 | '#description' => t("Which eWeb sites should a user automatically be logged on to when logged in to drupal?"), |
| 281 | ); |
| 282 | |
| 283 | $form['sso']['netforum_auth_eweb_sso'] = array( |
| 284 | '#title' => t('eWeb Sites'), |
| 285 | '#type' => 'checkboxes', |
| 286 | '#description' => t('Select all to log users onto every eweb site in netFORUM or pick only the sites you want'), |
| 287 | '#options' => array_merge(array('ALL' => 'All eweb sites'), netforum_auth_eweb_sites()), |
| 288 | '#default_value' => variable_get('netforum_auth_eweb_sso', array()), |
| 289 | ); |
| 290 | |
| 291 | $form['sso']['netforum_auth_cookie_domain'] = array( |
| 292 | '#title' => t('SSO Cookie domain'), |
| 293 | '#type' => 'textfield', |
| 294 | '#description' => t('To use SSO both eWeb and your drupal installation must share the same top level domain (tld). For example, if you have drupal running www.example.com then the address for eWeb needs to be something that ends in example.com like store.example.com and this field should be set to .example.com'), |
| 295 | '#size' => 40, |
| 296 | '#default_value' => variable_get('netforum_auth_cookie_domain', $_SERVER['HTTP_HOST']), |
| 297 | ); |
| 298 | |
| 299 | $form['sso']['netforum_auth_sso_logout_url'] = array( |
| 300 | '#title' => t('SSO logout URL'), |
| 301 | '#type' => 'textfield', |
| 302 | '#description' => t('When a user logs out of drupal any netFORUM cookies set for the domain above will be deleted, but the user can also be directed to a url that will log them out of eWeb such as http://eweb.example.com/eWeb/Logout.aspx . If this is set to <drupal> then only the cookies will be removed, and the user will be logged out of eWeb when they close the browser.'), |
| 303 | '#validate' => array('netforum_valid_sso_logout' => array()), |
| 304 | '#size' => 40, |
| 305 | '#default_value' => variable_get('netforum_auth_sso_logout_url', '<drupal>'), |
| 306 | ); |
| 307 | |
| 308 | /* |
| 309 | NOTE: This was added in response to http://drupal.org/node/454578 - although current testing suggests the old style |
| 310 | of setting the login and pw to the modified md5 plaintext password still works with the current version of netforum |
| 311 | */ |
| 312 | $form['sso']['pw_encryption'] = array( |
| 313 | '#title' => "Custom SSO Encryption Key", |
| 314 | '#type' => 'fieldset', |
| 315 | '#description' => t("For netFORUM 2.2 and above, these fields depend on the eWebUserPasswordCookieEncryptionKey setting in eweb/web.config. Leave blank to use the pre-2.2 style of SSO."), |
| 316 | ); |
| 317 | $form['sso']['pw_encryption']['netforum_auth_custom_password_encryption_key'] = array( |
| 318 | '#title' => t('AES Key'), |
| 319 | '#type' => 'textfield', |
| 320 | '#description' => t('The encryption key should be the Base 64 encoded. It must be generated for you based on the value of the eWebUserPasswordCookieEncryptionKey. '), |
| 321 | '#size' => 40, |
| 322 | '#required' => FALSE, |
| 323 | '#default_value' => variable_get('netforum_auth_custom_password_encryption_key', ''), |
| 324 | ); |
| 325 | $form['sso']['pw_encryption']['netforum_auth_custom_password_encryption_iv'] = array( |
| 326 | '#title' => t('AES Initialization Vector (IV)'), |
| 327 | '#type' => 'textfield', |
| 328 | '#description' => t('The IV should also be Base 64 encoded and shorter than the key.'), |
| 329 | '#size' => 30, |
| 330 | '#required' => FALSE, |
| 331 | '#default_value' => variable_get('netforum_auth_custom_password_encryption_iv', ''), |
| 332 | ); |
| 333 | |
| 334 | |
| 335 | $form['sso']['netforum_auth_shared_sso'] = array( |
| 336 | '#title' => t('Allow other drupal sites to share this domain for SSO'), |
| 337 | '#type' => 'checkbox', |
| 338 | '#description' => t("Sometimes users might log into another website running Drupal with a different domain than eWeb, in that case SSO won't work. Checking this will allow other websites to use this site and domain for logging in to eWeb."), |
| 339 | '#default_value' => variable_get('netforum_auth_shared_sso', 0), |
| 340 | ); |
| 341 | |
| 342 | $form['sso']['netforum_auth_shared_sso_secret'] = array( |
| 343 | '#title' => t('Shared secret password'), |
| 344 | '#type' => 'textfield', |
| 345 | '#description' => t('Both sites sharing a domain for SSO must have the same shared secret password. This is used to help ensure that only authorized sites can log users on.'), |
| 346 | '#default_value' => variable_get('netforum_auth_shared_sso_secret', ''), |
| 347 | '#size' => 40, |
| 348 | ); |
| 349 | |
| 350 | $form['sso']['netforum_auth_shared_sso_url'] = array( |
| 351 | '#title' => t('Shared SSO url'), |
| 352 | '#type' => 'textfield', |
| 353 | '#description' => t('To use another website for eWeb SSO, enter the URL of the site here. The website must also have netFORUM Authentication enabled, a shared key, and allowing other sites must be checked. The cookie domain and eweb site settings listed above will be ignored, and the settings on the remote site will be used instead.'), |
| 354 | '#default_value' => variable_get('netforum_auth_shared_sso_url', ''), |
| 355 | '#size' => 40, |
| 356 | ); |
| 357 | } |
| 358 | |
| 359 | return system_settings_form($form); |
| 360 | } |
| 361 | |
| 362 | function netforum_auth_admin_settings_validate($form_id, $form_values) { |
| 363 | if (($form_values['netforum_auth_shared_sso'] == 1 || $form_values['netforum_auth_shared_sso_url'] != '') && trim($form_values['netforum_auth_shared_sso_secret']) == '' ) { |
| 364 | form_set_error('netforum_auth_shared_sso_secret', t('The shared secret is required when using this domain for shared sso')); |
| 365 | } |
| 366 | else { |
| 367 | $secret_okay = true; |
| 368 | } |
| 369 | |
| 370 | if (trim($form_values['netforum_auth_shared_sso_url']) != '' && substr($form_values['netforum_auth_shared_sso_url'], 0, 7) != 'http://' && substr($form_values['netforum_auth_shared_sso_url'], 0, 8) != 'https://') { |
| 371 | form_set_error('netforum_auth_shared_sso_url', t('Shared SSO url must start with http:// or https://')); |
| 372 | } |
| 373 | else { |
| 374 | $url_okay = true; |
| 375 | } |
| 376 | |
| 377 | if ( $secret_okay === true && $url_okay === true && trim($form_values['netforum_auth_shared_sso_url']) != '' ) { |
| 378 | if (ini_get('allow_url_fopen')) { |
| 379 | $check_url = $form_values['netforum_auth_shared_sso_url']; |
| 380 | if (substr($check_url, -1) != '/') { |
| 381 | $check_url .= "/"; |
| 382 | } |
| 383 | $token = md5("netFORUMAUTHINTERNAL". $form_values['netforum_auth_shared_sso_secret']); |
| 384 | $check_url .= "user/netforum_sso_check/". $token; |
| 385 | $remote_site_response = file_get_contents($check_url); |
| 386 | if (stristr($remote_site_response, "<checkresult>1</checkresult>") === FALSE) { |
| 387 | form_set_error('form', t("The shared SSO site either could not be reached or the shared secret didn't match.")); |
| 388 | } |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | if (trim($form_values['netforum_auth_custom_password_encryption_key']) != '' || trim($form_values['netforum_auth_custom_password_encryption_iv']) != '') { |
| 393 | $key = trim($form_values['netforum_auth_custom_password_encryption_key']); |
| 394 | $iv = trim($form_values['netforum_auth_custom_password_encryption_iv']); |
| 395 | |
| 396 | # TODO: The two else statements should check for appropriate key length, but mb_strlen is returning less than expected. Instead we |
| 397 | # run one test encryption to see if it works. If there are errors Drupal will catch and display them. |
| 398 | netforum_aes_encrypt("test", $key, $iv); |
| 399 | |
| 400 | |
| 401 | if ($key == '') { |
| 402 | form_set_error('netforum_auth_custom_password_encryption_key', t('SSO key cannot be blank if SSO IV is set')); |
| 403 | } |
| 404 | // else { |
| 405 | // $keylen = mb_strlen(base64_decode($key)); |
| 406 | // if ($keylen != 32) { |
| 407 | // form_set_error('netforum_auth_custom_password_encryption_key', t('SSO key is the wrong size, 32 bytes expected but %size found after decoding.', array('%size' => $keylen))); |
| 408 | // } |
| 409 | // } |
| 410 | |
| 411 | if ($iv == '') { |
| 412 | form_set_error('netforum_auth_custom_password_encryption_iv', t('SSO IV cannot be blank if SSO key is set')); |
| 413 | } |
| 414 | // else { |
| 415 | // $keylen = mb_strlen(base64_decode($iv)); |
| 416 | // if ($keylen != 16) { |
| 417 | // form_set_error('netforum_auth_custom_password_encryption_iv', t('SSO IV is the wrong size, 16 bytes expected but %size found after decoding.', array('%size' => $keylen))); |
| 418 | // } |
| 419 | // } |
| 420 | |
| 421 | } |
| 422 | |
| 423 | if (strtolower($form_values['netforum_auth_user_register']) != '<drupal>' || strtolower($form_values['netforum_auth_forgotten_password']) != '<drupal>' || strtolower($form_values['netforum_auth_user_editing']) != '<drupal>') { |
| 424 | cache_clear_all('*', 'cache_menu', TRUE); |
| 425 | } |
| 426 | } |
| 427 | |
| 428 | /** |
| 429 | * The form describing netforum user roles |
| 430 | * |
| 431 | * @ingroup forms |
| 432 | */ |
| 433 | function netforum_auth_role_settings() { |
| 434 | $ignore_roles = netforum_auth_ignore_roles(); |
| 435 | |
| 436 | $form['desc'] = array( |
| 437 | '#type' => 'item', |
| 438 | '#description' => t('For each of the following roles on the drupal website, identify which individual or organizations should receive those roles'), |
| 439 | ); |
| 440 | |
| 441 | $form['#submit'] = array('netforum_auth_role_settings_submit' => array()); |
| 442 | |
| 443 | $categories = netforum_auth_categories(); |
| 444 | $netforum_auth_roles = variable_get('netforum_auth_roles', array_keys(user_roles(1))); |
| 445 | // This iterates only on the roles we are NOT ignoring, by default this is authenticated and anonymous |
| 446 | foreach (array_diff_key(user_roles(), $ignore_roles) as $rid => $role) { |
| 447 | $form[$rid] = array( |
| 448 | '#title' => $role, |
| 449 | '#type' => 'fieldset', |
| 450 | '#description' => t("Which netFORUM users are assigned to the drupal site role %role ?", array('%role' => $role) ), |
| 451 | '#collapsible' => TRUE, |
| 452 | '#collapsed' => TRUE, |
| 453 | ); |
| 454 | $form[$rid]["netforum_auth_roles_$rid"] = array( |
| 455 | '#title' => 'netFORUM Types', |
| 456 | '#type' => 'checkboxes', |
| 457 | '#options' => $categories, |
| 458 | '#default_value' => $netforum_auth_roles[$rid], |
| 459 | ); |
| 460 | } |
| 461 | |
| 462 | $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') ); |
| 463 | $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') ); |
| 464 | |
| 465 | if (!empty($_POST) && form_get_errors()) { |
| 466 | drupal_set_message(t('The settings have not been saved because of the errors.'), 'error'); |
| 467 | } |
| 468 | $form['#base'] = 'system_settings_form'; |
| 469 | |
| 470 | return $form; |
| 471 | } |
| 472 | |
| 473 | function netforum_auth_role_settings_submit($form_id, $form_values) { |
| 474 | $netforum_auth_roles = array(); |
| 475 | |
| 476 | foreach (array_diff_key(user_roles(), netforum_auth_ignore_roles()) as $rid => $role) { |
| 477 | $element = 'netforum_auth_roles_'. $rid; |
| 478 | $netforum_auth_roles[$rid] = array(); |
| 479 | if (isset($form_values[$element]) && is_array($form_values[$element])) { |
| 480 | foreach ($form_values[$element] as $key => $check_val) { |
| 481 | if ((string)$key == (string)$check_val) { |
| 482 | $netforum_auth_roles[$rid][] = $key; |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | variable_set('netforum_auth_roles', $netforum_auth_roles); |
| 489 | drupal_set_message(t('The configuration options have been saved.')); |
| 490 | } |
| 491 | |
| 492 | /** |
| 493 | * Validate the sso logout url option |
| 494 | */ |
| 495 | function netforum_valid_sso_logout($form = null) { |
| 496 | if ($form == null) { |
| 497 | return; |
| 498 | } |
| 499 | $url = $form['#post']['netforum_auth_sso_logout_url']; |
| 500 | if (strtolower(trim($url)) != '<drupal>' && valid_url($url, true) == false) { |
| 501 | form_set_error('netforum_auth_sso_logout_url', t('Valid sso logout URL required')); |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | /** |
| 506 | * clear the menu cache and redirect to netforum settings |
| 507 | * |
| 508 | */ |
| 509 | function netforum_auth_cache_clear() { |
| 510 | cache_clear_all('*', 'cache_menu', TRUE); |
| 511 | drupal_set_message(t('Menu cache cleared.')); |
| 512 | drupal_goto('admin/settings/netforum'); |
| 513 | } |
| 514 | |
| 515 | /** |
| 516 | * Confirm that this site is available for shared sso and that the shared secret is valid |
| 517 | * |
| 518 | */ |
| 519 | function netforum_auth_shared_sso_check($token = '') { |
| 520 | $passed_check = false; |
| 521 | if (variable_get('netforum_auth_shared_sso', 0) != 0 && variable_get('netforum_auth_shared_sso_secret', '') != '') { |
| 522 | $internal_token = md5("netFORUMAUTHINTERNAL". variable_get('netforum_auth_shared_sso_secret', '')); |
| 523 | if ($internal_token == $token) { |
| 524 | $passed_check = true; |
| 525 | } |
| 526 | } |
| 527 | print "<checkresult>". $passed_check ."</checkresult>"; |
| 528 | exit; |
| 529 | } |
| 530 | |
| 531 | |
| 532 | /** |
| 533 | * Find the username and password for the individual and log them into eweb |
| 534 | * |
| 535 | * We use two tokens to save a DB/xweb hit where not necessary, one for the password one for the cst_id |
| 536 | * |
| 537 | * Enterprise only. |
| 538 | */ |
| 539 | function netforum_auth_shared_sso_login($cstid = '', $cstid_token = '', $pw_token = '') { |
| 540 | $allow_logins = variable_get('netforum_auth_shared_sso', 0); |
| 541 | $shared_secret = variable_get('netforum_auth_shared_sso_secret', ''); |
| 542 | if ($allow_logins != 0 && $shared_secret != '' && $cstid != '' && $cstid_token != '') { |
| 543 | $cstid_internal_token = _netforum_auth_make_cstid_token($cstid); |
| 544 | if ($cstid_internal_token == $cstid_token) { |
| 545 | $account = new stdClass(); |
| 546 | $res = db_query("SELECT cst_key, cst_id, cst_web_password FROM {users} WHERE cst_id = '%s'", $cstid); |
| 547 | if (db_num_rows($res) >= 0) { |
| 548 | while ($account = db_fetch_object($res)) { |
| 549 | if (_netforum_auth_match_password_token($account->cst_web_password, $pw_token) ) { |
| 550 | $account->name = $account->cst_id; |
| 551 | $found_user = true; |
| 552 | break; |
| 553 | } |
| 554 | } |
| 555 | } |
| 556 | else { |
| 557 | $arguments = array( |
| 558 | 'szObjectName' => "Customer", |
| 559 | 'szColumnList' => "cst_id, cst_web_password", |
| 560 | 'szWhereClause' => "cst_id = \'". $cstid ."\'", |
| 561 | 'szOrderBy' => "", |
| 562 | ); |
| 563 | $response = netforum_xweb_request('GetQuery', $arguments); |
| 564 | if ($response && $response->attributes()->recordReturn > 0) { |
| 565 | foreach ($response->CustomerObject as $cst) { |
| 566 | if (_netforum_auth_match_password_token($cst->cst_web_password, $pw_token)) { |
| 567 | $found_user = true; |
| 568 | $account->cst_key = (string)$cst->cst_key; |
| 569 | $account->cst_web_password = (string)$cst->cst_web_password; |
| 570 | $account->cst_id = $cstid; |
| 571 | $account->name = $cstid; |
| 572 | } |
| 573 | } |
| 574 | } |
| 575 | } |
| 576 | if ($found_user === true) { |
| 577 | netforum_auth_eweb_sso_login($account); |
| 578 | } |
| 579 | } |
| 580 | } |
| 581 | print "<!--"; |
| 582 | exit; |
| 583 | } |
| 584 | |
| 585 | /** |
| 586 | * Take a customer ID and turn it into a unique token |
| 587 | * |
| 588 | */ |
| 589 | function _netforum_auth_make_cstid_token($cstid = ''){ |
| 590 | return md5(variable_get('netforum_auth_shared_sso_secret', '') ."evensalt". $_SERVER['REMOTE_ADDR'] .'FreeTokensforall!'. $cstid ."nfautthcstid"); |
| 591 | } |
| 592 | |
| 593 | /** |
| 594 | * Take a password and turn it into a unique token |
| 595 | * |
| 596 | */ |
| 597 | function _netforum_auth_make_password_token($cst_web_password = '', $timestamp = ''){ |
| 598 | if ($timestamp == '') { |
| 599 | $timestamp = time(); |
| 600 | } |
| 601 | return md5('nfauthpwstr'. $cst_web_password .'oddsalt'. $_SERVER['REMOTE_ADDR'] .'goodfornow'. $timestamp ."looooongstringsalt!". variable_get('netforum_auth_shared_sso_secret', '')); |
| 602 | } |
| 603 | |
| 604 | /** |
| 605 | * Find out if the password matches a recently generated token |
| 606 | * |
| 607 | * for the tokens to match they must be generated within 20 seconds of each other and requsted by the same host/ip address |
| 608 | */ |
| 609 | function _netforum_auth_match_password_token($cst_web_password, $token) { |
| 610 | $seconds_back = 10; |
| 611 | $timestamp = time(); |
| 612 | $match = false; |
| 613 | for ($i = 0; $i <= $seconds_back ; $i++) { |
| 614 | $internal_token = _netforum_auth_make_password_token($cst_web_password, ($timestamp - $i)); |
| 615 | if ($internal_token == $token) { |
| 616 | $match = true; |
| 617 | break; |
| 618 | } |
| 619 | } |
| 620 | return $match; |
| 621 | } |
| 622 | |
| 623 | /** |
| 624 | * Implementation of hook_auth() |
| 625 | * |
| 626 | * uses xWeb to get an auth token, returns true if the token is set, |
| 627 | * false if the token is empty (eg, all zeroes) |
| 628 | * |
| 629 | * Also intercepts all login requests with an email address associated and |
| 630 | * authenticates against netFORUM. Local users should have no @ sign in their |
| 631 | * username |
| 632 | */ |
| 633 | function netforum_authentication_auth($username, $password, $server) { |
| 634 | global $_netforum_auth_password_plain; |
| 635 | $_netforum_auth_password_plain = $password; |
| 636 | if ($server != '') { |
| 637 | $username .= "@$server"; |
| 638 | } |
| 639 | |
| 640 | //If we are using OD skip the rest of our function and let the OD function handle it. |
| 641 | if (netforum_is_team()) { |
| 642 | return _netforum_authentication_auth_od($username, $password); |
| 643 | } |
| 644 | |
| 645 | $result = netforum_xweb_request("WebLogin", array("userLoginPlain" => $username, |
| 646 | "passwordPlain" => $password, |
| 647 | "keyOverride" => "")); |
| 648 | |
| 649 | if (is_null($result) || isset($result->WebLoginResult) === false ) { |
| 650 | //try local authentication juuuust in case xWeb is unavailable |
| 651 | if (_netforum_authentication_auth_local($username, $password)) { |
| 652 | return true; |
| 653 | } |
| 654 | else { |
| 655 | drupal_set_message(t('Could not communicate with authentication server, please try again in a few minutes'), 'error'); |
| 656 | watchdog('netforum', t("Could not authenticate user %username because the xweb query returned a null result - is the server available and responsive?", array('%username' => $username)), WATCHDOG_ERROR); |
| 657 | return false; |
| 658 | } |
| 659 | } |
| 660 | |
| 661 | |
| 662 | $auth_token = $result->WebLoginResult; |
| 663 | |
| 664 | if (netforum_is_empty_guid($auth_token)) { |
| 665 | return FALSE; |
| 666 | } |
| 667 | else { |
| 668 | global $_netforum_auth_token; |
| 669 | $_netforum_auth_token = $auth_token; |
| 670 | return TRUE; |
| 671 | } |
| 672 | |
| 673 | } |
| 674 | |
| 675 | /** |
| 676 | * Called from netforum_authentication_auth which is the implementation of hook_auth() |
| 677 | * |
| 678 | * uses xWeb On Demand to verify a login, returns true a matching username and pw, |
| 679 | * false if CheckeWebUser returns no records |
| 680 | * |
| 681 | */ |
| 682 | function _netforum_authentication_auth_od($username, $password) { |
| 683 | $result = netforum_xweb_request("CheckEWebUser", array("szEmail" => $username, |
| 684 | "szPassword" => $password)); |
| 685 | |
| 686 | if (is_null($result) ) { |
| 687 | //try local authentication juuuust in case xWeb is unavailable |
| 688 | if (_netforum_authentication_auth_local($username, $password)) { |
| 689 | $_SESSION['_netforum_auth_eweb_pw'] = $password; |
| 690 | return true; |
| 691 | } |
| 692 | else { |
| 693 | drupal_set_message(t('Could not communicate with authentication server, please try again in a few minutes'), 'error'); |
| 694 | watchdog('netforum', t("Could not authenticate user %username because the xweb query returned a null result - is the server available and responsive?", array('%username' => $username)), WATCHDOG_ERROR); |
| 695 | return false; |
| 696 | } |
| 697 | } |
| 698 | |
| 699 | if ($result->attributes()->recordReturn == 0) { |
| 700 | return FALSE; |
| 701 | } |
| 702 | else { |
| 703 | global $_netforum_auth_eweb_od_user; |
| 704 | $_netforum_auth_eweb_od_user = $result->Result; |
| 705 | $_SESSION['_netforum_auth_eweb_pw'] = $password; //We'll need this if they hit a link going to the netforum site |
| 706 | return TRUE; |
| 707 | } |
| 708 | } |
| 709 | |
| 710 | /** |
| 711 | * Authenticate a username using the local DB cache |
| 712 | * |
| 713 | */ |
| 714 | function _netforum_authentication_auth_local($username, $password) { |
| 715 | $result = db_query("SELECT uid FROM {users} WHERE name='%s' AND cst_web_password = '%s'", $username, netforum_auth_hash_pw($password)); |
| 716 | if (db_num_rows($result) > 0) { |
| 717 | return true; |
| 718 | } |
| 719 | else { |
| 720 | return false; |
| 721 | } |
| 722 | } |
| 723 | |
| 724 | /** |
| 725 | * Implementation of hook_info() |
| 726 | * |
| 727 | */ |
| 728 | function netforum_authentication_info($field = 0) { |
| 729 | $info['name'] = 'netFORUM'; |
| 730 | $info['protocol'] = 'SOAP'; |
| 731 | |
| 732 | if ($field) { |
| 733 | return $info[$field]; |
| 734 | } |
| 735 | else { |
| 736 | return $info; |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | /** |
| 741 | * Implementation of hook_user() |
| 742 | * |
| 743 | */ |
| 744 | function netforum_authentication_user($op, &$edit, &$account, $category = NULL) { |
| 745 | global $user; |
| 746 | switch ($op) { |
| 747 | case 'load': |
| 748 | //we do a lot on load because whenever a user is displayed, logged in, or worked with they should have the most up to date information, |
| 749 | //which means getting all of their data from netFORUM |
| 750 | if (!netforum_is_empty_guid($account->cst_key)) { |
| 751 | if ($_SESSION['netforum_auth_skip_info_sync'] !== true) { |
| 752 | global $_netforum_auth_already_checked_roles; |
| 753 | $ignore_roles = netforum_auth_ignore_roles(); |
| 754 | $new_info = array(); |
| 755 | |
| 756 | |
| 757 | if ($_netforum_auth_already_checked_roles !== true) { |
| 758 | $netforum_roles = netforum_auth_map_user_roles($account); |
| 759 | //If there is no response from xweb we get an empty array, this is to prevent us from mistaing no response for no roles or entering an infinite update loop |
| 760 | if (netforum_auth_fresh_user_categories() === true) { |
| 761 | //these are the roles that are checked off on the site's user edit page, not set via netForum. |
| 762 | $sticky_roles = array(); |
| 763 | //no, not the delicious kind of sticky roles. |
| 764 | |
| 765 | if (is_array($account->netforum_auth_admin_set_roles)) { |
| 766 | $sticky_roles = array_diff_key($account->netforum_auth_admin_set_roles, $netforum_roles); //take out the roles that are being set by netforum |
| 767 | $sticky_roles = array_diff_key($sticky_roles, $ignore_roles); //take out the roles like authenticated user |
| 768 | |
| 769 | if ($sticky_roles != $account->netforum_auth_admin_set_roles) { |
| 770 | //if the netforum roles now include a role that was sticky it's removed from the sticky roles and is no longer given to the user by the sticky roles. |
| 771 | //That way, when netforum stops returning that role, then it will also dissapear from their account. |
| 772 | $new_info['netforum_auth_admin_set_roles'] = $sticky_roles; |
| 773 | } |
| 774 | } |
| 775 | |
| 776 | //Now we need to look at the current user roles (from the db) and compare them to the combined netforum roles and sticky roles. |
| 777 | //if they are different, update the roles and save them to the database. |
| 778 | $combined_roles = array(); |
| 779 | foreach ($sticky_roles as $k => $v) { |
| 780 | $combined_roles[$k] = $v; |
| 781 | } |
| 782 | foreach ($netforum_roles as $k => $v){ |
| 783 | $combined_roles[$k] = $v; |
| 784 | } |
| 785 | |
| 786 | //just to make sure that that the roles we're comparing are the actual values from site, eg if the name of the role was changed, |
| 787 | //we use array_walk to replace the values of our combined roles array with the freshest site values based on the id |
| 788 | $site_roles = user_roles(true); |
| 789 | array_walk($combined_roles, create_function('&$v, $k, &$roles', '$v = $roles[$k];'), $site_roles); |
| 790 | |
| 791 | //If there is some change, store them in the database. This way, if xWeb is unavailable we can still give the user appropriate permissions |
| 792 | if ($combined_roles != array_diff_key($account->roles, $ignore_roles)) { |
| 793 | $new_info['roles'] = $combined_roles; |
| 794 | } |
| 795 | $_netforum_auth_already_checked_roles = true; |
| 796 | } //end ofthe roles checking and assigning |
| 797 | } |
| 798 | |
| 799 | $cst_fields = netforum_auth_user_fields(); |
| 800 | $eml_field = _netforum_auth_get_email_field('Customer'); |
| 801 | if (in_array($eml_field, $cst_fields) === false) { |
| 802 | $cst_fields[] = $eml_field; //make sure we grab the email address |
| 803 | } |
| 804 | if (in_array('cst_web_force_password_change', $cst_fields) === false) { |
| 805 | $cst_fields[] = 'cst_web_force_password_change'; //make sure we check to see if they should change their pw |
| 806 | } |
| 807 | |
| 808 | //Now that we know what fields we want, go get them |
| 809 | $cst_obj = false; |
| 810 | if (netforum_is_enterprise()) { //Enterprise only gets the query |
| 811 | //check to see if any of the customer fields are different from the information in the DB |
| 812 | $query = Array('szObjectName' => 'Customer', |
| 813 | 'szColumnList' => implode(", ", $cst_fields), |
| 814 | 'szWhereClause' => "cst_key = '". $account->cst_key ."'", |
| 815 | 'szOrderBy' => ''); |
| 816 | $response = netforum_xweb_request('GetQuery', $query, '3 seconds'); //do not look for cached results to this query longer than this request |
| 817 | if ($response && $response->attributes()->recordReturn == 1) { |
| 818 | $cst_obj = $response->CustomerObject; |
| 819 | } |
| 820 | } |
| 821 | else { //This is the NF OD Section |
| 822 | //For netFORUM Team/Pro/On Demand use the data returned from CheckEWebUser |
| 823 | global $_netforum_auth_eweb_od_user; |
| 824 | if (isset($_netforum_auth_eweb_od_user)) { |
| 825 | $cst_obj = $_netforum_auth_eweb_od_user; |
| 826 | } |
| 827 | else { |
| 828 | $query = Array('szObjectName' => 'Customer', |
| 829 | 'sz' => implode(", ", $cst_fields), |
| 830 | 'szWhereClause' => "cst_key = '". $account->cst_key ."'", |
| 831 | 'szOrderBy' => ''); |
| 832 | |
| 833 | |
| 834 | $arguments = array( |
| 835 | 'szObjectName' => "Customer", |
| 836 | 'szObjectKey' => $account->cst_key, |
| 837 | ); |
| 838 | $response = netforum_xweb_request('GetFacadeObject', $arguments, '3 seconds'); //do not look for cached results to this query longer than this request |
| 839 | if ($response && $response->attributes()->recordReturn == 1) { |
| 840 | $cst_obj = $response->CustomerObject; |
| 841 | } |
| 842 | } |
| 843 | } |
| 844 | |
| 845 | // If either of the above calls to get user data succeeded, load up the account |
| 846 | if ($cst_obj) { |
| 847 | $email = (string)$cst_obj->{$eml_field}; |
| 848 | if ($account->mail != $email ) { |
| 849 | $new_info['mail'] = $email; |
| 850 | } |
| 851 | |
| 852 | if ((int)$cst_obj->cst_web_force_password_change == 1) { |
| 853 | global $_netforum_auth_must_change_pw; |
| 854 | $_netforum_auth_must_change_pw = true; |
| 855 | } |
| 856 | |
| 857 | foreach ($cst_fields as $field) { |
| 858 | $field_value = (string)$cst_obj->{$field}; |
| 859 | if (empty($field) === false && $account->{$field} != $field_value) { |
| 860 | $new_info[$field] = $field_value; |
| 861 | } |
| 862 | } |
| 863 | } |
| 864 | |
| 865 | if (count($new_info) > 0) { |
| 866 | user_save($account, $new_info); |
| 867 | } |
| 868 | } |
| 869 | } |
| 870 | break; |
| 871 | |
| 872 | case 'login': |
| 873 | global $_netforum_auth_must_change_pw; |
| 874 | |
| 875 | if ($_netforum_auth_must_change_pw === true) { |
| 876 | $current_path = isset($_GET['q']) ? $_GET['q'] : ''; |
| 877 | $edit_path = 'user/'. $account->uid .'/edit'; |
| 878 | if ($current_path != $edit_path && ($user->uid == $account->uid)) { |
| 879 | drupal_set_message('Your password needs to be reset, please do so now by clicking '. l('here', $edit_path), 'error'); |
| 880 | } |
| 881 | } |
| 882 | //Shared SSO is Enterprise only |
| 883 | if (netforum_is_enterprise() && netforum_is_empty_guid($account->cst_key) === false) { |
| 884 | |
| 885 | netforum_auth_eweb_sso_login(); |
| 886 | |
| 887 | $shared_sso_url = variable_get('netforum_auth_shared_sso_url', ''); |
| 888 | if ($shared_sso_url != '') { |
| 889 | if (substr($shared_sso_url, -1) != "/") { |
| 890 | $shared_sso_url .= "/"; |
| 891 | } |
| 892 | $cstid_token = _netforum_auth_make_cstid_token($account->cst_id); |
| 893 | $pw_token = _netforum_auth_make_password_token($account->cst_web_password); |
| 894 | $link_attributes = array('rel' => 'stylesheet', 'type' => 'text/css', |
| 895 | 'href' => $shared_sso_url ."user/netforum_sso_share/". $account->cst_id ."/". $cstid_token ."/". $pw_token); |
| 896 | $_SESSION['netforum_auth_link'] = $link_attributes; |
| 897 | } |
| 898 | } |
| 899 | break; |
| 900 | |
| 901 | case 'logout': //Enterprise only |
| 902 | if (netforum_is_empty_guid($account->cst_key) === false) { |
| 903 | netforum_auth_eweb_sso_logout(); |
| 904 | unset($_SESSION['_netforum_auth_eweb_pw']); |
| 905 | } |
| 906 | break; |
| 907 | |
| 908 | case 'insert': |
| 909 | global $_netforum_auth_token, $_netforum_auth_cst_key, $_netforum_auth_eweb_od_user; |
| 910 | |
| 911 | $nf_user_data = array(); //The goal is to populate this so we can add in the new user |
| 912 | $eml_field = _netforum_auth_get_email_field('Customer'); |
| 913 | $needed_columns = array_unique(array('cst_type', 'cst_web_password', 'cst_id') + netforum_auth_user_fields()); |
| 914 | |
| 915 | |
| 916 | //For Enterprise netforum if we have the customer key or can get it |
| 917 | if (netforum_is_empty_guid($_netforum_auth_token) === false || netforum_is_empty_guid($_netforum_auth_cst_key) === false) { |
| 918 | if (netforum_is_empty_guid($_netforum_auth_token) === false) { |
| 919 | $result = netforum_xweb_request("WebValidate", array("authenticationToken" => $_netforum_auth_token)); |
| 920 | if (is_null($result) || isset($result->WebValidateResult) === false ) { |
| 921 | drupal_set_message(t('Could not fetch netFORUM information for new user'), 'error'); |
| 922 | break; |
| 923 | } |
| 924 | else { |
| 925 | $_netforum_auth_cst_key = (string)$result->WebValidateResult; |
| 926 | $_netforum_auth_token = null; //unset this so we don't keep calling xweb |
| 927 | } |
| 928 | } |
| 929 | |
| 930 | if (netforum_is_empty_guid($_netforum_auth_cst_key) === false) { |
| 931 | |
| 932 | $query = Array('szObjectName' => 'Customer', |
| 933 | 'szColumnList' => $eml_field .", ". implode($needed_columns, ", "), |
| 934 | 'szWhereClause' => "cst_key = '". $_netforum_auth_cst_key ."'", |
| 935 | 'szOrderBy' => ''); |
| 936 | $response = netforum_xweb_request('GetQuery', $query); |
| 937 | if (isset($response) && $response->attributes()->recordReturn == 1) { |
| 938 | $cst_obj = $response->CustomerObject; |
| 939 | $nf_user_data = Array( |
| 940 | 'cst_key' => $_netforum_auth_cst_key, |
| 941 | 'mail' => (string)$cst_obj->{$eml_field}, |
| 942 | ); |
| 943 | foreach($needed_columns as $col) { |
| 944 | $nf_user_data[$col] = (string)$cst_obj->{$col}; |
| 945 | } |
| 946 | $nf_user_data['cst_web_password'] = (string)$cst_obj->cst_web_password; |
| 947 | } |
| 948 | else { |
| 949 | $nf_user_data['cst_key'] = $_netforum_auth_cst_key; |
| 950 | } |
| 951 | } |
| 952 | } |
| 953 | |
| 954 | //For netFORUM Team/Pro/On Demand use the data returned from CheckEWebUser |
| 955 | if (isset($_netforum_auth_eweb_od_user)) { |
| 956 | $nf_user_data = Array( |
| 957 | 'cst_key' => (string)$_netforum_auth_eweb_od_user->cst_key, |
| 958 | 'mail' => (string)$_netforum_auth_eweb_od_user->{$eml_field}, |
| 959 | ); |
| 960 | foreach($needed_columns as $col) { |
| 961 | $nf_user_data[$col] = (string)$_netforum_auth_eweb_od_user->{$col}; |
| 962 | } |
| 963 | $nf_user_data['cst_web_password'] = (string)$_netforum_auth_eweb_od_user->cst_web_password; |
| 964 | } |
| 965 | |
| 966 | |
| 967 | if ($nf_user_data) { |
| 968 | user_save($account, $nf_user_data); |
| 969 | } |
| 970 | |
| 971 | |
| 972 | break; |
| 973 | |
| 974 | case 'update': |
| 975 | if ( netforum_is_empty_guid($account->cst_key) === false) { |
| 976 | if (netforum_is_enterprise()) { //We only push data back to Enterprise netforum |
| 977 | $eml_field = _netforum_auth_get_email_field('Customer'); |
| 978 | //this array keeps key => value pairs to correspond to the netFORUM information to be updated. |
| 979 | $nf_variables = array(); |
| 980 | if (strtolower(variable_get('netforum_auth_user_editing', '<drupal>')) == '<drupal>') { |
| 981 | if (isset($edit['mail']) && $edit['mail'] != '' && $edit['mail'] != $account->mail) { |
| 982 | $nf_variables[$eml_field] = $edit['mail']; |
| 983 | } |
| 984 | if (isset($edit['pass']) && empty($edit['pass']) === false) { |
| 985 | $nf_variables['cst_web_password'] = $edit['pass']; |
| 986 | $nf_variables['cst_web_force_password_change'] = 0; |
| 987 | //Save cst_web_password because we use it if the user is logging in and xWeb is not available. |
| 988 | $edit['cst_web_password'] = netforum_auth_hash_pw($edit['pass']); |
| 989 | } |
| 990 | if (isset($edit['name']) && $edit['name'] != '' && $edit['name'] != $account->name) { |
| 991 | $nf_variables['cst_web_login'] = $edit['name']; |
| 992 | } |
| 993 | } |
| 994 | |
| 995 | if (count($nf_variables) > 0) { |
| 996 | $success = false; //don't assume it worked by default, this is set on success below |
| 997 | if ($account->cst_type == 'Individual') { //this way customers and individuals can log in and edit info. Beware when setting variables above that they are cst_type agnostic |
| 998 | $data_node = netforum_ind_info_parameters($nf_variables); |
| 999 | $response = netforum_xweb_request('SetIndividualInformation', array('IndividualKey' => $account->cst_key, 'oUpdateNode' => $data_node)); |
| 1000 | if (isset($response) && $response->attributes()->recordReturn == 1 && $response->IndividualObject->ind_cst_key == $account->cst_key) { |
| 1001 | $success = true; |
| 1002 | } |
| 1003 | } |
| 1004 | elseif ($account->cst_type == 'Organization') { |
| 1005 | $data_node = netforum_org_info_parameters($nf_variables); |
| 1006 | $response = netforum_xweb_request('SetOrganizationInformation', array('OrganizationKey' => $account->cst_key, 'oUpdateNode' => $data_node)); |
| 1007 | if ( isset($response) && $response->attributes()->recordReturn == 1 && $response->OrganizationObject->org_cst_key == $account->cst_key) { |
| 1008 | $success = true; |
| 1009 | } |
| 1010 | } |
| 1011 | |
| 1012 | if ($success === false) { |
| 1013 | drupal_set_message(t('Information update failed, please try again in a few minutes.'), 'error'); |
| 1014 | watchdog('netforum', t("Could not update user information in netFORUM for %name", array('%name' => $account->name)), WATCHDOG_ERROR); |
| 1015 | $path = isset($_GET['q']) ? $_GET['q'] : ''; |
| 1016 | $query = drupal_query_string_encode($_GET, array('q')); |
| 1017 | if ($query != '') { |
| 1018 | $path .= '?'. $query; |
| 1019 | } |
| 1020 | drupal_goto($path); |
| 1021 | } |
| 1022 | else { |
| 1023 | $_SESSION['netforum_auth_skip_info_sync'] = true; |
| 1024 | } |
| 1025 | } |
| 1026 | } |
| 1027 | |
| 1028 | if (isset($edit['roles']) ) { |
| 1029 | //keep track of any roles set in case it was set by an admin. If the admin added a role that doesn't get set via netforum remember that and |
| 1030 | //add / save it in when the user is loaded. If the role is later something gets set for this user via netforum, then when it is removed (ie, no longer |
| 1031 | //set via netforum) it will also be removed from the user record. That means you can make the website override netforum, but if netforum later gives that |
| 1032 | //permission it will be taken away when netforum also takes it away. |
| 1033 | |
| 1034 | //what's the phrase? Store em all and let the load sort it out? |
| 1035 | $edit['netforum_auth_admin_set_roles'] = $edit['roles']; |
| 1036 | } |
| 1037 | } |
| 1038 | |
| 1039 | break; |
| 1040 | |
| 1041 | case 'after_update': |
| 1042 | if (isset($_SESSION['netforum_auth_skip_info_sync']) && $_SESSION['netforum_auth_skip_info_sync'] === true) { |
| 1043 | unset($_SESSION['netforum_auth_skip_info_sync']); |
| 1044 | } |
| 1045 | break; |
| 1046 | |
| 1047 | default: |
| 1048 | break; |
| 1049 | } |
| 1050 | } |
| 1051 | |
| 1052 | /** |
| 1053 | * Fetch the netforum criteria for assigning users to groups |
| 1054 | * |
| 1055 | * This function should return an associative array of netFORUM keys and |
| 1056 | * descrptions that will be used to determine what drupal roles map to |
| 1057 | * what netFORUM roles. For example, member types or committes. |
| 1058 | * |
| 1059 | * To assign users to groups based on something other than membership create |
| 1060 | * a module that implements hook_netforum_auth_categories. |
| 1061 | * |
| 1062 | * If you use netFORUM Team or Pro use hook_netforum_auth_od_categories |
| 1063 | * |
| 1064 | * Remember to cast all associatve array keys to strings before storing in the array |
| 1065 | * |
| 1066 | * @return |
| 1067 | * Returns an associative array of unique keys corresponding to descriptions |
| 1068 | */ |
| 1069 | function netforum_auth_categories() { |
| 1070 | $categories = array(); |
| 1071 |