예제 #1
0
    /**
     * Responds to validate.edit hook notifications.
     *
     * @param Zikula_Event $event The event that triggered this function call.
     *
     * @return void
     *
     * @throws Zikula_Exception_Forbidden Thrown if the user does not have the appropriate access level for the function, or to
     *      modify the acceptance of policies on a user account other than his own.
     *
     * @throws Zikula_Exception_Fatal Thrown if the user record retrieved from the POST is in an unexpected form or its data is
     *      unexpected.
     */
    public function validateEdit(Zikula_Event $event)
    {
        if (!$this->request->isPost()) {
            // Validation is only appropriate for a post, otherwise it is probably a hack attempt.
            throw new Zikula_Exception_Forbidden();
        }

        // If there is no 'acceptedpolicies_uid' in the POST, then there is no attempt to update the acceptance of policies,
        // So there is nothing to validate.
        if ($this->request->getPost()->has('acceptedpolicies_uid')) {

            // Set up the necessary objects for the validation response
            $policiesAcceptedAtRegistration = array(
                'termsOfUse'                => $this->request->getPost()->get('acceptedpolicies_termsofuse', false),
                'privacyPolicy'             => $this->request->getPost()->get('acceptedpolicies_privacypolicy', false),
                'agePolicy'                 => $this->request->getPost()->get('acceptedpolicies_agepolicy', false),
                'cancellationRightPolicy'   => $this->request->getPost()->get('acceptedpolicies_cancellationrightpolicy', false),
                'tradeConditions'           => $this->request->getPost()->get('acceptedpolicies_tradeconditions', false)
            );
            $uid = $this->request->getPost()->get('acceptedpolicies_uid', false);
            $this->validation = new Zikula_Hook_ValidationResponse($uid ? $uid : '', $policiesAcceptedAtRegistration);

            $activePolicies = $this->helper->getActivePolicies();

            // Get the user record from the event. If there is no user record, create a dummy one.
            $user = $event->getSubject();
            if (!isset($user) || empty($user)) {
                $user = array(
                    '__ATTRIBUTES__' => array(),
                );
            }

            $goodUidAcceptPolicies = isset($uid) && !empty($uid) && is_numeric($uid);
            $goodUidUser = is_array($user) && isset($user['uid']) && is_numeric($user['uid']);

            if (!UserUtil::isLoggedIn()) {
                // User is not logged in, so this should be either part of a login attempt or a new user registration.

                $eventName = $event->getName();
                $isRegistration = ($eventName != 'users.login.validate_edit');

                if ($isRegistration) {
                    // A registration. There will be no accepted policies stored yet (function returns the appropriate array for a null uid),
                    // and there is no (or at least there *should* be no) uid to set on the validation response.
                    $acceptedPolicies = $this->helper->getAcceptedPolicies();
                } else {
                    // A login attempt.

                    $goodUidAcceptPolicies = $goodUidAcceptPolicies && ($uid > 2);
                    $goodUidUser = $goodUidUser && ($user['uid'] > 2);

                    if (!$goodUidUser || !$goodUidAcceptPolicies) {
                        // Critical fail if the $user record is bad, or if the uid used for Legal is bad.
                        throw new Zikula_Exception_Fatal();
                    } elseif ($user['uid'] != $uid) {
                        // Fail if the uid of the subject does not match the uid from the form. The user changed his
                        // login information, so not only should we not validate what was posted, we should not allow the user
                        // to proceed with this login attempt at all.
                        LogUtil::registerError(__('Sorry! You changed your authentication information, and one or more items displayed on the login screen may not have been applicable for your account. Please try logging in again.', $this->domain));
                        $this->request->getSession()->clearNamespace('Zikula_Users');
                        $this->request->getSession()->clearNamespace('Legal');
                        $this->redirect(ModUtil::url('Users', 'user', 'login'));
                    }

                    $acceptedPolicies = $this->helper->getAcceptedPolicies($uid);
                }

                // Do the validation
                if ($activePolicies['termsOfUse'] && !$acceptedPolicies['termsOfUse'] && (!isset($policiesAcceptedAtRegistration['termsOfUse']) || empty($policiesAcceptedAtRegistration['termsOfUse']) || !$policiesAcceptedAtRegistration['termsOfUse'])) {
                    if ($isRegistration) {
                        $validationErrorMsg = __('In order to register for a new account, you must accept this site\'s Terms of Use.', $this->domain);
                    } else {
                        $validationErrorMsg = __('In order to log in, you must accept this site\'s Terms of Use.', $this->domain);
                    }
                    $this->validation->addError('termsofuse', $validationErrorMsg);
                }

                if ($activePolicies['privacyPolicy'] && !$acceptedPolicies['privacyPolicy'] && (!isset($policiesAcceptedAtRegistration['privacyPolicy']) || empty($policiesAcceptedAtRegistration['privacyPolicy']) || !$policiesAcceptedAtRegistration['privacyPolicy'])) {
                    if ($isRegistration) {
                        $validationErrorMsg = __('In order to register for a new account, you must accept this site\'s Privacy Policy.', $this->domain);
                    } else {
                        $validationErrorMsg = __('In order to log in, you must accept this site\'s Privacy Policy.', $this->domain);
                    }
                    $this->validation->addError('privacypolicy', $validationErrorMsg);
                }

                if ($activePolicies['agePolicy'] && !$acceptedPolicies['agePolicy'] && (!isset($policiesAcceptedAtRegistration['agePolicy']) || empty($policiesAcceptedAtRegistration['agePolicy']) || !$policiesAcceptedAtRegistration['agePolicy'])) {
                    if ($isRegistration) {
                        $validationErrorMsg = __f('In order to register for a new account, you must confirm that you meet the requirements of this site\'s Minimum Age Policy. If you are not %1$s years of age or older, and you do not have a parent\'s permission to use this site, then you should not continue registering for access to this site.', array(ModUtil::getVar('Legal', Legal_Constant::MODVAR_MINIMUM_AGE, 0)), $this->domain);
                    } else {
                        $validationErrorMsg = __f('In order to log in, you must confirm that you meet the requirements of this site\'s Minimum Age Policy. If you are not %1$s years of age or older, and you do not have a parent\'s permission to use this site, then please ask your parent to contact a site administrator.', array(ModUtil::getVar('Legal', Legal_Constant::MODVAR_MINIMUM_AGE, 0)), $this->domain);
                    }
                    $this->validation->addError('agepolicy', $validationErrorMsg);
                }

                if ($activePolicies['cancellationRightPolicy'] && !$acceptedPolicies['cancellationRightPolicy'] && (!isset($policiesAcceptedAtRegistration['cancellationRightPolicy']) || empty($policiesAcceptedAtRegistration['cancellationRightPolicy']) || !$policiesAcceptedAtRegistration['cancellationRightPolicy'])) {
                    if ($isRegistration) {
                        $validationErrorMsg = __('In order to register for a new account, you must accept our cancellation right policy.', $this->domain);
                    } else {
                        $validationErrorMsg = __('In order to log in, you must accept our cancellation right policy.', $this->domain);
                    }
                    $this->validation->addError('cancellationrightpolicy', $validationErrorMsg);
                }

                if ($activePolicies['tradeConditions'] && !$acceptedPolicies['tradeConditions'] && (!isset($policiesAcceptedAtRegistration['tradeConditions']) || empty($policiesAcceptedAtRegistration['tradeConditions']) || !$policiesAcceptedAtRegistration['tradeConditions'])) {
                    if ($isRegistration) {
                        $validationErrorMsg = __('In order to register for a new account, you must accept our general terms and conditions of trade.', $this->domain);
                    } else {
                        $validationErrorMsg = __('In order to log in, you must accept our general terms and conditions of trade.', $this->domain);
                    }
                    $this->validation->addError('tradeconditions', $validationErrorMsg);
                }
            } else {
                // Someone is logged in, so either user looking at own record, an admin creating a new user,
                // an admin editing a user, or an admin editing a registration.

                // In this instance, we are only checking to see if the user has edit permission for the policy acceptance status
                // being changed.

                $editablePolicies = $this->helper->getEditablePolicies();

                if (!isset($user) || empty($user) || !is_array($user)) {
                        throw new Zikula_Exception_Fatal();
                }

                $isNewUser = (!isset($user['uid']) || empty($user['uid']));

                if (!$isNewUser && !is_numeric($user['uid'])) {
                        throw new Zikula_Exception_Fatal();
                }

                if ($isNewUser || ($user['uid'] > 2)) {
                    if (!$isNewUser) {
                        // Only check this stuff if the admin is not creating a new user. It doesn't make sense otherwise.

                        if (!$goodUidUser || !$goodUidAcceptPolicies || ($user['uid'] != $uid)) {
                            // Fail if the uid of the subject does not match the uid from the form. The user changed the uid
                            // on the account (is that even possible?!) or somehow the main user form and the part for Legal point
                            // to different user account. In any case, that is a bad situation that should cause a critical failure.

                            // Also fail if the $user record is bad, or if the uid used for Legal is bad.

                            throw new Zikula_Exception_Fatal();
                        }
                    }

                    // Fail on any attempt to accept a policy that is not edtiable.
                    if (isset($policiesAcceptedAtRegistration['termsOfUse']) && !$editablePolicies['termsOfUse']) {
                        throw new Zikula_Exception_Forbidden();
                    }
                    if (isset($policiesAcceptedAtRegistration['privacyPolicy']) && !$editablePolicies['privacyPolicy']) {
                        throw new Zikula_Exception_Forbidden();
                    }
                    if (isset($policiesAcceptedAtRegistration['agePolicy']) && !$editablePolicies['agePolicy']) {
                        throw new Zikula_Exception_Forbidden();
                    }
                    if (isset($policiesAcceptedAtRegistration['cancellationRightPolicy']) && !$editablePolicies['cancellationRightPolicy']) {
                        throw new Zikula_Exception_Forbidden();
                    }
                    if (isset($policiesAcceptedAtRegistration['tradeConditions']) && !$editablePolicies['tradeConditions']) {
                        throw new Zikula_Exception_Forbidden();
                    }
                }
            }

            $event->data->set(self::EVENT_KEY, $this->validation);
        }
    }
