protected function __trigger() { self::__init(); $db = ASDCLoader::instance(); $success = false; $Members = $this->_Parent->ExtensionManager->create('members'); $Members->initialiseCookie(); if ($Members->isLoggedIn() !== true) { redirect(URL . '/forbidden/'); } $Members->initialiseMemberObject(); // Make sure we dont accidently use an expired token extension_Members::purgeCodes(); $activation_row = $db->query(sprintf("SELECT * FROM `tbl_members_codes` WHERE `token` = '%s' AND `member_id` = %d LIMIT 1", $db->escape($_POST['fields']['code']), (int) $Members->Member->get('id')))->current(); // No code, you are a spy! if ($activation_row === false) { redirect(URL . '/members/activate/failed/'); } // Got this far, all is well. $db->query(sprintf("UPDATE `tbl_entries_data_%d` SET `role_id` = %d WHERE `entry_id` = %d LIMIT 1", $Members->roleField(), 3, (int) $Members->Member->get('id'))); extension_Members::purgeTokens((int) $Members->Member->get('id')); $em = new EntryManager($this->_Parent); $entry = end($em->fetch((int) $Members->Member->get('id'))); $email = $entry->getData(self::findFieldID('email-address', 'members')); $name = $entry->getData(self::findFieldID('name', 'members')); $Members->emailNewMember(array('section' => $Members->memberSectionHandle(), 'entry' => $entry, 'fields' => array('username-and-password' => $entry->getData(self::findFieldID('username-and-password', 'members')), 'name' => $name['value'], 'email-address' => $email['value']))); redirect(URL . '/members/activate/success/'); }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $success = false; self::__init(); $db = ASDCLoader::instance(); $Members = $this->_Parent->ExtensionManager->create('members'); $Members->initialiseCookie(); if ($Members->isLoggedIn() !== true) { $result->appendChild(new XMLElement('error', 'Must be logged in.')); $result->setAttribute('status', 'error'); return $result; } $Members->initialiseMemberObject(); // Make sure we dont accidently use an expired code extension_Members::purgeCodes(); $em = new EntryManager($this->_Parent); $entry = end($em->fetch((int) $Members->Member->get('id'))); $email = $entry->getData(self::findFieldID('email-address', 'members')); $name = $entry->getData(self::findFieldID('name', 'members')); $success = $Members->emailNewMember(array('entry' => $entry, 'fields' => array('username-and-password' => $entry->getData(self::findFieldID('username-and-password', 'members')), 'name' => $name['value'], 'email-address' => $email['value']))); if ($success == true && isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', $success === true ? 'success' : 'error'); return $result; }
protected function addEmailTemplates($template) { // Read the template from the Configuration if it exists // This is required for the Email Template Filter/Email Template Manager if (!is_null(extension_Members::getSetting($template))) { $this->eParamFILTERS = array_merge($this->eParamFILTERS, explode(',', extension_Members::getSetting($template))); } }
protected function __trigger() { $role_field_handle = ASDCLoader::instance()->query(sprintf("SELECT `element_name` FROM `tbl_fields` WHERE `type` = 'memberrole' AND `parent_section` = %d LIMIT 1", extension_Members::memberSectionID()))->current()->element_name; $role_id = Symphony::Configuration()->get('new_member_default_role', 'members'); if (Symphony::Configuration()->get('require_activation', 'members') == 'yes') { $role_id = extension_Members::INACTIVE_ROLE_ID; } $_POST['fields'][$role_field_handle] = $role_id; include TOOLKIT . '/events/event.section.php'; return $result; }
/** * Where `$name` is one of the following values, `role`, `timezone`, * `email`, `activation`, `authentication` and `identity`, this function * will return the Field's `element_name`. `element_name` is a handle * of the Field's label, used most commonly by events in `$_POST` data. * If no `$name` is given, an array of all Member field handles will * be returned. * * @param string $type * @return string */ public function getFieldHandle($type = null) { if (is_null($type)) { return null; } $type = extension_Members::getFieldType($type); // Check to see if this name has been stored in our 'static' cache // If it hasn't, lets go find it (for better or worse) if (!isset($this->handles[$type])) { $this->initialiseField($type, $this->section_id); } // No field, return null if (!isset($this->handles[$type])) { return null; } // Return the handle return $this->handles[$type]; }
protected function __trigger() { self::__init(); $db = ASDCLoader::instance(); $success = false; $Members = $this->_Parent->ExtensionManager->create('members'); $Members->initialiseCookie(); if ($Members->isLoggedIn() !== true) { redirect(URL . '/forbidden/'); } $Members->initialiseMemberObject(); // Make sure we dont accidently use an expired token extension_Members::purgeCodes(); $em = new EntryManager($this->_Parent); $entry = end($em->fetch((int) $Members->Member->get('id'))); $email = $entry->getData(self::findFieldID('email-address', 'members')); $name = $entry->getData(self::findFieldID('name', 'members')); $Members->emailNewMember(array('section' => $Members->memberSectionHandle(), 'entry' => $entry, 'fields' => array('username-and-password' => $entry->getData(self::findFieldID('username-and-password', 'members')), 'name' => $name['value'], 'email-address' => $email['value']))); redirect(URL . '/members/activate/sent/'); }
public static function documentation() { // Fetch all the Email Templates available and add to the end of the documentation $templates = extension_Members::fetchEmailTemplates(); $div = new XMLElement('div'); if (!empty($templates)) { $label = new XMLElement('label', __('Generate Recovery Code Email Template')); $generate_recovery_code_templates = extension_Members::setActiveTemplate($templates, 'generate-recovery-code-template'); $label->appendChild(Widget::Select('members[generate-recovery-code-template][]', $generate_recovery_code_templates, array('multiple' => 'multiple'))); $div->appendChild($label); $div->appendChild(Widget::Input('members[event]', 'generate-recovery-code', 'hidden')); $div->appendChild(Widget::Input('action[save]', __('Save Changes'), 'submit', array('accesskey' => 's'))); } return ' <p>This event takes a member\'s email address or username to validate the existence of the Member before generating a recovery code for that member. A member\'s password is not completely reset until their recovery code is used in the Members: Reset Password event. This recovery code can be seen by including the Member: Password field in a data source on the same page as this event, or by using the event\'s result.</p> <h3>Example Front-end Form Markup</h3> <p>This is an example of the markup you can use on your front end to create a form for this event. An input field accepts either the member\'s email address or username.</p> <pre class="XML"><code> <form method="post"> <label>Username: <input name="fields[username]" type="text" value="{$username}"/></label> or <label>Email: <input name="fields[email]" type="text" value="{$email}"/></label> <input type="hidden" name="members-section-id" value="{$your-section-id}"/> <input type="submit" name="action[' . self::ROOTELEMENT . ']" value="Reset Password"/> <input type="hidden" name="redirect" value="{$root}/"/> </form> </code></pre> <h3>More Information</h3> <p>For further information about this event, including response and error XML, please refer to the <a href="https://github.com/symphonycms/members/wiki/Members%3A-Generate-Recovery-Code">wiki</a>.</p> ' . $div->generate() . ' '; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); self::__init(); $db = ASDCLoader::instance(); $success = false; $Members = Frontend::instance()->ExtensionManager->create('members'); $Members->initialiseCookie(); if ($Members->isLoggedIn() !== true) { $result->appendChild(new XMLElement('error', 'Must be logged in.')); $result->setAttribute('status', 'error'); return $result; } $Members->initialiseMemberObject(); // Make sure we dont accidently use an expired code extension_Members::purgeCodes(); $activation_row = $db->query(sprintf("SELECT * FROM `tbl_members_codes` WHERE `code` = '%s' AND `member_id` = %d LIMIT 1", $db->escape($_POST['fields']['code']), (int) $Members->Member->get('id')))->current(); // No code, you are a spy! if ($activation_row === false) { $success = false; $result->appendChild(new XMLElement('error', 'Activation failed. Code was invalid.')); } else { // Got this far, all is well. $db->query(sprintf("UPDATE `tbl_entries_data_%d` SET `role_id` = %d WHERE `entry_id` = %d LIMIT 1", $Members->roleField(), Symphony::Configuration()->get('new_member_default_role', 'members'), (int) $Members->Member->get('id'))); extension_Members::purgeCodes((int) $Members->Member->get('id')); $em = new EntryManager($this->_Parent); $entry = end($em->fetch((int) $Members->Member->get('id'))); $email = $entry->getData(self::findFieldID('email-address', 'members')); $name = $entry->getData(self::findFieldID('name', 'members')); $Members->emailNewMember(array('section' => $Members->memberSectionHandle(), 'entry' => $entry, 'fields' => array('username-and-password' => $entry->getData(self::findFieldID('username-and-password', 'members')), 'name' => $name['value'], 'email-address' => $email['value']))); $success = true; } if ($success == true && isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('status', $success === true ? 'success' : 'error'); return $result; }
public function __viewIndex() { // Add in custom assets Administration::instance()->Page->addStylesheetToHead(URL . '/extensions/sections_event/assets/sections_event.permissions_index.css', 'screen', 111); $this->setPageType('table'); $this->setTitle(__('%1$s – %2$s', array(__('Symphony'), __('Section permissions')))); $this->appendSubheading(__('Section permissions')); // check if roles exist $roles = RoleManager::fetch(); if (!is_array($roles) || empty($roles)) { return $this->Form->appendChild($this->buildErrorMessage(__('No roles found. <a href="%s">Add a new one?</a>', array(extension_Members::baseURL() . 'roles/new/')))); } // build table $aTableHead = array(array(__('Member role'), 'col')); $aTableBody = array(); foreach ($roles as $role) { // Setup each cell $td1 = Widget::TableData(Widget::Anchor($role->get('name'), Administration::instance()->getCurrentPageURL() . 'edit/' . $role->get('id') . '/', null, 'content')); // Add cells to a row $aTableBody[] = Widget::TableRow(array($td1)); } $table = Widget::Table(Widget::TableHead($aTableHead), null, Widget::TableBody($aTableBody)); $this->Form->appendChild($table); }
public static function documentation() { // Fetch all the Email Templates available and add to the end of the documentation $templates = extension_Members::fetchEmailTemplates(); $div = new XMLElement('div'); if (!empty($templates)) { $label = new XMLElement('label', __('Regenerate Activation Code Email Template')); $regenerate_activation_code_templates = extension_Members::setActiveTemplate($templates, 'regenerate-activation-code-template'); $label->appendChild(Widget::Select('members[regenerate-activation-code-template][]', $regenerate_activation_code_templates, array('multiple' => 'multiple'))); $div->appendChild($label); $div->appendChild(Widget::Input('members[event]', 'reset-password', 'hidden')); $div->appendChild(Widget::Input('action[save]', __('Save Changes'), 'submit', array('accesskey' => 's'))); } return ' <p>This event will regenerate an activation code for a user if their current activation code has expired. The activation code can be sent to a Member\'s email after this event has executed.</p> <h3>Example Front-end Form Markup</h3> <p>This is an example of the form markup you can use on your front end. An input field accepts either the member\'s email address or username.</p> <pre class="XML"><code> <form method="post"> <label>Username: <input name="fields[username]" type="text" value="{$username}"/></label> or <label>Email: <input name="fields[email]" type="text" value="{$email}"/></label> <input type="hidden" name="members-section-id" value="{$your-section-id}"/> <input type="submit" name="action[' . self::ROOTELEMENT . ']" value="Regenerate Activation Code"/> <input type="hidden" name="redirect" value="{$root}/"/> </form> </code></pre> <h3>More Information</h3> <p>For further information about this event, including response and error XML, please refer to the <a href="https://github.com/symphonycms/members/wiki/Members%3A-Regenerate-Activation-Code">wiki</a>.</p> ' . $div->generate() . ' '; }
public function appendMemberRolePermissionFieldsets($context) { $fieldset = new XMLElement('fieldset'); $fieldset->setAttribute('class', 'settings type-file'); $fieldset->appendChild(new XMLElement('legend', 'Forum Permissions')); $aTableHead = array(array('Action', 'col'), array('Allowed', 'col')); $permissions = $context['permissions']['forum']; $group = new XMLElement('div', NULL, array('class' => 'group')); /** FIRST TABLE **/ $aTableBody = extension_Members::buildRolePermissionTableBody(array(array('Start New Discussion', 'forum', 'start_discussion', isset($permissions['start_discussion'])), array('Edit Discussions', 'forum', 'edit_discussion', isset($permissions['edit_discussion'])), array('Edit Own Discussions*', 'forum', 'edit_own_discussion', isset($permissions['edit_own_discussion'])), array('Remove Discussions', 'forum', 'remove_discussion', isset($permissions['remove_discussion'])), array('Remove Own Discussions*', 'forum', 'remove_own_discussion', isset($permissions['remove_own_discussion'])))); $table = Widget::Table(Widget::TableHead($aTableHead), NULL, Widget::TableBody($aTableBody), 'role-permissions narrow'); $group->appendChild($table); /** SECOND TABLE **/ $aTableBody = extension_Members::buildRolePermissionTableBody(array(array('Add Comment', 'forum', 'add_comment', isset($permissions['add_comment'])), array('Edit Comment', 'forum', 'edit_comment', isset($permissions['edit_comment'])), array('Edit Own Comment*', 'forum', 'edit_own_comment', isset($permissions['edit_own_comment'])), array('Remove Comment', 'forum', 'remove_comment', isset($permissions['remove_comment'])), array('Remove Own Comment*', 'forum', 'remove_own_comment', isset($permissions['remove_own_comment'])))); $table = Widget::Table(Widget::TableHead($aTableHead), NULL, Widget::TableBody($aTableBody), 'role-permissions narrow'); $group->appendChild($table); /** THIRD TABLE **/ $aTableBody = extension_Members::buildRolePermissionTableBody(array(array('Pin/Unpin Discussion', 'forum', 'pin_discussion', isset($permissions['pin_discussion'])), array('Open/Close Discussion', 'forum', 'close_discussion', isset($permissions['close_discussion'])))); $table = Widget::Table(Widget::TableHead($aTableHead), NULL, Widget::TableBody($aTableBody), 'role-permissions narrow'); $group->appendChild($table); $fieldset->appendChild($group); $fieldset->appendChild(new XMLElement('p', '* <em>Does not apply if global edit/remove is allowed</em>', array('class' => 'help'))); $context['form']->appendChild($fieldset); }
private function __triggerCode() { $result = new XMLElement(self::ROOTELEMENT, NULL, array('step' => '2')); $success = false; $Members = $this->_Parent->ExtensionManager->create('members'); $code = $_POST['fields']['code']; self::__init(); $db = ASDCLoader::instance(); // Make sure we dont accidently use an expired code extension_Members::purgeCodes(); $code_row = $db->query(sprintf("SELECT * FROM `tbl_members_codes` WHERE `code` = '%s' LIMIT 1", $db->escape($code)))->current(); // No code, you are a spy! if ($code_row !== false) { extension_Members::purgeCodes($code_row->member_id); $success = $Members->sendNewPasswordEmail($code_row->member_id); } $result->setAttribute('result', $success === true ? 'success' : 'error'); if ($success == false) { $result->appendChild(new XMLElement('error', 'Sending email containing new password failed.')); } elseif ($success == true && isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } return $result; }
public function addMemberDetailsToPageParams(array $context = null) { if (!$this->isLoggedIn()) { return; } $this->initialiseMemberObject(); $context['params']['member-id'] = $this->getMemberID(); if (!is_null(extension_Members::getFieldHandle('role'))) { $role_data = $this->getMember()->getData(extension_Members::getField('role')->get('id')); $role = RoleManager::fetch($role_data['role_id']); if ($role instanceof Role) { $context['params']['member-role'] = $role->get('name'); } } if (!is_null(extension_Members::getFieldHandle('activation'))) { if ($this->getMember()->getData(extension_Members::getField('activation')->get('id'), true)->activated != "yes") { $context['params']['member-activated'] = 'no'; } } }
/** * This function will ensure that the user who has submitted the form (and * hence is requesting that an event be triggered) is actually allowed to * do this request. * There are 2 action types, creation and editing. Creation is a simple yes/no * affair, whereas editing has three levels of permission, None, Own Entries * or All Entries: * - None: This user can't do process this event * - Own Entries: If the entry the user is trying to update is their own * determined by if the `entry_id` or, in the case of a SBL or * similar field, the `entry_id` of the linked entry matches the logged in * user's id, process the event. * - All Entries: The user can update any entry in Symphony. * If there are no Roles in this system, or the event is set to ignore permissions * (by including a function, `ignoreRolePermissions` that returns `true`, it will * immediately proceed to processing any of the Filters attached to the event * before returning. * * @uses EventPreSaveFilter * * @param array $context * @return null */ public function checkEventPermissions(array &$context) { // If this system has no Roles, or the event is set to ignore role permissions // continue straight to processing the Filters if (!FieldManager::isFieldUsed(extension_Members::getFieldType('role')) || method_exists($context['event'], 'ignoreRolePermissions') && $context['event']->ignoreRolePermissions() == true) { $this->__processEventFilters($context); return null; } // Prior to Symphony 2.2.2, the EventPreSaveFilter delegate doesn't // pass the `$entry_id`. This can cause an issue when an Event has the // `allow_multiple` filter set as we can't determine the correct `$entry_id` // This will check to see if the `$entry_id` is set, otherwise fallback // to the previous logic. This will mean that using `allow_multiple` will // not be compatible without Symphony 2.2.2 and Members 1.1 // @see https://github.com/symphonycms/members/issues/167 if (isset($context['entry_id']) && is_numeric($context['entry_id'])) { $entry_id = (int) $context['entry_id']; $action = 'edit'; } else { if (isset($_POST['id']) && !empty($_POST['id'])) { $entry_id = (int) $_POST['id']; $action = 'edit'; } else { $action = 'create'; $entry_id = 0; } } $required_level = $action == 'create' ? EventPermissions::CREATE : EventPermissions::ALL_ENTRIES; $role_id = Role::PUBLIC_ROLE; $isLoggedIn = $this->getMemberDriver()->isLoggedIn(); if ($isLoggedIn && $this->getMemberDriver()->initialiseMemberObject()) { if ($this->getMemberDriver()->getMember() instanceof Entry) { $required_level = EventPermissions::OWN_ENTRIES; $role_data = $this->getMemberDriver()->getMember()->getData(extension_Members::getField('role')->get('id')); $role_id = $role_data['role_id']; if ($action == 'edit' && method_exists($context['event'], 'getSource')) { $section_id = $context['event']->getSource(); $isOwner = false; // If the event is the same section as the Members section, then for `$isOwner` // to be true, the `$entry_id` must match the currently logged in user. if ($section_id == $this->getMemberDriver()->getMember()->get('section_id')) { // Check the logged in member is the same as the `entry_id` that is about to // be updated. If so the user is the Owner and can modify EventPermissions::OWN_ENTRIES $isOwner = $this->getMemberDriver()->getMemberID() == $entry_id; } else { $field_ids = array(); // Get the ID's of the fields that may be used for Linking (Username/Email) if (!is_null(extension_Members::getFieldHandle('identity'))) { $field_ids[] = extension_Members::getField('identity')->get('id'); } if (!is_null(extension_Members::getFieldHandle('email'))) { $field_ids[] = extension_Members::getField('email')->get('id'); } // Query for the `field_id` of any linking fields that link to the members // section AND to one of the linking fields (Username/Email) $fields = Symphony::Database()->fetchCol('child_section_field_id', sprintf("\n\t\t\t\t\t\t\t\t\tSELECT `child_section_field_id`\n\t\t\t\t\t\t\t\t\tFROM `tbl_sections_association`\n\t\t\t\t\t\t\t\t\tWHERE `parent_section_id` = %d\n\t\t\t\t\t\t\t\t\tAND `child_section_id` = %d\n\t\t\t\t\t\t\t\t\tAND `parent_section_field_id` IN ('%s')\n\t\t\t\t\t\t\t\t", $this->getMemberDriver()->getMember()->get('section_id'), $section_id, implode("','", $field_ids))); // If there was a link found, get the `relation_id`, which is the `member_id` of // an entry in the active Members section. if (!empty($fields)) { foreach ($fields as $field_id) { if ($isOwner === true) { break; } $field = FieldManager::fetch($field_id); if ($field instanceof Field) { // So we are trying to find all entries that have selected the Member entry // to determine ownership. This check will use the `fetchAssociatedEntryIDs` // function, which typically works backwards, by accepting the `entry_id` (in // this case, our logged in Member ID). This will return an array of all the // linked entries, so we then just check that the current entry that is going to // be updated is in that array $member_id = $field->fetchAssociatedEntryIDs($this->getMemberDriver()->getMemberID()); $isOwner = in_array($entry_id, $member_id); } } } } // User is not the owner, so they can edit EventPermissions::ALL_ENTRIES if ($isOwner === false) { $required_level = EventPermissions::ALL_ENTRIES; } } } } $role = RoleManager::fetch($role_id); $event_handle = strtolower(preg_replace('/^event/i', NULL, get_class($context['event']))); $success = false; if ($role) { $success = $role->canProcessEvent($event_handle, $action, $required_level) ? true : false; } $context['messages'][] = array('permission', $success, $success === false ? __('You are not authorised to perform this action.') : null); // Process the Filters for this event. $this->__processEventFilters($context); }
/** * Will delete the Role given a `$role_id`. Should `$purge_members` * be passed, this function will remove all Members associated with * this role as well * * @param integer $role_id * @param boolean $purge_members * @return boolean */ public static function delete($role_id, $purge_members = false) { Symphony::Database()->delete("`tbl_members_roles_forbidden_pages`", " `role_id` = " . $role_id); Symphony::Database()->delete("`tbl_members_roles_event_permissions`", " `role_id` = " . $role_id); Symphony::Database()->delete("`tbl_members_roles`", " `id` = " . $role_id); $role_fields = FieldManager::fetch(null, null, 'ASC', 'sortorder', extension_Members::getFieldType('role')); if ($purge_members) { $members = array(); foreach ($role_fields as $role_field) { $members_of_role = Symphony::Database()->fetchCol('entry_id', sprintf("SELECT `entry_id` FROM `tbl_entries_data_%d` WHERE `role_id` = %d", $role_field->get('id'), $role_id)); $members = array_merge($members, $members_of_role); } /** * Prior to deletion of entries. An array of Entry ID's is provided which * can be manipulated. This delegate was renamed from `Delete` to `EntryPreDelete` * in Symphony 2.3. * * @delegate EntryPreDelete * @param string $context * '/publish/' * @param array $entry_id * An array of Entry ID's passed by reference */ Symphony::ExtensionManager()->notifyMembers('EntryPreDelete', '/publish/', array('entry_id' => &$members)); EntryManager::delete($members); /** * After the deletion of entries, this delegate provides an array of Entry ID's * that were deleted. * * @since Symphony 2.3 * @delegate EntryPostDelete * @param string $context * '/publish/' * @param array $entry_id * An array of Entry ID's that were deleted. */ Symphony::ExtensionManager()->notifyMembers('EntryPostDelete', '/publish/', array('entry_id' => $members)); } return true; }
protected function __trigger() { $success = true; $result = new XMLElement('forgot-password'); $Members = $this->_Parent->ExtensionManager->create('members'); $username = $email = $code = NULL; if (isset($_POST['fields']['code']) && strlen(trim($_POST['fields']['code'])) > 0) { $code = $_POST['fields']['code']; $new_password = General::generatePassword(); self::__init(); $db = ASDCLoader::instance(); // Make sure we dont accidently use an expired token extension_Members::purgeTokens(); $token_row = $db->query(sprintf("SELECT * FROM `tbl_members_login_tokens` WHERE `token` = '%s' LIMIT 1", $db->escape($code)))->current(); // No code, you are a spy! if ($token_row === false) { redirect(URL . '/members/reset-pass/failed/'); } // Attempt to update the password $db->query(sprintf("UPDATE `tbl_entries_data_%d` SET `password` = '%s' WHERE `entry_id` = %d LIMIT 1", $Members->usernameAndPasswordField(), md5($new_password), $token_row->member_id)); extension_Members::purgeTokens($token_row->member_id); // SEND THE EMAIL!! $entry = $Members->initialiseMemberObject($token_row->member_id); $email_address = $entry->getData(self::findFieldID('email-address', 'members')); $name = $entry->getData(self::findFieldID('name', 'members')); $subject = 'Your new password'; $body = 'Dear {$name}, Just now, you have asked the Symphony brain trust to bestow you with a new password. Well, here it is: {$new-password} There\'s a good chance that you won\'t like this new password and want to change it - don\'t worry, we\'re not offended. You can do that once you\'ve logged in by going here: {$root}/members/change-pass/ If you have any trouble, please email us at support@symphony-cms.com and we\'ll do our best to help. Regards, Symphony Team'; $body = str_replace(array('{$name}', '{$root}', '{$new-password}'), array($name['value'], URL, $new_password), $body); $sender_email = 'noreply@' . parse_url(URL, PHP_URL_HOST); $sender_name = Symphony::Configuration()->get('sitename', 'general'); General::sendEmail($email_address['value'], $sender_email, $sender_name, $subject, $body); redirect(URL . '/members/reset-pass/success/'); } // Username take precedence if (isset($_POST['fields']['member-username']) && strlen(trim($_POST['fields']['member-username'])) > 0) { $username = $_POST['fields']['member-username']; } if (isset($_POST['fields']['member-email-address']) && strlen(trim($_POST['fields']['member-email-address'])) > 0) { $email = $_POST['fields']['member-email-address']; } if (is_null($username) && is_null($email)) { $success = false; $result->appendChild(new XMLElement('member-username', NULL, array('type' => 'missing'))); $result->appendChild(new XMLElement('member-email-address', NULL, array('type' => 'missing'))); } else { $members = array(); if (!is_null($email)) { $members = $Members->findMemberIDFromEmail($email); } if (!is_null($username)) { $members[] = $Members->findMemberIDFromUsername($username); } // remove duplicates $members = array_unique($members); try { if (is_array($members) && !empty($members)) { foreach ($members as $member_id) { $Members->sendForgotPasswordEmail($member_id); } redirect(URL . '/members/reset-pass/code/'); } } catch (Exception $e) { // Shouldn't get here, but will catch an invalid member ID if it does } $success = false; } $result->setAttribute('status', $success === true ? 'success' : 'error'); return $result; }
/** * Will delete the Role given a `$role_id`. Should `$purge_members` * be passed, this function will remove all Members associated with * this role as well * * @param integer $role_id * @param boolean $purge_members * @return boolean */ public function delete($role_id, $purge_members = false) { Symphony::Database()->delete("`tbl_members_roles_forbidden_pages`", " `role_id` = " . $role_id); Symphony::Database()->delete("`tbl_members_roles_event_permissions`", " `role_id` = " . $role_id); Symphony::Database()->delete("`tbl_members_roles`", " `id` = " . $role_id); if ($purge_members) { $members = Symphony::Database()->fetchCol('entry_id', sprintf("SELECT `entry_id` FROM `tbl_entries_data_%d` WHERE `role_id` = %d", extension_Members::getField('role')->get('id'), $role_id)); /** * Prior to deletion of entries. Array of Entry ID's is provided. * The array can be manipulated * * @delegate Delete * @param string $context * '/publish/' * @param array $checked * An array of Entry ID's passed by reference */ Symphony::ExtensionManager()->notifyMembers('Delete', '/publish/', array('entry_id' => &$checked)); $entryManager = new EntryManager(Symphony::Engine()); $entryManager->delete($members); } return true; }
/** * This will determine required action level for given a give section ID. * * @param $section_id * @param $entry_id * * @return integer */ private function determineActionLevel($section_id, $entry_id = null) { // if member role is Public, require ALL if ($this->memberGetRoleId() == Role::PUBLIC_ROLE) { return SE_Permissions::LEVEL_ALL; } if (!is_numeric($entry_id)) { $entry_id = null; } // if the section is same as Members section if ($section_id == extension_Members::getMembersSection() && $entry_id !== null) { // check the `entry_id` is the same as the logged in member if ($entry_id == $this->memberGetDriver()->getMemberID()) { return SE_Permissions::LEVEL_OWN; } } elseif ($this->relatedFieldExists($section_id)) { if ($entry_id === null) { return SE_Permissions::LEVEL_OWN; } $entry_member_id = $this->relatedFieldGetMemberId($section_id, $entry_id); $logged_in_member_id = $this->memberGetDriver()->getMemberID(); if ($entry_member_id == $logged_in_member_id) { return SE_Permissions::LEVEL_OWN; } } // default to ALL return SE_Permissions::LEVEL_ALL; }
/** * Determine current member role ID. * * @return int */ private final function memberDetermineRoleId() { $driver = $this->memberGetDriver(); // not logged in? if (!$driver->isLoggedIn()) { return $this->memberGetDefaultRoleId(); } /** @var $member Entry */ $member = $driver->getMember(); $role_data = $member->getData(extension_Members::getField('role')->get('id')); $role = RoleManager::fetch($role_data['role_id']); // role doesn't exist? if (!$role instanceof Role) { return $this->memberGetDefaultRoleId(); } return (int) $role_data['role_id']; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; $driver = Symphony::ExtensionManager()->create('members'); // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // If a member is logged in, return early with an error if ($driver->getMemberDriver()->isLoggedIn()) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('You cannot generate a recovery code while being logged in.')))); $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('generate-recovery-code-template'); // Check that either a Member: Username or Member: Password field // has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } // Check that a member exists first before proceeding. if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($identity->get('label'))), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Generate new password $newPassword = General::generatePassword(); // Set the Entry password to be reset and the current timestamp $auth = extension_Members::getField('authentication'); $status = Field::__OK__; $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); $entry_data = $entry->getData(); // Generate a Recovery Code with the same logic as a normal password $data = $auth->processRawFieldData(array('password' => General::hash($newPassword . $member_id, 'sha1')), $status); $data['recovery-code'] = $data['password']; $data['reset'] = 'yes'; $data['expires'] = DateTimeObj::get('Y-m-d H:i:s', time()); // Overwrite the password with the old password data. This prevents // a users account from being locked out if it it just reset by a random // member of the public $data['password'] = $entry_data[$auth->get('id')]['password']; $data['length'] = $entry_data[$auth->get('id')]['length']; $data['strength'] = $entry_data[$auth->get('id')]['strength']; Symphony::Database()->update($data, 'tbl_entries_data_' . $auth->get('id'), ' `entry_id` = ' . $member_id); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('recovery-code', $data['recovery-code'])); $result->appendChild($post_values); return $result; }
/** * Login function takes an associative array of fields that contain * an Identity field (Email/Username) and a Password field. They keys * should be the Field's `element_name`. * An optional parameter, `$isHashed` refers to if the password provided * is hashed already, or requires hashing prior to logging in. * * @throws Exception * @param array $credentials * @param boolean $isHashed * Defaults to false * @return boolean */ public function login(array $credentials, $isHashed = false) { $username = $email = $password = null; $data = extension_Members::$_errors = array(); // Map POST data to simple terms if (isset($credentials[$this->section->getFieldHandle('identity')])) { $username = $credentials[$this->section->getFieldHandle('identity')]; } if (isset($credentials[$this->section->getFieldHandle('email')])) { $email = $credentials[$this->section->getFieldHandle('email')]; } // Allow login via username OR email. This normalises the $data array from the custom // field names to simple names for ease of use. if (isset($username)) { $data['username'] = Symphony::Database()->cleanValue($username); } else { if (isset($email) && !is_null($this->section->getFieldHandle('email'))) { $data['email'] = Symphony::Database()->cleanValue($email); } } // Map POST data for password to `$password` if (isset($credentials[$this->section->getFieldHandle('authentication')])) { $password = $credentials[$this->section->getFieldHandle('authentication')]; $data['password'] = !empty($password) ? $password : ''; } // Check to ensure that we actually have some data to try and log a user in with. if (empty($data['password']) && isset($credentials[$this->section->getFieldHandle('authentication')])) { extension_Members::$_errors[$this->section->getFieldHandle('authentication')] = array('label' => $this->section->getField('authentication')->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('%s is a required field.', array($this->section->getField('authentication')->get('label')))); } if (isset($data['username']) && empty($data['username'])) { extension_Members::$_errors[$this->section->getFieldHandle('identity')] = array('label' => $this->section->getField('identity')->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('%s is a required field.', array($this->section->getField('identity')->get('label')))); } if (isset($data['email']) && empty($data['email'])) { extension_Members::$_errors[$this->section->getFieldHandle('email')] = array('label' => $this->section->getField('email')->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('%s is a required field.', array($this->section->getField('email')->get('label')))); } else { if (!fieldMemberEmail::applyValidationRule($email)) { extension_Members::$_errors[$this->section->getFieldHandle('email')] = array('message' => __('\'%s\' contains invalid characters.', array($this->section->getField('email')->get('label'))), 'message-id' => EventMessages::FIELD_INVALID, 'type' => 'invalid', 'label' => $this->section->getField('email')->get('label')); return null; } } // If there is errors already, no point continuing, return false if (!empty(extension_Members::$_errors)) { return false; } if ($id = $this->findMemberIDFromCredentials($data, $isHashed)) { try { self::$member_id = $id; $this->initialiseCookie(); $this->initialiseMemberObject(); $this->cookie->set('id', $id); $this->cookie->set('members-section-id', $this->getMember()->get('section_id')); if (isset($username)) { $this->cookie->set('username', $data['username']); } else { $this->cookie->set('email', $data['email']); } $this->cookie->set('password', $this->getMember()->getData($this->section->getField('authentication')->get('id'), true)->password); self::$isLoggedIn = true; } catch (Exception $ex) { // Or do something else? throw new Exception($ex); } return true; } $this->logout(); return false; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('activate-account-template'); // Do sanity checks on the incoming data $activation = extension_Members::getField('activation'); if (!$activation instanceof fieldMemberActivation) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Activation field found.')))); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Email field has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } // Ensure that the Member: Activation field has been provided if (!isset($fields[$activation->get('element_name')]) or empty($fields[$activation->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($activation->get('label'))), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } else { $fields[$activation->get('element_name')] = trim($fields[$activation->get('element_name')]); } // Check that a member exists first before proceeding. $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Retrieve Member's entry $driver = Symphony::ExtensionManager()->create('members'); $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); if ($entry->getData($activation->get('id'), true)->activated == 'yes') { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member is already activated.'), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } // Make sure we dont accidently use an expired code $activation->purgeCodes(); $code = $activation->isCodeActive($member_id); if ($code['code'] != $fields[$activation->get('element_name')]) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'invalid', 'message' => __('Activation error. Code was invalid or has expired.'), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } // Got to here, then everything is awesome. $status = Field::__OK__; $data = $activation->processRawFieldData(array('activated' => 'yes', 'timestamp' => DateTimeObj::get('Y-m-d H:i:s', time()), 'code' => null), $status); // Update the database setting activation to yes. Symphony::Database()->update($data, 'tbl_entries_data_' . $activation->get('id'), ' `entry_id` = ' . $member_id); // Update our `$entry` object with the new activation data $entry->setData($activation->get('id'), $data); // Simulate an array to login with. $data_fields = array_merge($fields, array(extension_Members::getFieldHandle('authentication') => $entry->getData(extension_Members::getField('authentication')->get('id'), true)->password)); // Only login if the Activation field allows auto login. if (extension_Members::getSetting('activate-account-auto-login') == 'no' || $driver->getMemberDriver()->login($data_fields, true)) { // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); } else { if (extension_Members::getSetting('activate-account-auto-login') == 'yes') { if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'error'); } } $result->appendChild($post_values); return $result; }
public function checkFrontendPagePermissions($context) { $this->initialiseCookie(); ## Cookies only show up on page refresh. This flag helps in making sure the correct XML is being set $loggedin = false; $action = $_REQUEST['member-action']; if (trim($action) == 'logout') { $this->logout(); redirect(URL); } elseif (isset($action['login'])) { $username = Symphony::Database()->cleanValue($_REQUEST['username']); $password = Symphony::Database()->cleanValue($_REQUEST['password']); if ($this->login($username, $password)) { if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } redirect(URL . $_SERVER['REQUEST_URI']); } self::$_failed_login_attempt = true; } elseif (isset($context['env']['url']['member-token']) && preg_match('/^[a-f0-9]{8}$/', $context['env']['url']['member-token'])) { $token = Symphony::Database()->fetchRow(0, "SELECT * FROM `tbl_members_login_tokens` WHERE `token` = '" . $context['env']['url']['member-token'] . "' LIMIT 1"); if (is_array($token) && !empty($token)) { $entry = $this->fetchMemberFromID($token['member_id']); $username_field_data = $entry->getData($this->usernameAndPasswordField()); $loggedin = $this->login($username_field_data['username'], $username_field_data['password'], true); self::purgeTokens($token['member_id']); } } else { $loggedin = $this->isLoggedIn(); } $this->initialiseMemberObject(); if ($loggedin && is_object($this->Member)) { $role_data = $this->Member->getData($this->roleField()); } $role = $this->fetchRole($loggedin ? $role_data['role_id'] : 1, true); if (!$role->canAccessPage((int) $context['page_data']['id'])) { /* Array ( [id] => 115 [parent] => 91 [title] => New [handle] => new [path] => downloads [params] => type [data_sources] => menu [events] => save_download [sortorder] => 13 [type] => Array ( ) [filelocation] => /Users/pointybeard/Sites/projects/overture/public/workspace/pages/downloads_new.xsl ) Array ( [id] => 136 [parent] => [title] => Forbidden [handle] => forbidden [path] => [params] => [data_sources] => menu [events] => [sortorder] => 37 ) */ if ($row = Symphony::Database()->fetchRow(0, "SELECT `tbl_pages`.* FROM `tbl_pages`, `tbl_pages_types`\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t WHERE `tbl_pages_types`.page_id = `tbl_pages`.id AND tbl_pages_types.`type` = '403'\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t LIMIT 1")) { //redirect(URL . '/' . $row['path'] . '/' . $row['handle']); //$page['filelocation'] = $this->resolvePageFileLocation($page['path'], $page['handle']); //$page['type'] = $this->__fetchPageTypes($page['id']); $row['type'] = Symphony::Database()->fetchCol('type', "SELECT `type` FROM `tbl_pages_types` WHERE `page_id` = '" . $row['id'] . "' "); $row['filelocation'] = PAGES . '/' . trim(str_replace('/', '_', $row['path'] . '_' . $row['handle']), '_') . '.xsl'; $context['page_data'] = $row; return; } $this->_Parent->customError(E_USER_ERROR, 'Forbidden', 'Please <a href="' . URL . '/symphony/login/">login</a> to view this page.', false, true, 'error', array('header' => 'HTTP/1.0 403 Forbidden')); } //$context['wrapper']->appendChild($this->buildXML()); }
public function cbCheckFrontendPagePermissions($context) { $this->initialiseCookie(); ## Cookies only show up on page refresh. This flag helps in making sure the correct XML is being set $loggedin = false; $action = $_REQUEST['member-action']; if (trim($action) == 'logout') { $this->logout(); if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } redirect(URL); } elseif (trim($action) == 'login') { $username = Symphony::Database()->cleanValue($_REQUEST['username']); $password = Symphony::Database()->cleanValue($_REQUEST['password']); if ($this->login($username, $password)) { if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } redirect(URL); } self::$_failed_login_attempt = true; } else { $loggedin = $this->isLoggedIn(); } $this->initialiseMemberObject(); if ($loggedin && is_object($this->Member)) { $role_data = $this->Member->getData($this->roleField()); $this->__updateSystemTimezoneOffset(); } $role = $this->fetchRole($loggedin ? $role_data['role_id'] : 1, true); if (!$role->canAccessPage((int) $context['page_data']['id'])) { if ($row = Symphony::Database()->fetchRow(0, "SELECT `tbl_pages`.* FROM `tbl_pages`, `tbl_pages_types` \r\n\t\t\t\t\tWHERE `tbl_pages_types`.page_id = `tbl_pages`.id AND tbl_pages_types.`type` = '403' \r\n\t\t\t\t\tLIMIT 1")) { $row['type'] = Symphony::Database()->fetchCol('type', "SELECT `type` FROM `tbl_pages_types` WHERE `page_id` = '" . $row['id'] . "' "); $row['filelocation'] = PAGES . '/' . trim(str_replace('/', '_', $row['path'] . '_' . $row['handle']), '_') . '.xsl'; $context['page_data'] = $row; return; } throw new SymphonyErrorPage('Please <a href="' . URL . '/symphony/login/">login</a> to view this page.', 'Forbidden', 'error', array('header' => 'HTTP/1.0 403 Forbidden')); } }
public static function findCodeExpiry() { return extension_Members::findCodeExpiry('tbl_fields_memberpassword'); }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_REQUEST['fields']; $this->driver = Symphony::ExtensionManager()->create('members'); $requested_identity = $fields[extension_Members::getFieldHandle('identity')]; // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Set the section ID $result = $this->setMembersSection($result, $_REQUEST['members-section-id']); if ($result->getAttribute('result') === 'error') { // We are not calling notifyMembersPasswordResetFailure here, // because this is not an authentication error $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { // We are not calling notifyMembersPasswordResetFailure here, // because this is not an authentication error return $result; } // Add any Email Templates for this event $this->addEmailTemplates('reset-password-template'); // Check that there is a row with this recovery code and that they // request a password reset $auth = $this->driver->getMemberDriver()->section->getField('authentication'); if (!$auth instanceof fieldMemberPassword) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Authentication field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Email field // has been detected $identity = $this->driver->getMemberDriver()->setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Identity field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } if (!isset($fields[$this->driver->getMemberDriver()->section->getFieldHandle('authentication')]['recovery-code']) or empty($fields[$this->driver->getMemberDriver()->section->getFieldHandle('authentication')]['recovery-code'])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('label' => $auth->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('Recovery code is a required field.')))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } $row = Symphony::Database()->fetchRow(0, sprintf("\n\t\t\t\t\tSELECT `entry_id`, `recovery-code`\n\t\t\t\t\tFROM tbl_entries_data_%d\n\t\t\t\t\tWHERE reset = 'yes'\n\t\t\t\t\tAND `recovery-code` = '%s'\n\t\t\t\t", $auth->get('id'), Symphony::Database()->cleanValue($fields[$this->driver->getMemberDriver()->section->getFieldHandle('authentication')]['recovery-code']))); if (empty($row)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member encountered errors.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('label' => $auth->get('label'), 'type' => 'invalid', 'message-id' => EventMessages::FIELD_INVALID, 'message' => __('No recovery code found.')))); $this->notifyMembersPasswordResetFailure($requested_identity); } else { // Retrieve Member Entry record $entry = $this->driver->getMemberDriver()->fetchMemberFromID($row['entry_id']); // Check that the given Identity data matches the Member that the // recovery code is for $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (!$entry instanceof Entry || $member_id != $row['entry_id']) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($identity->get('element_name'), null, extension_Members::$_errors[$identity->get('element_name')])); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // Check that the recovery code is still valid and has not expired if (is_null(Symphony::Database()->fetchVar('entry_id', 0, sprintf("\n\t\t\t\t\t\tSELECT `entry_id`\n\t\t\t\t\t\tFROM `tbl_entries_data_%d`\n\t\t\t\t\t\tWHERE `entry_id` = %d\n\t\t\t\t\t\tAND DATE_FORMAT(expires, '%%Y-%%m-%%d %%H:%%i:%%s') > '%s'\n\t\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", $auth->get('id'), $member_id, DateTimeObj::get('Y-m-d H:i:s', strtotime('now - ' . $auth->get('code_expiry'))))))) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('label' => $auth->get('label'), 'type' => 'invalid', 'message-id' => MemberEventMessages::RECOVERY_CODE_INVALID, 'message' => __('Recovery code has expired.')))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // Create new password using the auth field so simulate the checkPostFieldData // and processRawFieldData functions. $message = ''; // For the purposes of this event, the auth field should ALWAYS be required // as we have to set a password (ie. handle the case where this field is // actually optional) RE: #193 $auth->set('required', 'yes'); $status = $auth->checkPostFieldData($fields[$auth->get('element_name')], $message, $member_id); if (Field::__OK__ != $status) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('type' => $status == Field::__MISSING_FIELDS__ ? 'missing' : 'invalid', 'message' => $message, 'message-id' => $status == Field::__MISSING_FIELDS__ ? EventMessages::FIELD_MISSING : EventMessages::FIELD_INVALID, 'label' => $auth->get('label')))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // processRawFieldData will encode the user's new password with the current one $status = Field::__OK__; $data = $auth->processRawFieldData(array('password' => Symphony::Database()->cleanValue($fields[$auth->get('element_name')]['password'])), $status); $data['recovery-code'] = null; $data['reset'] = 'no'; $data['expires'] = null; // Update the database with the new password, removing the recovery code and setting // reset to no. Symphony::Database()->update($data, 'tbl_entries_data_' . $auth->get('id'), ' `entry_id` = ' . $member_id); /** * Fired just after a Member has reset their password. * * @delegate MembersPostResetPassword * @param string $context * '/frontend/' * @param integer $member_id * The Member ID of the member who just reset their password */ Symphony::ExtensionManager()->notifyMembers('MembersPostResetPassword', '/frontend/', array('member_id' => $member_id)); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); if (extension_Members::getSetting('reset-password-auto-login') == "yes") { // Instead of replicating the same logic, call the UpdatePasswordLogin which will // handle relogging in the user. $this->driver->getMemberDriver()->filter_UpdatePasswordLogin(array('entry' => $entry, 'fields' => array($this->driver->getMemberDriver()->section->getFieldHandle('authentication') => array('password' => Symphony::Database()->cleanValue($fields[$auth->get('element_name')]['password']))))); } if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); } $result->appendChild($post_values); return $result; }
public function __actionDelete($role_id = null, $redirect = null, $purge_members = false) { if (array_key_exists('delete', $_POST['action'])) { if (!$role_id) { redirect(extension_Members::baseURL() . 'roles/'); } if ($role_id == Role::PUBLIC_ROLE) { return $this->pageAlert(__('The Public role cannot be removed'), Alert::ERROR); } if (!($existing = RoleManager::fetch($role_id))) { throw new SymphonyErrorPage(__('The role you requested to delete does not exist.'), __('Role not found')); } // @todo What should happen to any Members that had this Role? RoleManager::delete($role_id, $purge_members); if (!is_null($redirect)) { redirect($redirect); } } }
/** * If the Members installation has a Activation field used, we need to make sure * that this field represents accurately what Role this Member actually has. * The Activation field allows developers to set a Activation Role, which is the role * assigned to Members who have registered, but not yet activated their account. * This Activation role masks the Role field's value, so the Member assumes the * Role of the Activation role. * * @param integer $entry_id * The Entry ID of the Member * @param integer $role_id * A given Role ID * @return integer * The resulting Role ID, whether that is the Activation ID or the * given `$role_id`. */ public function getActivationRole($entry_id = null, $role_id = null) { if (is_null($entry_id)) { return null; } $activation_role_id = null; $activation = extension_Members::getField('activation', $this->get('parent_section')); if (!is_null($activation) && !is_null($entry_id)) { $entry = EntryManager::fetch($entry_id); $entry = $entry[0]; if ($entry instanceof Entry && $entry->getData($activation->get('id'), true)->activated != 'yes') { $activation_role_id = $activation->get('activation_role_id'); } } if (!is_null($role_id) && is_null($activation_role_id)) { return $role_id; } else { return $activation_role_id; } }
/** * Part 2 - Update Password, logs the user in * If the user changed their password, we need to login them back into the * system with their new password. */ public function filter_UpdatePasswordLogin(array $context) { // If the user didn't update their password, or no Identity field exists return if (empty($context['fields'][extension_Members::getFieldHandle('authentication')]['password'])) { return; } // Handle which is the Identity field, either the Member: Username or Member: Email field $identity = is_null(extension_Members::getFieldHandle('identity')) ? 'email' : 'identity'; $this->login(array(extension_Members::getFieldHandle($identity) => $context['entry']->getData(extension_Members::getField($identity)->get('id'), true)->value, extension_Members::getFieldHandle('authentication') => $context['fields'][extension_Members::getFieldHandle('authentication')]['password']), false); if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('regenerate-activation-code-template'); $activation = extension_Members::getField('activation'); if (!$activation instanceof fieldMemberActivation) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Activation field found.')))); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Password field // has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($identity->get('label'))), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Make sure we dont accidently use an expired code $activation->purgeCodes(); // Check that a member exists first before proceeding. $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Check that the current member isn't already activated. If they // are, no point in regenerating the code. $driver = Symphony::ExtensionManager()->create('members'); $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); if ($entry->getData($activation->get('id'), true)->activated == 'yes') { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member is already activated.'), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } // Regenerate the code $status = Field::__OK__; $data = $activation->processRawFieldData(array('activated' => 'no'), $status); // Update the database setting activation to yes. Symphony::Database()->update($data, 'tbl_entries_data_' . $activation->get('id'), ' `entry_id` = ' . $member_id); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('activation-code', $data['code'])); $result->appendChild($post_values); return $result; }