Skip to content
Snippets Groups Projects
class.staff.php 46.9 KiB
Newer Older
  • Learn to ignore specific revisions
  •             if (($res = db_query($sql))
                        && (list($count, $sid) = db_fetch_row($res))) {
    
                    if ($count == 1 && $sid == $uid) {
    
                        $errors['isadmin'] = __(
                            'Cowardly refusing to remove or lock out the only active administrator'
                        );
                    }
                }
            }
    
    
    Jared Hancock's avatar
    Jared Hancock committed
            // Update some things for ::updateAccess to inspect
    
            $this->setDepartmentId($vars['dept_id']);
    
    Jared Hancock's avatar
    Jared Hancock committed
    
            // Format access update as [array(dept_id, role_id, alerts?)]
            $access = array();
            if (isset($vars['dept_access'])) {
                foreach (@$vars['dept_access'] as $dept_id) {
                    $access[] = array($dept_id, $vars['dept_access_role'][$dept_id],
                        @$vars['dept_access_alerts'][$dept_id]);
                }
            }
            $this->updateAccess($access, $errors);
    
            $this->setExtraAttr('def_assn_role',
                isset($vars['assign_use_pri_role']), false);
    
    Jared Hancock's avatar
    Jared Hancock committed
    
            // Format team membership as [array(team_id, alerts?)]
            $teams = array();
            if (isset($vars['teams'])) {
                foreach (@$vars['teams'] as $team_id) {
                    $teams[] = array($team_id, @$vars['team_alerts'][$team_id]);
                }
            }
            $this->updateTeams($teams, $errors);
    
            // Update the local permissions
            $this->updatePerms($vars['perms'], $errors);
    
    Jared Hancock's avatar
    Jared Hancock committed
            $this->isadmin = $vars['isadmin'];
    
    Jared Hancock's avatar
    Jared Hancock committed
            $this->isactive = isset($vars['islocked']) ? 0 : 1;
    
    Jared Hancock's avatar
    Jared Hancock committed
            $this->isvisible = isset($vars['isvisible'])?1:0;
            $this->onvacation = isset($vars['onvacation'])?1:0;
            $this->assigned_only = isset($vars['assigned_only'])?1:0;
    
            $this->role_id = $vars['role_id'];
    
    Jared Hancock's avatar
    Jared Hancock committed
            $this->username = $vars['username'];
            $this->firstname = $vars['firstname'];
            $this->lastname = $vars['lastname'];
            $this->email = $vars['email'];
            $this->backend = $vars['backend'];
            $this->phone = Format::phone($vars['phone']);
            $this->phone_ext = $vars['phone_ext'];
            $this->mobile = Format::phone($vars['mobile']);
            $this->notes = Format::sanitize($vars['notes']);
    
    
    Jared Hancock's avatar
    Jared Hancock committed
            if ($errors)
                return false;
    
    Jared Hancock's avatar
    Jared Hancock committed
            if ($this->save()) {
    
    Jared Hancock's avatar
    Jared Hancock committed
                if ($vars['welcome_email'])
    
                    $this->sendResetEmail('registration-staff', false);
    
    Jared Hancock's avatar
    Jared Hancock committed
                return true;
            }
    
    Jared Hancock's avatar
    Jared Hancock committed
            if (isset($this->staff_id)) {
    
                $errors['err']=sprintf(__('Unable to update %s.'), __('this agent'))
                   .' '.__('Internal error occurred');
    
                $errors['err']=sprintf(__('Unable to create %s.'), __('this agent'))
                   .' '.__('Internal error occurred');
    
    Jared Hancock's avatar
    Jared Hancock committed
            }
            return false;
        }
    
    Jared Hancock's avatar
    Jared Hancock committed
    
        /**
         * Parameters:
         * $access - (<array($dept_id, $role_id, $alerts)>) a list of the complete,
         *      extended access for this agent. Any the agent currently has, which
         *      is not listed will be removed.
         * $errors - (<array>) list of error messages from the process, which will
         *      be indexed by the dept_id number.
         */
        function updateAccess($access, &$errors) {
            reset($access);
            $dropped = array();
            foreach ($this->dept_access as $DA)
                $dropped[$DA->dept_id] = 1;
            while (list(, list($dept_id, $role_id, $alerts)) = each($access)) {
                unset($dropped[$dept_id]);
                if (!$role_id || !Role::lookup($role_id))
                    $errors['dept_access'][$dept_id] = __('Select a valid role');
                if (!$dept_id || !Dept::lookup($dept_id))
                    $errors['dept_access'][$dept_id] = __('Select a valid departent');
                if ($dept_id == $this->getDeptId())
                    $errors['dept_access'][$dept_id] = __('Agent already has access to this department');
                $da = $this->dept_access->findFirst(array('dept_id' => $dept_id));
                if (!isset($da)) {
                    $da = StaffDeptAccess::create(array(
                        'dept_id' => $dept_id, 'role_id' => $role_id
                    ));
                    $this->dept_access->add($da);
                }
                else {
                    $da->role_id = $role_id;
                }
                $da->setAlerts($alerts);
                if (!$errors)
                    $da->save();
            }
    
            if (!$errors && $dropped) {
    
    Jared Hancock's avatar
    Jared Hancock committed
                $this->dept_access
                    ->filter(array('dept_id__in' => array_keys($dropped)))
                    ->delete();
    
                $this->dept_access->reset();
            }
    
    Jared Hancock's avatar
    Jared Hancock committed
            return !$errors;
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function updatePerms($vars, &$errors=array()) {
    
            if (!$vars) {
                $this->permissions = '';
                return;
            }
    
            $permissions = $this->getPermission();
    
    Jared Hancock's avatar
    Jared Hancock committed
            foreach (RolePermission::allPermissions() as $g => $perms) {
    
                foreach ($perms as $k => $v) {
    
    Jared Hancock's avatar
    Jared Hancock committed
                    $permissions->set($k, in_array($k, $vars) ? 1 : 0);
                }
            }
            $this->permissions = $permissions->toJson();
    
            return true;
    
    
    interface RestrictedAccess {
        function checkStaffPerm($staff);
    }
    
    Jared Hancock's avatar
    Jared Hancock committed
    
    class StaffDeptAccess extends VerySimpleModel {
        static $meta = array(
            'table' => STAFF_DEPT_TABLE,
            'pk' => array('staff_id', 'dept_id'),
            'select_related' => array('dept', 'role'),
            'joins' => array(
                'dept' => array(
                    'constraint' => array('dept_id' => 'Dept.id'),
    
                    // FIXME: The ORM needs a way to support
                    //        staff__dept_access__dept performing a LEFT join b/c
                    //        staff__dept_access is LEFT
                    'null' => true,
    
    Jared Hancock's avatar
    Jared Hancock committed
                ),
                'staff' => array(
                    'constraint' => array('staff_id' => 'Staff.staff_id'),
                ),
                'role' => array(
                    'constraint' => array('role_id' => 'Role.id'),
                ),
            ),
        );
    
        const FLAG_ALERTS =     0x0001;
    
        function isAlertsEnabled() {
            return $this->flags & self::FLAG_ALERTS != 0;
        }
    
        function setFlag($flag, $value) {
            if ($value)
                $this->flags |= $flag;
            else
                $this->flags &= ~$flag;
        }
    
        function setAlerts($value) {
            $this->setFlag(self::FLAG_ALERTS, $value);
        }
    }
    
    
    /**
     * This form is used to administratively change the password. The
     * ChangePasswordForm is used for an agent to change their own password.
     */
    class PasswordResetForm
    extends AbstractForm {
        function buildFields() {
            return array(
    
                'welcome_email' => new BooleanField(array(
    
                    'default' => true,
                    'configuration' => array(
                        'desc' => __('Send the agent a password reset email'),
                    ),
                )),
                'passwd1' => new PasswordField(array(
                    'placeholder' => __('New Password'),
                    'required' => true,
                    'configuration' => array(
                        'classes' => 'span12',
                    ),
                    'visibility' => new VisibilityConstraint(
    
                        new Q(array('welcome_email' => false)),
    
                        VisibilityConstraint::HIDDEN
                    ),
                )),
                'passwd2' => new PasswordField(array(
                    'placeholder' => __('Confirm Password'),
                    'required' => true,
                    'configuration' => array(
                        'classes' => 'span12',
                    ),
                    'visibility' => new VisibilityConstraint(
    
                        new Q(array('welcome_email' => false)),
    
                        VisibilityConstraint::HIDDEN
                    ),
                )),
    
                'change_passwd' => new BooleanField(array(
    
                    'default' => true,
    
                    'configuration' => array(
                        'desc' => __('Require password change at next login'),
                        'classes' => 'form footer',
                    ),
                    'visibility' => new VisibilityConstraint(
    
                        new Q(array('welcome_email' => false)),
    
                        VisibilityConstraint::HIDDEN
                    ),
                )),
            );
        }
    
        function validate($clean) {
            if ($clean['passwd1'] != $clean['passwd2'])
                $this->getField('passwd1')->addError(__('Passwords do not match'));
        }
    
    class PasswordChangeForm
    extends AbstractForm {
        function buildFields() {
    
                'current' => new PasswordField(array(
                    'placeholder' => __('Current Password'),
                    'required' => true,
    
                    'configuration' => array(
                        'autofocus' => true,
                    ),
    
                )),
                'passwd1' => new PasswordField(array(
    
                    'label' => __('Enter a new password'),
    
                    'placeholder' => __('New Password'),
                    'required' => true,
                )),
                'passwd2' => new PasswordField(array(
                    'placeholder' => __('Confirm Password'),
                    'required' => true,
                )),
            );
    
    
            // When using the password reset system, the current password is not
            // required for agents.
            if (isset($_SESSION['_staff']['reset-token'])) {
                unset($fields['current']);
                $fields['passwd1']->set('configuration', array('autofocus' => true));
            }
            else {
                $fields['passwd1']->set('layout',
                    new GridFluidCell(12, array('style' => 'padding-top: 20px'))
                );
            }
            return $fields;
    
        }
    
        function getInstructions() {
            return __('Confirm your current password and enter a new password to continue');
        }
    
        function validate($clean) {
            if ($clean['passwd1'] != $clean['passwd2'])
                $this->getField('passwd1')->addError(__('Passwords do not match'));
    
    
    class ResetAgentPermissionsForm
    extends AbstractForm {
        function buildFields() {
            $permissions = array();
            foreach (RolePermission::allPermissions() as $g => $perms) {
                foreach ($perms as $k => $v) {
                    if (!$v['primary'])
                        continue;
                    $permissions[$g][$k] = "{$v['title']}{$v['desc']}";
                }
            }
            return array(
                'clone' => new ChoiceField(array(
                    'default' => 0,
                    'choices' =>
    
                        array(0 => '— '.__('Clone an existing agent').' —')
    
                        + Staff::getStaffMembers(),
                    'configuration' => array(
                        'classes' => 'span12',
                    ),
                )),
                'perms' => new ChoiceField(array(
                    'choices' => $permissions,
                    'widget' => 'TabbedBoxChoicesWidget',
                    'configuration' => array(
                        'multiple' => true,
                    ),
                )),
            );
        }
    
        function getClean() {
            $clean = parent::getClean();
            // Index permissions as ['ticket.edit' => 1]
            $clean['perms'] = array_keys($clean['perms']);
            return $clean;
        }
    
    
        function render($staff=true, $title=false, $options=array()) {
            return parent::render($staff, $title, $options + array('template' => 'dynamic-form-simple.tmpl.php'));
    
        }
    }
    
    class ChangeDepartmentForm
    extends AbstractForm {
        function buildFields() {
            return array(
                'dept_id' => new ChoiceField(array(
                    'default' => 0,
                    'required' => true,
                    'label' => __('Primary Department'),
                    'choices' =>
                        array(0 => '— '.__('Primary Department').' —')
                        + Dept::getDepartments(),
                    'configuration' => array(
                        'classes' => 'span12',
                    ),
                )),
                'role_id' => new ChoiceField(array(
                    'default' => 0,
                    'required' => true,
                    'label' => __('Primary Role'),
                    'choices' =>
                        array(0 => '— '.__('Corresponding Role').' —')
                        + Role::getRoles(),
                    'configuration' => array(
                        'classes' => 'span12',
                    ),
                )),
                'eavesdrop' => new BooleanField(array(
                    'configuration' => array(
                        'desc' => __('Maintain access to current primary department'),
                        'classes' => 'form footer',
                    ),
                )),
                // alerts?
            );
        }
    
    
        function getInstructions() {
            return __('Change the primary department and primary role of the selected agents');
        }
    
    
        function getClean() {
            $clean = parent::getClean();
            $clean['eavesdrop'] = $clean['eavesdrop'] ? 1 : 0;
            return $clean;
        }
    
    
        function render($staff=true, $title=false, $options=array()) {
            return parent::render($staff, $title, $options + array('template' => 'dynamic-form-simple.tmpl.php'));
    
    
    class StaffQuickAddForm
    extends AbstractForm {
        static $layout = 'GridFormLayout';
    
        function buildFields() {
            global $cfg;
    
            return array(
                'firstname' => new TextboxField(array(
                    'required' => true,
                    'configuration' => array(
                        'placeholder' => __("First Name"),
                        'autofocus' => true,
                    ),
                    'layout' => new GridFluidCell(6),
                )),
                'lastname' => new TextboxField(array(
                    'required' => true,
                    'configuration' => array(
                        'placeholder' => __("Last Name"),
                    ),
                    'layout' => new GridFluidCell(6),
                )),
                'email' => new TextboxField(array(
                    'required' => true,
                    'configuration' => array(
                        'validator' => 'email',
                        'placeholder' => __('Email Address — e.g. me@mycompany.com'),
    
                      ),
                )),
                'dept_id' => new ChoiceField(array(
                    'label' => __('Department'),
                    'required' => true,
                    'choices' => Dept::getDepartments(),
                    'default' => $cfg->getDefaultDeptId(),
                    'layout' => new GridFluidCell(6),
                )),
                'role_id' => new ChoiceField(array(
                    'label' => __('Primary Role'),
                    'required' => true,
                    'choices' =>
                        array(0 => __('Select Role'))
                        + Role::getRoles(),
                    'layout' => new GridFluidCell(6),
                )),
                'isadmin' => new BooleanField(array(
                    'label' => __('Account Type'),
                    'configuration' => array(
                        'desc' => __('Agent has access to the admin panel'),
                    ),
                    'layout' => new GridFluidCell(6),
                )),
                'welcome_email' => new BooleanField(array(
                    'configuration' => array(
                        'desc' => __('Send a welcome email with login information'),
                    ),
                    'default' => true,
                    'layout' => new GridFluidCell(12, array('style' => 'padding-top: 50px')),
                )),
                'passwd1' => new PasswordField(array(
                    'required' => true,
                    'configuration' => array(
                        'placeholder' => __("Temporary Password"),
                    ),
                    'visibility' => new VisibilityConstraint(
                        new Q(array('welcome_email' => false))
                    ),
                    'layout' => new GridFluidCell(6),
                )),
                'passwd2' => new PasswordField(array(
                    'required' => true,
                    'configuration' => array(
                        'placeholder' => __("Confirm Password"),
                    ),
                    'visibility' => new VisibilityConstraint(
                        new Q(array('welcome_email' => false))
                    ),
                    'layout' => new GridFluidCell(6),
                )),
                // TODO: Add role_id drop-down
            );
        }
    
        function getClean() {
            $clean = parent::getClean();
    
            list($clean['username'],) = preg_split('/[^\w.-]/u', $clean['email'], 2);
            if (mb_strlen($clean['username']) < 3 || Staff::lookup($clean['username']))
    
                $clean['username'] = mb_strtolower($clean['firstname']);
    
            $clean['perms'] = array(
                User::PERM_CREATE,
                User::PERM_EDIT,
                User::PERM_DELETE,
                User::PERM_MANAGE,
                User::PERM_DIRECTORY,
                Organization::PERM_CREATE,
                Organization::PERM_EDIT,
                Organization::PERM_DELETE,
                FAQ::PERM_MANAGE,
            );