Array('self' => 'view'), // because setting to logged in user only 'OnUpdateRootPassword' => Array('self' => true), 'OnUpdatePassword' => Array('self' => true), 'OnSaveSelected' => Array ('self' => 'view'), 'OnGeneratePassword' => Array ('self' => 'view'), // front 'OnRefreshForm' => Array('self' => true), 'OnForgotPassword' => Array('self' => true), 'OnSubscribeQuery' => Array('self' => true), 'OnSubscribeUser' => Array('self' => true), 'OnRecommend' => Array('self' => true), 'OnItemBuild' => Array('self' => true), 'OnMassResetSettings' => Array('self' => 'edit'), 'OnMassCloneUsers' => Array('self' => 'add'), ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Builds item (loads if needed) * * Pattern: Prototype Manager * * @param kEvent $event * @access protected */ function OnItemBuild(&$event) { parent::OnItemBuild($event); if ($event->Special == 'forgot') { $this->_makePasswordRequired($event); } } /** * Shows only admins when required * * @param kEvent $event */ function SetCustomQuery(&$event) { $object =& $event->getObject(); /* @var $object kDBList */ if ($event->Special == 'regular') { $object->addFilter('primary_filter', '%1$s.UserType = ' . UserType::USER); } if ($event->Special == 'admins') { $object->addFilter('primary_filter', '%1$s.UserType = ' . UserType::ADMIN); } if (!$this->Application->isAdminUser) { $object->addFilter('status_filter', '%1$s.Status = '.STATUS_ACTIVE); } if ($event->Special == 'online') { $object->addFilter('online_users_filter', 's.PortalUserId IS NOT NULL'); } if ($event->Special == 'group') { $group_id = $this->Application->GetVar('g_id'); if ($group_id !== false) { // show only users, that user doesn't belong to current group $sql = 'SELECT PortalUserId FROM ' . $this->Application->GetTempName(TABLE_PREFIX.'UserGroup', 'prefix:g') . ' WHERE GroupId = ' . (int)$group_id; $user_ids = $this->Conn->GetCol($sql); if ($user_ids) { $object->addFilter('already_member_filter', '%1$s.PortalUserId NOT IN (' . implode(',', $user_ids) . ')'); } } } } /** * Checks permissions of user * * @param kEvent $event */ function CheckPermission(&$event) { if ($event->Name == 'OnLogin' || $event->Name == 'OnLogout') { // permission is checked in OnLogin event directly return true; } if (!$this->Application->isAdminUser) { $user_id = $this->Application->RecallVar('user_id'); $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); if ($event->Name == 'OnCreate' && $user_id == USER_GUEST) { // "Guest" can create new users return true; } if ($event->Name == 'OnUpdate' && $user_id > 0) { $user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true)); foreach ($items_info as $id => $field_values) { if ($id != $user_id) { // registered users can update their record only return false; } $user_dummy->Load($id); $status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField')); if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) { // not active user is not allowed to update his record (he could not activate himself manually) return false; } if (isset($field_values[$status_field]) && $user_dummy->GetDBField($status_field) != $field_values[$status_field]) { // user can't change status by himself return false; } } return true; } if ( $event->Name == 'OnResetLostPassword' && $event->Special == 'forgot' && $user_id == USER_GUEST ) { // non-logged in users can reset their password, when reset code is valid return is_numeric( $this->getPassedID($event) ); } if ($event->Name == 'OnUpdate' && $user_id <= 0) { // guests are not allowed to update their record, because they don't have it :) return false; } } return parent::CheckPermission($event); } /** * Handles session expiration (redirects to valid template) * * @param kEvent $event */ function OnSessionExpire(&$event) { $this->Application->resetCounters('UserSession'); // place 2 of 2 (also in kHTTPQuery::getRedirectParams) $admin_url_params = Array ( 'm_cat_id' => 0, // category means nothing on admin login screen 'm_wid' => '', // remove wid, otherwise parent window may add wid to its name breaking all the frameset (for targets) 'pass' => 'm', // don't pass any other (except "m") prefixes to admin session expiration template 'expired' => 1, // expiration mark to show special error on login screen 'no_pass_through' => 1, // this way kApplication::HREF won't add them again ); if ($this->Application->isAdmin) { $this->Application->Redirect('index', $admin_url_params, '', 'index.php'); } if ($this->Application->GetVar('admin') == 1) { // Front-End showed in admin's right frame $session_admin =& $this->Application->recallObject('Session.admin'); /* @var $session_admin Session */ if (!$session_admin->LoggedIn()) { // front-end session created from admin session & both expired $this->Application->DeleteVar('admin'); $this->Application->Redirect('index', $admin_url_params, '', 'admin/index.php'); } } // Front-End session expiration $get = $this->Application->HttpQuery->getRedirectParams(); $t = $this->Application->GetVar('t'); $get['js_redirect'] = $this->Application->ConfigValue('UseJSRedirect'); $this->Application->Redirect($t ? $t : 'index', $get); } /** * [AGENT] Deletes expired sessions * * @param kEvent $event */ function OnDeleteExpiredSessions(&$event) { if (defined('IS_INSTALL') && IS_INSTALL) { return ; } $this->Application->Session->DeleteExpired(); } /** * Checks user data and logs it in if allowed * * @param kEvent $event */ function OnLogin(&$event) { $email_as_login = $this->Application->ConfigValue('Email_As_Login'); $username = $this->Application->GetVar($email_as_login && !$this->Application->isAdmin ? 'email' : 'login'); $password = $this->Application->GetVar('password'); $rember_login = $this->Application->GetVar('cb_remember_login') == 1; $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $user_helper->event =& $event; $result = $user_helper->loginUser($username, $password, false, $rember_login); if ($result != LoginResult::OK) { $object =& $user_helper->getUserObject(); if ($result == LoginResult::NO_PERMISSION) { $object->SetError('ValidateLogin', 'no_permission', 'la_no_permissions'); } else { $object->SetID(USER_GUEST); $object->SetError('ValidateLogin', 'invalid_password', 'la_invalid_password'); } $event->status = kEvent::erFAIL; } } /** * [HOOK] Auto-Logins Front-End user when "Remember Login" cookie is found * * @param kEvent $event */ function OnAutoLoginUser(&$event) { $remember_login_cookie = $this->Application->GetVar('remember_login'); if (!$remember_login_cookie || $this->Application->isAdmin || $this->Application->LoggedIn()) { return ; } $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $user_helper->loginUser('', '', false, false, $remember_login_cookie); } /** * Called when user logs in using old in-portal * * @param kEvent $event */ function OnInpLogin(&$event) { $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); $sync_manager->performAction('LoginUser', $event->getEventParam('user'), $event->getEventParam('pass') ); if ($event->redirect && is_string($event->redirect)) { // some real template specified instead of true $this->Application->Redirect($event->redirect, $event->getRedirectParams()); } } /** * Called when user logs in using old in-portal * * @param kEvent $event */ function OnInpLogout(&$event) { $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); $sync_manager->performAction('LogoutUser'); } function OnLogout(&$event) { $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $user_helper->event =& $event; $user_helper->logoutUser(); } /** * Redirects user after succesfull registration to confirmation template (on Front only) * * @param kEvent $event */ function OnAfterItemCreate(&$event) { $this->afterItemChanged($event); $object =& $event->getObject(); /* @var $object kDBItem */ $primary_group_id = $object->GetDBField('PrimaryGroupId'); if ($primary_group_id) { $ug_table = TABLE_PREFIX . 'UserGroup'; if ( $object->IsTempTable() ) { $ug_table = $this->Application->GetTempName($ug_table, 'prefix:' . $event->Prefix); } $fields_hash = Array ( 'PortalUserId' => $object->GetID(), 'GroupId' => $primary_group_id, ); $this->Conn->doInsert($fields_hash, $ug_table, 'REPLACE'); } } /** * Login user if possible, if not then redirect to corresponding template * * @param kEvent $event */ function autoLoginUser(&$event) { $object =& $event->getObject(); $this->Application->SetVar('u.current_id', $object->GetID()); if ($object->GetDBField('Status') == STATUS_ACTIVE && !$this->Application->ConfigValue('User_Password_Auto')) { $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $user_helper->loginUser($object->GetDBField('Login'), $object->GetDBField('Password_plain')); } } /** * When creating user & user with such email exists then force to use OnUpdate insted of ? * * @param kEvent $event */ function OnSubstituteSubscriber(&$event) { $ret = false; $object =& $event->getObject( Array('skip_autoload' => true) ); $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if ($items_info) { list($id, $field_values) = each($items_info); $user_email = isset($field_values['Email']) ? $field_values['Email'] : false; if ($user_email) { // check if is subscriber $verify_user =& $this->Application->recallObject('u.verify', null, Array('skip_autoload' => true) ); $verify_user->Load($user_email, 'Email'); if ( $verify_user->isLoaded() && $verify_user->isSubscriberOnly() ) { $items_info = Array( $verify_user->GetDBField('PortalUserId') => $field_values ); $this->Application->SetVar($event->getPrefixSpecial(true), $items_info); $ret = true; } } } if ( isset($event->MasterEvent) ) { $event->MasterEvent->setEventParam('is_subscriber_only', $ret); } else { $event->setEventParam('is_subscriber_only', $ret); } } /** * Enter description here... * * @param kEvent $event * @param bool $dry_run * @return bool */ function isSubscriberOnly(&$event, $dry_run = false) { $event->CallSubEvent('OnSubstituteSubscriber'); $is_subscriber = $event->getEventParam('is_subscriber_only'); if ($dry_run) { return $is_subscriber; } if ($is_subscriber) { $object =& $event->getObject( Array('skip_autoload' => true) ); $this->OnUpdate($event); if ($event->status == kEvent::erSUCCESS) { $this->OnAfterItemCreate($event); $object->SendEmailEvents(); if (!$this->Application->isAdmin && $event->redirect) { $this->autoLoginUser($event); } } } return $is_subscriber; } /** * Creates new user * * @param kEvent $event */ function OnCreate(&$event) { if (!$this->Application->isAdminUser) { $this->setUserStatus($event); } if ( !$this->isSubscriberOnly($event) ) { $object =& $event->getObject( Array('skip_autoload' => true) ); /* @var $object UsersItem */ if ( $this->Application->ConfigValue('User_Password_Auto') ) { $password = $object->generatePassword( rand(5, 8) ); $this->Application->SetVar('user_password', $password); } parent::OnCreate($event); $this->Application->SetVar('u.current_id', $object->getID()); // for affil:OnRegisterAffiliate after hook $this->setNextTemplate($event); if (!$this->Application->isAdmin && ($event->status == kEvent::erSUCCESS) && $event->redirect) { $object->SendEmailEvents(); $this->autoLoginUser($event); } } } /** * Set's new user status based on config options * * @param kEvent $event */ function setUserStatus(&$event) { $object =& $event->getObject( Array('skip_autoload' => true) ); $new_users_allowed = $this->Application->ConfigValue('User_Allow_New'); switch ($new_users_allowed) { case 1: // Immediate $object->SetDBField('Status', STATUS_ACTIVE); $next_template = $this->Application->GetVar('registration_confirm_template'); if ($next_template) { $event->redirect = $next_template; } break; case 3: // Upon Approval case 4: // Email Activation $next_template = $this->Application->GetVar('registration_confirm_pending_template'); if ($next_template) { $event->redirect = $next_template; } $object->SetDBField('Status', STATUS_PENDING); break; case 2: // Not Allowed $object->SetDBField('Status', STATUS_DISABLED); break; } } /** * Set's new unique resource id to user * * @param kEvent $event */ function OnBeforeItemCreate(&$event) { parent::OnBeforeItemCreate($event); $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ if ( !$this->isSubscriberOnly($event, true) ) { $cs_helper->CheckStateField($event, 'State', 'Country'); } $this->_makePasswordRequired($event); $cs_helper->PopulateStates($event, 'State', 'Country'); $object =& $event->getObject(); /* @var $object UsersItem */ if ( $this->Application->ConfigValue('Email_As_Login') ) { $field_options = $object->GetFieldOptions('Email'); $field_options['error_msgs']['unique'] = $this->Application->Phrase('lu_user_and_email_already_exist'); $object->SetFieldOptions('Email', $field_options); } $this->setUserGroup($object); $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ if (!$user_helper->checkBanRules($object)) { $event->status = kEvent::erFAIL; return ; } } /** * Sets primary group of the user * * @param kDBItem $object */ protected function setUserGroup(&$object) { if ($object->Special == 'subscriber') { $object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_SubscriberGroup')); return ; } // set primary group to user if ( !$this->Application->isAdminUser ) { $group_id = $object->GetDBField('PrimaryGroupId'); if ($group_id) { // check, that group is allowed for Front-End $sql = 'SELECT GroupId FROM ' . TABLE_PREFIX . 'PortalGroup WHERE GroupId = ' . (int)$group_id . ' AND FrontRegistration = 1'; $group_id = $this->Conn->GetOne($sql); } if (!$group_id) { // when group not selected OR not allowed -> use default group $object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_NewGroup')); } } } /** * Set's new unique resource id to user * * @param kEvent $event */ function OnAfterItemValidate(&$event) { $object =& $event->getObject(); /* @var $object kDBItem */ $resource_id = $object->GetDBField('ResourceId'); if (!$resource_id) { $object->SetDBField('ResourceId', $this->Application->NextResourceId()); } } /** * Enter description here... * * @param kEvent $event */ function OnRecommend(&$event) { $friend_email = $this->Application->GetVar('friend_email'); $friend_name = $this->Application->GetVar('friend_email'); // used for error reporting only -> rewrite code + theme (by Alex) $object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too /* @var $object UsersItem */ if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $friend_email)) { /*$cutoff = adodb_mktime() + (int)$this->Application->ConfigValue('Suggest_MinInterval'); $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'SuggestMail WHERE email = ' . $this->Conn->qstr($friend_email) . ' AND sent < ' . $cutoff; if ($this->Conn->GetRow($sql) !== false) { $object->SetError('Email', 'send_error', 'lu_email_already_suggested'); $event->status = kEvent::erFAIL; return ; }*/ $send_params = Array (); $send_params['to_email'] = $friend_email; $send_params['to_name'] = $friend_name; $user_id = $this->Application->RecallVar('user_id'); $email_event =& $this->Application->EmailEventUser('USER.SUGGEST', $user_id, $send_params); $email_event =& $this->Application->EmailEventAdmin('USER.SUGGEST'); if ($email_event->status == kEvent::erSUCCESS){ /*$fields_hash = Array ( 'email' => $friend_email, 'sent' => adodb_mktime(), ); $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'SuggestMail');*/ $event->setRedirectParams(Array('opener' => 's', 'pass' => 'all'), true); $event->redirect = $this->Application->GetVar('template_success'); } else { // $event->setRedirectParams(Array('opener' => 's', 'pass' => 'all'), true); // $event->redirect = $this->Application->GetVar('template_fail'); $object->SetError('Email', 'send_error', 'lu_email_send_error'); $event->status = kEvent::erFAIL; } } else { $object->SetError('Email', 'invalid_email', 'lu_InvalidEmail'); $event->status = kEvent::erFAIL; } } /** * Saves address changes and mades no redirect * * @param kEvent $event */ function OnUpdateAddress(&$event) { $object =& $event->getObject( Array('skip_autoload' => true) ); $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if ($items_info) { list ($id, $field_values) = each($items_info); if ($id > 0) { $object->Load($id); } $object->SetFieldsFromHash($field_values); $object->setID($id); $object->Validate(); } $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ $cs_helper->PopulateStates($event, 'State', 'Country'); $event->redirect = false; } /** * Validate subscriber's email & store it to session -> redirect to confirmation template * * @param kEvent $event */ function OnSubscribeQuery(&$event) { $user_email = $this->Application->GetVar('subscriber_email'); if ( preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email) ) { $object =& $this->Application->recallObject($this->Prefix . '.subscriber', null, Array('skip_autoload' => true)); /* @var $object UsersItem */ $object->Load($user_email, 'Email'); $event->SetRedirectParam('subscriber_email', $user_email); if ( $object->isLoaded() ) { if ( $this->isSubscribed($object) ) { $event->redirect = $this->Application->GetVar('unsubscribe_template'); } else { $event->redirect = $this->Application->GetVar('subscribe_template'); } } else { $event->redirect = $this->Application->GetVar('subscribe_template'); } } else { // used for error reporting only -> rewrite code + theme (by Alex) $object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too /* @var $object UsersItem */ $object->SetError('SubscribeEmail', 'invalid_email', 'lu_InvalidEmail'); $event->status = kEvent::erFAIL; } } /** * Subscribe/Unsubscribe user based on email stored in previous step * * @param kEvent $event */ function OnSubscribeUser(&$event) { $object = &$this->Application->recallObject($this->Prefix . '.subscriber', null, Array('skip_autoload' => true)); /* @var $object UsersItem */ $user_email = $this->Application->GetVar('subscriber_email'); if ( preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email) ) { $this->RemoveRequiredFields($object); $object->Load($user_email, 'Email'); if ( $object->isLoaded() ) { if ( $this->isSubscribed($object) ) { if ( $event->getEventParam('no_unsubscribe') ) { // for customization code from FormsEventHandler return ; } if ( $object->isSubscriberOnly() ) { $this->Application->SetVar($object->getPrefixSpecial(true) . '_id', $object->GetID()); $delete_event = new kEvent($object->getPrefixSpecial() . ':OnDelete'); $this->Application->HandleEvent($delete_event); } else { $this->RemoveSubscriberGroup( $object->GetID() ); } $event->redirect = $this->Application->GetVar('unsubscribe_ok_template'); } else { $this->AddSubscriberGroup($object); $event->redirect = $this->Application->GetVar('subscribe_ok_template'); } } else { $object->generatePassword(); $object->SetDBField('Email', $user_email); $object->SetDBField('Login', $user_email); $object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default $object->SetDBField('ip', $_SERVER['REMOTE_ADDR']); if ( $object->Create() ) { $this->AddSubscriberGroup($object); $event->redirect = $this->Application->GetVar('subscribe_ok_template'); } } } } /** * Adding user to subscribers group * * @param UsersItem $object */ function AddSubscriberGroup(&$object) { if ( !$object->isSubscriberOnly() ) { $fields_hash = Array ( 'PortalUserId' => $object->GetID(), 'GroupId' => $this->Application->ConfigValue('User_SubscriberGroup'), ); $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'UserGroup'); } $this->Application->EmailEventAdmin('USER.SUBSCRIBE'); $this->Application->EmailEventUser('USER.SUBSCRIBE', $object->GetID()); } /** * Removing user from subscribers group * * @param int $user_id */ function RemoveSubscriberGroup($user_id) { $group_id = $this->Application->ConfigValue('User_SubscriberGroup'); $sql = 'DELETE FROM ' . TABLE_PREFIX . 'UserGroup WHERE PortalUserId = ' . $user_id . ' AND GroupId = ' . $group_id; $this->Conn->Query($sql); $this->Application->EmailEventAdmin('USER.UNSUBSCRIBE'); $this->Application->EmailEventUser('USER.UNSUBSCRIBE', $user_id); } /** * Checks user subscription status * * @param kDBItem $object * @return bool */ function isSubscribed(&$object) { $group_id = $this->Application->ConfigValue('User_SubscriberGroup'); $sql = 'SELECT GroupId FROM ' . TABLE_PREFIX . 'UserGroup WHERE (PortalUserId = ' . $object->GetID() . ') AND (GroupId = ' . $group_id . ')'; return $this->Conn->GetOne($sql); } function OnForgotPassword(&$event) { $user_object =& $this->Application->recallObject('u.forgot', null, Array('skip_autoload' => true)); /* @var $user_object UsersItem */ // used for error reporting only -> rewrite code + theme (by Alex) $user_current_object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too /* @var $user_current_object UsersItem */ $found = $allow_reset = false; $email = $this->Application->GetVar('email'); $username = $this->Application->GetVar('username'); if ( strlen($username) ) { $user_object->Load($username, 'Login'); } elseif( strlen($email) ) { $user_object->Load($email, 'Email'); } if ( $user_object->isLoaded() ) { $min_pwd_reset_delay = $this->Application->ConfigValue('Users_AllowReset'); $found = ($user_object->GetDBField('Status') == STATUS_ACTIVE) && strlen( $user_object->GetDBField('Password') ); if ( !$user_object->GetDBField('PwResetConfirm') ) { // no reset made -> allow $allow_reset = true; } else { // reset made -> wait N minutes, then allow $allow_reset = adodb_mktime() > $user_object->GetDBField('PwRequestTime') + $min_pwd_reset_delay; } } if ($found && $allow_reset) { $this->Application->EmailEventUser('USER.PSWDC', $user_object->GetID()); $event->redirect = $this->Application->GetVar('template_success'); return ; } if ( !strlen($username) && !strlen($email) ) { $user_current_object->SetError('Login', 'forgotpw_nodata', 'lu_ferror_forgotpw_nodata'); $user_current_object->SetError('Email', 'forgotpw_nodata', 'lu_ferror_forgotpw_nodata'); } elseif ( !$found ) { if ( strlen($username) ) { $user_current_object->SetError('Login', 'unknown_username', 'lu_ferror_unknown_username'); } if ( strlen($email) ) { $user_current_object->SetError('Email', 'unknown_email', 'lu_ferror_unknown_email'); } } elseif ( !$allow_reset ) { if ( strlen($username) ) { $user_current_object->SetError('Login', 'reset_denied', 'lu_ferror_reset_denied'); } if ( strlen($email) ) { $user_current_object->SetError('Email', 'reset_denied', 'lu_ferror_reset_denied'); } } if ( $user_current_object->HasErrors() ) { $event->redirect = false; } } function OnUpdate(&$event) { parent::OnUpdate($event); $this->setNextTemplate($event); } /** * Checks state against country * * @param kEvent $event */ function OnBeforeItemUpdate(&$event) { parent::OnBeforeItemUpdate($event); $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ $cs_helper->CheckStateField($event, 'State', 'Country'); $cs_helper->PopulateStates($event, 'State', 'Country'); if ($event->Special == 'forgot') { $object =& $event->getObject(); /* @var $object kDBItem */ $object->SetDBField('PwResetConfirm', ''); $object->SetDBField('PwRequestTime_date', NULL); $object->SetDBField('PwRequestTime_time', NULL); } } /** * Enter description here... * * @param kEvent $event */ function setNextTemplate(&$event) { if ($this->Application->isAdmin) { return ; } $event->SetRedirectParam('opener', 's'); $object =& $event->getObject(); if ($object->GetDBField('Status') == STATUS_ACTIVE) { $next_template = $this->Application->GetVar('next_template'); if ($next_template) { $event->redirect = $next_template; } } } /** * Delete users from groups if their membership is expired * * @param kEvent $event */ function OnCheckExpiredMembership(&$event) { // send pre-expiration reminders: begin $pre_expiration = adodb_mktime() + $this->Application->ConfigValue('User_MembershipExpirationReminder') * 3600 * 24; $sql = 'SELECT PortalUserId, GroupId FROM '.TABLE_PREFIX.'UserGroup WHERE (MembershipExpires IS NOT NULL) AND (ExpirationReminderSent = 0) AND (MembershipExpires < '.$pre_expiration.')'; $skip_clause = $event->getEventParam('skip_clause'); if ($skip_clause) { $sql .= ' AND !('.implode(') AND !(', $skip_clause).')'; } $records = $this->Conn->Query($sql); if ($records) { $conditions = Array(); foreach ($records as $record) { $email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRATION.NOTICE', $record['PortalUserId']); $email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRATION.NOTICE'); $conditions[] = '(PortalUserId = '.$record['PortalUserId'].' AND GroupId = '.$record['GroupId'].')'; } $sql = 'UPDATE '.TABLE_PREFIX.'UserGroup SET ExpirationReminderSent = 1 WHERE '.implode(' OR ', $conditions); $this->Conn->Query($sql); } // send pre-expiration reminders: end // remove users from groups with expired membership: begin $sql = 'SELECT PortalUserId FROM '.TABLE_PREFIX.'UserGroup WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')'; $user_ids = $this->Conn->GetCol($sql); if ($user_ids) { foreach ($user_ids as $id) { $email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRED', $id); $email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRED'); } } $sql = 'DELETE FROM '.TABLE_PREFIX.'UserGroup WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')'; $this->Conn->Query($sql); // remove users from groups with expired membership: end } /** * Enter description here... * * @param kEvent $event */ function OnRefreshForm(&$event) { $event->redirect = false; $item_info = $this->Application->GetVar($event->getPrefixSpecial()); list($id, $fields) = each($item_info); $object =& $event->getObject( Array('skip_autoload' => true) ); $object->setID($id); $object->IgnoreValidation = true; $object->SetFieldsFromHash($fields); } /** * Sets persistant variable * * @param kEvent $event */ function OnSetPersistantVariable(&$event) { $field = $this->Application->GetVar('field'); $value = $this->Application->GetVar('value'); $this->Application->StorePersistentVar($field, $value); $force_tab = $this->Application->GetVar('SetTab'); if ($force_tab) { $this->Application->StoreVar('force_tab', $force_tab); } } /** * Overwritten to return user from order by special .ord * * @param kEvent $event */ function getPassedID(&$event) { switch ($event->Special) { case 'ord': $order =& $this->Application->recallObject('ord'); /* @var $order OrdersItem */ return $order->GetDBField('PortalUserId'); break; case 'profile': $id = $this->Application->GetVar('user_id'); if (!$id) { // if none user_id given use current user id $id = $this->Application->RecallVar('user_id'); } return $id; break; case 'forgot': $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $id = $user_helper->validateUserCode( $this->Application->GetVar('user_key'), 'forgot_password' ); if ( is_numeric($id) ) { return $id; } break; } return parent::getPassedID($event); } /** * Allows to change root password * * @param kEvent $event */ function OnUpdateRootPassword(&$event) { return $this->OnUpdatePassword($event); } /** * Allows to change root password * * @param kEvent $event */ function OnUpdatePassword(&$event) { $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if (!$items_info) return ; list ($id, $field_values) = each($items_info); $user_id = $this->Application->RecallVar('user_id'); if ($id == $user_id && ($user_id > 0 || $user_id == USER_ROOT)) { $user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true)); /* @var $user_dummy kDBItem */ $user_dummy->Load($id); $status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField')); if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) { // not active user is not allowed to update his record (he could not activate himself manually) return false; } } if ($user_id == USER_ROOT) { $object =& $event->getObject( Array('skip_autoload' => true) ); /* @var $object UsersItem */ // put salt to user's config $field_options = $object->GetFieldOptions('RootPassword'); $field_options['salt'] = 'b38'; // this is internal hack to allow root/root passwords for dev if ($this->Application->isDebugMode() && $field_values['RootPassword'] == 'root') { $field_options['min_length'] = 4; } $object->SetFieldOptions('RootPassword', $field_options); $verify_options = $object->GetFieldOptions('VerifyRootPassword'); $verify_options['salt'] = 'b38'; $object->SetFieldOptions('VerifyRootPassword', $verify_options); $this->RemoveRequiredFields($object); $object->SetDBField('RootPassword', $this->Application->ConfigValue('RootPass')); $object->SetFieldsFromHash($field_values); $object->setID(-1); $status = $object->Validate(); if ($status) { // validation on, password match too $fields_hash = Array ( 'VariableValue' => $object->GetDBField('RootPassword') ); $conf_table = $this->Application->getUnitOption('conf', 'TableName'); $this->Conn->doUpdate($fields_hash, $conf_table, 'VariableName = "RootPass"'); $event->SetRedirectParam('opener', 'u'); } else { $event->status = kEvent::erFAIL; $event->redirect = false; return; } } else { $object =& $event->getObject(); $object->SetFieldsFromHash($field_values); if (!$object->Update()) { $event->status = kEvent::erFAIL; $event->redirect = false; } } $event->SetRedirectParam('opener', 'u'); $event->redirect == true; } /** * Apply custom processing to item * * @param kEvent $event */ function customProcessing(&$event, $type) { if ($event->Name == 'OnCreate' && $type == 'before') { $object =& $event->getObject(); /* @var $object kDBItem */ // if auto password has not been set already - store real one - to be used in email events if (!$this->Application->GetVar('user_password')) { $this->Application->SetVar('user_password', $object->GetDirtyField('Password')); $object->SetDBField('Password_plain', $object->GetDirtyField('Password')); } // validate here, because subscribing procedure should not validate captcha code if ($this->Application->ConfigValue('RegistrationCaptcha')) { $captcha_helper =& $this->Application->recallObject('CaptchaHelper'); /* @var $captcha_helper kCaptchaHelper */ $captcha_helper->validateCode($event, false); } } } function OnMassResetSettings(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { $event->status = kEvent::erFAIL; return; } $ids = $this->StoreSelectedIDs($event); $default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId'); if (in_array($default_user_id, $ids)) { array_splice($ids, array_search($default_user_id, $ids), 1); } if ($ids) { $q = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData WHERE PortalUserId IN ('.join(',', $ids).') AND (VariableName LIKE "%_columns_%" OR VariableName LIKE "%_filter%" OR VariableName LIKE "%_PerPage%")'; $this->Conn->Query($q); } $this->clearSelectedIDs($event); } /** * Checks, that currently loaded item is allowed for viewing (non permission-based) * * @param kEvent $event * @return bool */ function checkItemStatus(&$event) { $object =& $event->getObject(); if (!$object->isLoaded()) { return true; } $virtual_users = Array (USER_ROOT, USER_GUEST); return ($object->GetDBField('Status') == STATUS_ACTIVE) || in_array($object->GetID(), $virtual_users); } /** * Sends approved/declined email event on user status change * * @param kEvent $event */ function OnAfterItemUpdate(&$event) { $this->afterItemChanged($event); $object =& $event->getObject(); /* @var $object UsersItem */ if (!$this->Application->isAdmin || $object->IsTempTable()) { return ; } $this->sendStatusChangeEvent($object->GetID(), $object->GetOriginalField('Status'), $object->GetDBField('Status')); } /** * Occurs, after item is changed * * @param kEvent $event */ function afterItemChanged(&$event) { $this->saveUserImages($event); $object =& $event->getObject(); /* @var $object kDBItem */ if ( $object->GetDBField('EmailPassword') && $object->GetDBField('Password_plain') ) { $email_passwords = $this->Application->RecallVar('email_passwords'); $email_passwords = $email_passwords ? unserialize($email_passwords) : Array (); $email_passwords[ $object->GetID() ] = $object->GetDBField('Password_plain'); $this->Application->StoreVar('email_passwords', serialize($email_passwords)); } } /** * Stores user's original Status before overwriting with data from temp table * * @param kEvent $event */ function OnBeforeDeleteFromLive(&$event) { $user_status = $this->Application->GetVar('user_status'); if (!$user_status) { $user_status = Array (); } $user_id = $event->getEventParam('id'); if ($user_id > 0) { $user_status[$user_id] = $this->getUserStatus($user_id); $this->Application->SetVar('user_status', $user_status); } } /** * Sends approved/declined email event on user status change (in temp tables during editing) * * @param kEvent $event */ function OnAfterCopyToLive(&$event) { $temp_id = $event->getEventParam('temp_id'); $email_passwords = $this->Application->RecallVar('email_passwords'); if ( $email_passwords ) { $email_passwords = unserialize($email_passwords); if ( isset($email_passwords[$temp_id]) ) { $object =& $event->getObject(); /* @var $object kDBItem */ $object->SwitchToLive(); $object->Load( $event->getEventParam('id') ); $object->SetField('Password', $email_passwords[$temp_id]); $object->SetField('VerifyPassword', $email_passwords[$temp_id]); $this->Application->EmailEventUser($temp_id > 0 ? 'USER.NEW.PASSWORD': 'USER.ADD.BYADMIN', $object->GetID()); unset($email_passwords[$temp_id]); $this->Application->StoreVar('email_passwords', serialize($email_passwords)); } } if ( $temp_id > 0 ) { // only send status change e-mail on user update $new_status = $this->getUserStatus($temp_id); $user_status = $this->Application->GetVar('user_status'); $this->sendStatusChangeEvent($temp_id, $user_status[$temp_id], $new_status); } } /** * Returns user status (active, pending, disabled) based on ID and temp mode setting * * @param int $user_id * @return int */ function getUserStatus($user_id) { $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); $sql = 'SELECT Status FROM '.$table_name.' WHERE '.$id_field.' = '.$user_id; return $this->Conn->GetOne($sql); } /** * Sends approved/declined email event on user status change * * @param int $user_id * @param int $prev_status * @param int $new_status */ function sendStatusChangeEvent($user_id, $prev_status, $new_status) { $status_events = Array ( STATUS_ACTIVE => 'USER.APPROVE', STATUS_DISABLED => 'USER.DENY', ); $email_event = isset($status_events[$new_status]) ? $status_events[$new_status] : false; if (($prev_status != $new_status) && $email_event) { $this->Application->EmailEventUser($email_event, $user_id); $this->Application->EmailEventAdmin($email_event); } // deletes sessions from users, that are no longer active if (($prev_status != $new_status) && ($new_status != STATUS_ACTIVE)) { $sql = 'SELECT SessionKey FROM ' . TABLE_PREFIX . 'UserSession WHERE PortalUserId = ' . $user_id; $session_ids = $this->Conn->GetCol($sql); $this->Application->Session->DeleteSessions($session_ids); } } /** * OnAfterConfigRead for users * * @param kEvent $event */ function OnAfterConfigRead(&$event) { parent::OnAfterConfigRead($event); $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); // 1. arrange user registration countries $site_helper =& $this->Application->recallObject('SiteHelper'); /* @var $site_helper SiteHelper */ $first_country = $site_helper->getDefaultCountry('', false); if ($first_country === false) { $first_country = $this->Application->ConfigValue('User_Default_Registration_Country'); } if ($first_country) { // update user country dropdown sql $fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (CountryStateId = '.$first_country.', 1, 0) DESC, \\1', $fields['Country']['options_sql']); } // 2. set default user registration group $fields['PrimaryGroupId']['default'] = $this->Application->ConfigValue('User_NewGroup'); // 3. allow avatar upload on Front-End $file_helper =& $this->Application->recallObject('FileHelper'); /* @var $file_helper FileHelper */ $file_helper->createItemFiles($event->Prefix, true); // create image fields if ($this->Application->isAdminUser) { // 4. when in administrative console, then create all users with Active status $fields['Status']['default'] = STATUS_ACTIVE; // 5. remove groups tab on editing forms when AdvancedUserManagement config variable not set if (!$this->Application->ConfigValue('AdvancedUserManagement')) { $edit_tab_presets = $this->Application->getUnitOption($event->Prefix, 'EditTabPresets'); foreach ($edit_tab_presets as $preset_name => $preset_tabs) { if (array_key_exists('groups', $preset_tabs)) { unset($edit_tab_presets[$preset_name]['groups']); if (count($edit_tab_presets[$preset_name]) == 1) { // only 1 tab left -> remove it too $edit_tab_presets[$preset_name] = Array (); } } } $this->Application->setUnitOption($event->Prefix, 'EditTabPresets', $edit_tab_presets); } } if ( !$this->Application->ConfigValue('Email_As_Login') ) { // Login becomes required only, when it's used in registration process $fields['Login']['required'] = 1; } $this->Application->setUnitOption($event->Prefix, 'Fields', $fields); } /** * OnMassCloneUsers * * @param kEvent $event */ function OnMassCloneUsers(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { $event->status = kEvent::erFAIL; return; } $temp_handler =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler'); /* @var $temp_handler kTempTablesHandler */ $ids = $this->StoreSelectedIDs($event); $temp_handler->CloneItems($event->Prefix, '', $ids); $this->clearSelectedIDs($event); } /** * When cloning users, reset password (set random) * * @param kEvent $event */ function OnBeforeClone(&$event) { $object =& $event->getObject(); /* @var $object UsersItem */ $object->generatePassword(); $object->SetDBField('ResourceId', 0); // this will reset it // change email because it should be unique $object->NameCopy(Array (), $object->GetID(), 'Email', 'copy%1$s.%2$s'); } /** * Saves selected ids to session * * @param kEvent $event */ function OnSaveSelected(&$event) { $this->StoreSelectedIDs($event); // remove current ID, otherwise group selector will use it in filters $this->Application->DeleteVar($event->getPrefixSpecial(true) . '_id'); } /** * Sets primary group of selected users * * @param kEvent $event */ function OnProcessSelected(&$event) { $event->SetRedirectParam('opener', 'u'); $user_ids = $this->getSelectedIDs($event, true); $this->clearSelectedIDs($event); $dst_field = $this->Application->RecallVar('dst_field'); if ($dst_field != 'PrimaryGroupId') { return ; } $group_ids = $this->Application->GetVar('g'); $primary_group_id = $group_ids ? array_shift( array_keys($group_ids) ) : false; if (!$user_ids || !$primary_group_id) { return ; } $table_name = $this->Application->getUnitOption('ug', 'TableName'); // 1. mark group as primary $sql = 'UPDATE ' . TABLE_PREFIX . 'PortalUser SET PrimaryGroupId = ' . $primary_group_id . ' WHERE PortalUserId IN (' . implode(',', $user_ids) . ')'; $this->Conn->Query($sql); $sql = 'SELECT PortalUserId FROM ' . $table_name . ' WHERE (GroupId = ' . $primary_group_id . ') AND (PortalUserId IN (' . implode(',', $user_ids) . '))'; $existing_members = $this->Conn->GetCol($sql); // 2. add new members to a group $new_members = array_diff($user_ids, $existing_members); foreach ($new_members as $user_id) { $fields_hash = Array ( 'GroupId' => $primary_group_id, 'PortalUserId' => $user_id, ); $this->Conn->doInsert($fields_hash, $table_name); } } /** * Loads user images * * @param kEvent $event */ function OnAfterItemLoad(&$event) { parent::OnAfterItemLoad($event); // linking existing images for item with virtual fields $image_helper =& $this->Application->recallObject('ImageHelper'); /* @var $image_helper ImageHelper */ $object =& $event->getObject(); /* @var $object kDBItem */ $image_helper->LoadItemImages($object); $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ $cs_helper->PopulateStates($event, 'State', 'Country'); } /** * Save user images * * @param kEvent $event */ function saveUserImages(&$event) { if (!$this->Application->isAdmin) { $image_helper =& $this->Application->recallObject('ImageHelper'); /* @var $image_helper ImageHelper */ $object =& $event->getObject(); /* @var $object kDBItem */ // process image upload in virtual fields $image_helper->SaveItemImages($object); } } /** * Makes password required for new users * * @param kEvent $event */ function OnPreCreate(&$event) { parent::OnPreCreate($event); if ($event->status != kEvent::erSUCCESS) { return ; } $object =& $event->getObject(); /* @var $object kDBItem */ $user_type = $this->Application->GetVar('user_type'); if ($user_type) { $object->SetDBField('UserType', $user_type); if ( $user_type == UserType::ADMIN ) { $object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_AdminGroup')); } } if ( $this->Application->ConfigValue('User_Password_Auto') ) { $object->SetDBField('EmailPassword', 1); } $this->_makePasswordRequired($event); } /** * Makes password required for new users * * @param kEvent $event */ function OnNew(&$event) { parent::OnNew($event); if ($event->status == kEvent::erSUCCESS) { $this->_makePasswordRequired($event); } } /** * Makes password required for new users * * @param kEvent $event */ function _makePasswordRequired(&$event) { $object =& $event->getObject(); /* @var $object kDBItem */ $required_fields = Array ('Password', 'Password_plain', 'VerifyPassword', 'VerifyPassword_plain'); foreach ($required_fields as $required_field) { $object->setRequired($required_field); } } /** * Load item if id is available * * @param kEvent $event */ function LoadItem(&$event) { $id = $this->getPassedID($event); if ($id < 0) { // when root, guest and so on $object =& $event->getObject(); /* @var $object kDBItem */ $object->Clear($id); return ; } parent::LoadItem($event); } /** * Generates password * * @param kEvent $event */ function OnGeneratePassword(&$event) { $event->status = kEvent::erSTOP; if ( $this->Application->isAdminUser ) { echo kUtil::generatePassword(); } } /** * Changes user's password and logges him in * * @param kEvent $event */ function OnResetLostPassword(&$event) { $object =& $event->getObject(); /* @var $object kDBItem */ $event->CallSubEvent('OnUpdate'); if ( $event->status == kEvent::erSUCCESS ) { $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $user =& $user_helper->getUserObject(); $user->Load( $object->GetID() ); if ( $user_helper->checkLoginPermission() ) { $user_helper->loginUserById( $user->GetID() ); } } } }