예제 #2
0
파일: User.php 프로젝트: projectesIF/Sirius
    /**
     * Allow the user to accept active terms of use and/or privacy policy.
     *
     * This function is currently used by the Legal module's handler for the users.login.veto event.
     *
     * @return string The rendered output from the template.
     *
     * @throws Zikula_Exception_Forbidden Thrown if the user is not logged in and the acceptance attempt is not a result of a login attempt.
     *
     * @throws Zikula_Exception_Fatal Thrown if the user is already logged in and the acceptance attempt is a result of a login attempt;
     *      also thrown in cases where expected data is not present or not in an expected form;
     *      also thrown if the call to this function is not the result of a POST operation or a GET operation.
     */
    public function acceptPolicies()
    {
        // Retrieve and delete any session variables being sent in by the log-in process before we give the function a chance to
        // throw an exception. We need to make sure no sensitive data is left dangling in the session variables.
        $sessionVars = $this->request->getSession()->get('Legal_Controller_User_acceptPolicies', null, $this->name);
        $this->request->getSession()->del('Legal_Controller_User_acceptPolicies', $this->name);

        $processed = false;
        $helper = new Legal_Helper_AcceptPolicies();

        if ($this->request->isPost()) {
            $this->checkCsrfToken();

            $isLogin = isset($sessionVars) && !empty($sessionVars);

            if (!$isLogin && !UserUtil::isLoggedIn()) {
                throw new Zikula_Exception_Forbidden();
            } elseif ($isLogin && UserUtil::isLoggedIn()) {
                throw new Zikula_Exception_Fatal();
            }

            $policiesUid = $this->request->getPost()->get('acceptedpolicies_uid', false);
            $acceptedPolicies = array(
                'termsOfUse'                => $this->request->getPost()->get('acceptedpolicies_termsofuse', false),
                'privacyPolicy'             => $this->request->getPost()->get('acceptedpolicies_privacypolicy', false),
                'agePolicy'                 => $this->request->getPost()->get('acceptedpolicies_agepolicy', false),
                'cancellationRightPolicy'   => $this->request->getPost()->get('acceptedpolicies_cancellationrightpolicy', false),
                'tradeConditions'           => $this->request->getPost()->get('acceptedpolicies_tradeconditions', false)
            );

            if (!isset($policiesUid) || empty($policiesUid) || !is_numeric($policiesUid)) {
                throw new Zikula_Exception_Fatal();
            }

            $activePolicies = $helper->getActivePolicies();
            $originalAcceptedPolicies = $helper->getAcceptedPolicies($policiesUid);

            $fieldErrors = array();

            if ($activePolicies['termsOfUse'] && !$originalAcceptedPolicies['termsOfUse'] && !$acceptedPolicies['termsOfUse']) {
                $fieldErrors['termsofuse'] = $this->__('You must accept this site\'s Terms of Use in order to proceed.');
            }

            if ($activePolicies['privacyPolicy'] && !$originalAcceptedPolicies['privacyPolicy'] && !$acceptedPolicies['privacyPolicy']) {
                $fieldErrors['privacypolicy'] = $this->__('You must accept this site\'s Privacy Policy in order to proceed.');
            }

            if ($activePolicies['agePolicy'] && !$originalAcceptedPolicies['agePolicy'] && !$acceptedPolicies['agePolicy']) {
                $fieldErrors['agepolicy'] = $this->__f('In order to log in, you must confirm that you meet the requirements of this site\'s Minimum Age Policy. If you are not %1$s years of age or older, and you do not have a parent\'s permission to use this site, then please ask your parent to contact a site administrator.', array(ModUtil::getVar('Legal', Legal_Constant::MODVAR_MINIMUM_AGE, 0)));
            }

            if ($activePolicies['cancellationRightPolicy'] && !$originalAcceptedPolicies['cancellationRightPolicy'] && !$acceptedPolicies['cancellationRightPolicy']) {
                $fieldErrors['cancellationrightpolicy'] = $this->__('You must accept our cancellation right policy in order to proceed.');
            }

            if ($activePolicies['tradeConditions'] && !$originalAcceptedPolicies['tradeConditions'] && !$acceptedPolicies['tradeConditions']) {
                $fieldErrors['tradeconditions'] = $this->__('You must accept our general terms and conditions of trade in order to proceed.');
            }

            if (empty($fieldErrors)) {
                $now = new DateTime('now', new DateTimeZone('UTC'));
                $nowStr = $now->format(DateTime::ISO8601);

                if ($activePolicies['termsOfUse'] && $acceptedPolicies['termsOfUse']) {
                    $termsOfUseProcessed = UserUtil::setVar(Legal_Constant::ATTRIBUTE_TERMSOFUSE_ACCEPTED, $nowStr, $policiesUid);
                } else {
                    $termsOfUseProcessed = !$activePolicies['termsOfUse'] || $originalAcceptedPolicies['termsOfUse'];
                }

                if ($activePolicies['privacyPolicy'] && $acceptedPolicies['privacyPolicy']) {
                    $privacyPolicyProcessed = UserUtil::setVar(Legal_Constant::ATTRIBUTE_PRIVACYPOLICY_ACCEPTED, $nowStr, $policiesUid);
                } else {
                    $privacyPolicyProcessed = !$activePolicies['privacyPolicy'] || $originalAcceptedPolicies['privacyPolicy'];
                }

                if ($activePolicies['agePolicy'] && $acceptedPolicies['agePolicy']) {
                    $agePolicyProcessed = UserUtil::setVar(Legal_Constant::ATTRIBUTE_AGEPOLICY_CONFIRMED, $nowStr, $policiesUid);
                } else {
                    $agePolicyProcessed = !$activePolicies['agePolicy'] || $originalAcceptedPolicies['agePolicy'];
                }

                if ($activePolicies['cancellationRightPolicy'] && $acceptedPolicies['cancellationRightPolicy']) {
                    $cancellationRightPolicyProcessed = UserUtil::setVar(Legal_Constant::ATTRIBUTE_CANCELLATIONRIGHTPOLICY_ACCEPTED, $nowStr, $policiesUid);
                } else {
                    $cancellationRightPolicyProcessed = !$activePolicies['cancellationRightPolicy'] || $originalAcceptedPolicies['cancellationRightPolicy'];
                }

                if ($activePolicies['tradeConditions'] && $acceptedPolicies['tradeConditions']) {
                    $tradeConditionsProcessed = UserUtil::setVar(Legal_Constant::ATTRIBUTE_TRADECONDITIONS_ACCEPTED, $nowStr, $policiesUid);
                } else {
                    $tradeConditionsProcessed = !$activePolicies['tradeConditions'] || $originalAcceptedPolicies['tradeConditions'];
                }

                $processed = $termsOfUseProcessed && $privacyPolicyProcessed && $agePolicyProcessed && $cancellationRightPolicyProcessed && $tradeConditionsProcessed;
            }

            if ($processed) {
                if ($isLogin) {
                    $loginArgs = $this->request->getSession()->get('Users_Controller_User_login', array(), 'Zikula_Users');
                    $loginArgs['authentication_method'] = $sessionVars['authentication_method'];
                    $loginArgs['authentication_info']   = $sessionVars['authentication_info'];
                    $loginArgs['rememberme']            = $sessionVars['rememberme'];
                    return ModUtil::func('Users', 'user', 'login', $loginArgs);
                } else {
                    $this->redirect(System::getHomepageUrl());
                }
            }
        } elseif ($this->request->isGet()) {
            $isLogin = $this->request->getGet()->get('login', false);
            $fieldErrors = array();
        } else {
            throw new Zikula_Exception_Forbidden();
        }

        // If we are coming here from the login process, then there are certain things that must have been
        // send along in the session variable. If not, then error.
        if ($isLogin && (!isset($sessionVars['user_obj']) || !is_array($sessionVars['user_obj'])
                || !isset($sessionVars['authentication_info']) || !is_array($sessionVars['authentication_info'])
                || !isset($sessionVars['authentication_method']) || !is_array($sessionVars['authentication_method']))
                ) {
            throw new Zikula_Exception_Fatal();
        }

        if ($isLogin) {
            $policiesUid = $sessionVars['user_obj']['uid'];
        } else {
            $policiesUid = UserUtil::getVar('uid');
        }

        if (!$policiesUid || empty($policiesUid)) {
            throw new Zikula_Exception_Fatal();
        }

        if ($isLogin) {
            // Pass along the session vars to updateAcceptance. We didn't want to just keep them in the session variable
            // Legal_Controller_User_acceptPolicies because if we hit an exception or got redirected, then the data
            // would have been orphaned, and it contains some sensitive information.
            SessionUtil::requireSession();
            $this->request->getSession()->set('Legal_Controller_User_acceptPolicies', $sessionVars, $this->name);
        }

        $templateVars = array(
            'login'                     => $isLogin,
            'policiesUid'               => $policiesUid,
            'activePolicies'            => $helper->getActivePolicies(),
            'acceptedPolicies'          => isset($acceptedPolicies) ? $acceptedPolicies : $helper->getAcceptedPolicies($policiesUid),
            'originalAcceptedPolicies'  => isset($originalAcceptedPolicies) ? $originalAcceptedPolicies : $helper->getAcceptedPolicies($policiesUid),
            'fieldErrors'               => $fieldErrors,
        );

        return $this->view->assign($templateVars)
                ->fetch('legal_user_acceptpolicies.tpl');
    }