Esempio n. 1
0
 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)));
     }
 }
Esempio n. 2
0
 /**
  * Allows a user to select which section they would like to use as their
  * active members section. This allows developers to build multiple sections
  * for migration during development.
  *
  * @uses AddCustomPreferenceFieldsets
  * @todo Look at how this could be expanded so users can log into multiple sections. This is not in scope for 1.0
  *
  * @param array $context
  */
 public function appendPreferences($context)
 {
     $fieldset = new XMLElement('fieldset');
     $fieldset->setAttribute('class', 'settings');
     $fieldset->appendChild(new XMLElement('legend', __('Members')));
     $fieldset->appendChild(new XMLElement('p', __('A Members section will at minimum contain either a Member: Email or a Member: Username field'), array('class' => 'help')));
     $div = new XMLElement('div');
     $label = new XMLElement('label', __('Active Members Section'));
     // Get the Sections that contain a Member field.
     $sections = SectionManager::fetch();
     $config_sections = explode(',', extension_Members::getSetting('section'));
     $member_sections = array();
     if (is_array($sections) && !empty($sections)) {
         foreach ($sections as $section) {
             $schema = $section->fetchFieldsSchema();
             foreach ($schema as $field) {
                 if (!in_array($field['type'], extension_Members::$member_fields)) {
                     continue;
                 }
                 if (array_key_exists($section->get('id'), $member_sections)) {
                     continue;
                 }
                 $member_sections[$section->get('id')] = $section->get('name');
             }
         }
     }
     // Build the options
     $options = array(array(null, false, null));
     foreach ($sections as $section_id => $section) {
         $options[] = array($section->get('id'), in_array($section->get('id'), $config_sections), $section->get('name'));
     }
     $label->appendChild(Widget::Select('settings[members][section][]', $options, array('multiple' => 'multiple')));
     $div->appendChild($label);
     $fieldset->appendChild($div);
     $context['wrapper']->appendChild($fieldset);
 }
 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;
 }
Esempio n. 4
0
 public function __viewIndex()
 {
     $this->setPageType('table');
     $this->setTitle(__('%1$s – %2$s', array(__('Symphony'), __('Member Roles'))));
     if (!FieldManager::isFieldUsed(extension_Members::getFieldType('role'))) {
         $this->pageAlert(__('There are no Member: Role fields in this Symphony installation. <a href="%s">Add Member: Role field?</a>', array(SYMPHONY_URL . '/blueprints/sections/')), Alert::NOTICE);
     }
     $this->appendSubheading(__('Member Roles'), Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL() . 'new/', __('Create a Role'), 'create button', NULL, array('accesskey' => 'c')));
     $roles = RoleManager::fetch();
     // Find all possible member sections
     $config_sections = explode(',', extension_Members::getSetting('section'));
     $aTableHead = array(array(__('Name'), 'col'));
     $aTableBody = array();
     if (!is_array($roles) || empty($roles)) {
         $aTableBody = array(Widget::TableRow(array(Widget::TableData(__('None found.'), 'inactive', NULL, count($aTableHead)))));
     } else {
         if (empty($config_sections)) {
             $aTableBody = array(Widget::TableRow(array(Widget::TableData(__('No Member sections exist in Symphony. <a href="%s">Create a Section?</a>', array(SYMPHONY_URL . '/blueprints/sections/')), 'inactive', NULL, count($aTableHead)))));
         } else {
             $hasRoles = FieldManager::isFieldUsed(extension_Members::getFieldType('role'));
             $roleFields = FieldManager::fetch(null, null, 'ASC', 'sortorder', extension_Members::getFieldType('role'));
             $with_selected_roles = array();
             $i = 0;
             foreach ($roles as $role) {
                 // Setup each cell
                 $td1 = Widget::TableData(Widget::Anchor($role->get('name'), Administration::instance()->getCurrentPageURL() . 'edit/' . $role->get('id') . '/', null, 'content'));
                 if ($role->get('id') != Role::PUBLIC_ROLE) {
                     $td1->appendChild(Widget::Input("items[{$role->get('id')}]", null, 'checkbox'));
                 }
                 // Get the number of members for this role, as long as it's not the Public Role.
                 if ($hasRoles && $role->get('id') != Role::PUBLIC_ROLE) {
                     $columns = array($td1);
                     foreach ($roleFields as $roleField) {
                         $section = SectionManager::fetch($roleField->get('parent_section'));
                         $member_count = Symphony::Database()->fetchVar('count', 0, sprintf("SELECT COUNT(*) AS `count` FROM `tbl_entries_data_%d` WHERE `role_id` = %d", $roleField->get('id'), $role->get('id')));
                         // If it's the first time we're looping over the available sections
                         // then change the table header, otherwise just ignore it as it's
                         // been done before
                         if ($i === 1) {
                             $aTableHead[] = array($section->get('name'), 'col');
                         }
                         $columns[] = Widget::TableData(Widget::Anchor("{$member_count}", SYMPHONY_URL . '/publish/' . $section->get('handle') . '/?filter=' . $roleField->get('element_name') . ':' . $role->get('id')));
                     }
                     $aTableBody[] = Widget::TableRow($columns);
                 } else {
                     if ($role->get('id') == Role::PUBLIC_ROLE) {
                         $td2 = Widget::TableData(__('This is the role assumed by the general public.'));
                     } else {
                         $td2 = Widget::TableData(__('None'), 'inactive');
                     }
                 }
                 // Add cells to a row
                 if ($i === 0) {
                     $aTableBody[] = Widget::TableRow(array($td1, $td2));
                 }
                 if ($hasRoles && $role->get('id') != Role::PUBLIC_ROLE) {
                     $with_selected_roles[] = array("move::" . $role->get('id'), false, $role->get('name'));
                 }
                 $i++;
             }
         }
     }
     $table = Widget::Table(Widget::TableHead($aTableHead), NULL, Widget::TableBody($aTableBody), 'selectable');
     $this->Form->appendChild($table);
     $tableActions = new XMLElement('div');
     $tableActions->setAttribute('class', 'actions');
     $options = array(0 => array(null, false, __('With Selected...')), 2 => array('delete', false, __('Delete'), 'confirm'), 3 => array('delete-members', false, __('Delete Members'), 'confirm'));
     if (count($with_selected_roles) > 0) {
         $options[1] = array('label' => __('Move Members To'), 'options' => $with_selected_roles);
     }
     $tableActions->appendChild(Widget::Apply($options));
     $this->Form->appendChild($tableActions);
 }
 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;
 }
Esempio n. 6
0
 /**
  * Given an array of grouped options ready for use in `Widget::Select`
  * loop over all the options and compare the value to configuration value
  * (as specified by `$handle`) and if it matches, set that option to true
  *
  * @param array $options
  * @param string $handle
  * @return array
  */
 public static function setActiveTemplate(array $options, $handle)
 {
     $templates = explode(',', extension_Members::getSetting($handle));
     foreach ($options as $index => $ext) {
         foreach ($ext['options'] as $key => $opt) {
             if (in_array($opt[0], $templates)) {
                 $options[$index]['options'][$key][1] = true;
             }
         }
     }
     array_unshift($options, array(null, false, null));
     return $options;
 }