/** * Logins the user (performing the brute force attack check) * * @param myUser $userSf * @param PcUser $userApp - the user trying to login * @param boolean $rememberme - whether the user wanted to remember the login * @param boolean $remembermeCookieAlreadySet - in this case, if even * $rememberme is true, the cookie is not set because it is already available * @return boolean - false if the account is blocked because of a brute * force attack detection */ public static function login(myUser $userSf, PcUser $userApp, $rememberme = false, $remembermeCookieAlreadySet = false) { // Check whether the account must be block because of a // brute force attack detection $c = new Criteria(); $c->addJoin(PcUserPeer::ID, PcFailedLoginsPeer::USER_ID, Criteria::INNER_JOIN); $c->add(PcUserPeer::ID, $userApp->getId(), Criteria::EQUAL); $row = PcFailedLoginsPeer::doSelectOne($c); if ($row) { $maxAttempts = sfConfig::get('app_bruteForceLockout_loginAttemptThreshold'); $currentAttempts = $row->getTimes(); $timeout = sfConfig::get('app_bruteForceLockout_lockoutDuration'); $secondsElapsedFromLastAttempt = time() - strtotime($row->getUpdatedAt()); if ($secondsElapsedFromLastAttempt > $timeout) { // reset the 'failed logins' situation for the user $row->delete(); } else { if ($currentAttempts >= $maxAttempts) { PcWatchdog::alert('Brute force attack attempt', 'For the userid ' . $row->getUserId()); return false; } } } $userApp->setLanguage(PcUtils::getVisitorAcceptLanguage()); $userApp->setIpAddress(PcUtils::getVisitorIPAddress()); $userApp->save(); $userSf->setAuthenticated(true); $userSf->setAttribute('userid', $userApp->getId()); if ($userApp->isAdmin()) { $userSf->addCredential('admin'); } if ($userApp->isStaffMember()) { $userSf->addCredential('staffMember'); } if ($userApp->isContractor()) { $userSf->addCredential('contractor'); } if ($userApp->isEditor()) { $userSf->addCredential('editor'); } if ($userApp->isTranslator()) { $userSf->addCredential('translator'); } if ($rememberme && !$remembermeCookieAlreadySet) { self::setRememberMeCookie($userSf, $userApp); } else { if (!$rememberme) { // the user may login a second time (while still logged in because of forum integration problems), without // ticking the rememberme checkbox self::resetRememberMeCookie(); } else { // if $rememberme and $remembermeCookieAlreadySet // are both true we don't need to do anything } } sfContext::getInstance()->getEventDispatcher()->notify(new sfEvent('CustomAuthLogin', 'custom_auth.login', array('user' => $userApp, 'rememberme' => $rememberme))); return true; }
/** * Register a new user * * @param string $email - the email address * @param string $password - the plain password (no encryption) * @param string $lang - if it is null or empty, the language will be detected from the header of the request * @param string $preferredLang - this should be a 2-char abbreviation of the lang the user wants, * among the ones in the main app.yml config file * @param string $tzLabel - a timezone label as in the PcTimezone db table * @param integer $dstOn (1 or 0) - whether or not the dst for the user is on * @param boolen $joinNewsletter(=false) - whether the user decided to join our newsletter * @param boolen $sendActivationEmail(=true) - whether to send the activation email * @return boolean|PcUser false is a user with that email already exists, the PcUser object otherwise */ public static function registerNewUser($email, $password, $lang, $preferredLang, $tzLabel, $dstOn, $joinNewsletter = false, $sendActivationEmail = true) { if (self::emailExist($email)) { return false; } $newUser = new PcUser(); $newUser->setEmail($email); $newUser->setPassword($password); $newUser->setAwaitingActivation(1); if ($joinNewsletter) { $newUser->setNewsletter(1); } $newUser->save(); // Dealing with timezone $newUser->setDstActive($dstOn); $c = new Criteria(); $c->add(PcTimezonePeer::LABEL, $tzLabel, Criteria::EQUAL); $timezone = PcTimezonePeer::doSelectOne($c); if (!is_object($timezone)) { // set to a default one $timezone = PcTimezonePeer::retrieveByPK(21); } $newUser->setTimezoneId($timezone->getId()); // Dealing with formats // _ time format: the countries with the majority of our users are using the // 12H format, thus we can leave the default // _ for the date format we check whether they are in USA // _ for the first day of the week, we check whether they are in USA $dateFormatId = 3; $weekStart = 1; // from Monday $tzOffset = $timezone->getOffset(); if ($tzOffset <= -300 && $tzOffset >= -450) { $dateFormatId = 4; $weekStart = 0; // from Sunday } $newUser->setDateFormat($dateFormatId); $newUser->setWeekStart($weekStart); if ($lang != null && $lang !== '') { $newUser->setLanguage($lang); } else { $newUser->setLanguage(PcUtils::getVisitorAcceptLanguage()); } $availableLangs = PcLanguagePeer::getAvailableLanguageAbbreviations(); if (in_array($preferredLang, $availableLangs)) { $newUser->setPreferredLanguage($preferredLang); } else { $newUser->setPreferredLanguage(SfConfig::get('app_site_defaultLang')); } $newUser->setIpAddress(PcUtils::getVisitorIPAddress()); if ($sessionEntryPoint = sfContext::getInstance()->getUser()->getAttribute('session_entry_point')) { $newUser->setSessionEntryPoint($sessionEntryPoint); } if ($sessionReferral = sfContext::getInstance()->getUser()->getAttribute('session_referral')) { $newUser->setSessionReferral($sessionReferral); } $newUser->save(); // Creating system lists $inboxList = new PcList(); $inboxList->setIsInbox(1)->setTitle(__('ACCOUNT_LISTS_INBOX'))->setCreator($newUser)->save(); $todoList = new PcList(); $todoList->setIsTodo(1)->setTitle(__('ACCOUNT_LISTS_TODO'))->setCreator($newUser)->save(); // Creating default contexts $context = new PcUsersContexts(); $context->setPcUser($newUser)->setContext(__('ACCOUNT_TAGS_DEFAULT_HOME'))->save(); $context = new PcUsersContexts(); $context->setPcUser($newUser)->setContext(__('ACCOUNT_TAGS_DEFAULT_ERRANDS'))->save(); $context = new PcUsersContexts(); $context->setPcUser($newUser)->setContext(__('ACCOUNT_TAGS_DEFAULT_COMPUTER'))->save(); // Creating some tasks for the inbox $newUser->addToInbox(__('ACCOUNT_MISC_WELCOME_TASK')); // creating Plancake email address $newUser->generateAndStorePlancakeEmailAddress(); // I need to use a token for the activation of their account $token = ''; $c = new Criteria(); $c->add(PcActivationTokenPeer::USER_ID, $newUser->getId(), Criteria::EQUAL); $tokenEntry = PcActivationTokenPeer::doSelectOne($c); if (is_object($tokenEntry)) { $token = $tokenEntry->getToken(); } else { $secret = sfConfig::get('app_registration_secret'); // token doesn't need to be 32-char long. It is better to keep it short // so there will be less chance the email client will break the link into 2 lines $token = substr(md5($newUser->getId() . $secret . time()), 0, 14); $tokenEntry = new PcActivationToken(); $tokenEntry->setUserId($newUser->getId()); $tokenEntry->setToken($token); $tokenEntry->save(); } // now we can send the email if ($sendActivationEmail) { $link = sfContext::getInstance()->getController()->genUrl('@activation?t=' . $token, true); $from = sfConfig::get('app_emailAddress_contact'); $subject = 'Plancake - ' . __('WEBSITE_REGISTRATION_EMAIL_SUBJECT'); $body = sprintf(__('WEBSITE_REGISTRATION_EMAIL_BODY'), $link); PcUtils::sendEmail($email, $subject, $body, $from); } $newUser->refreshLatestBlogAccess(); sfContext::getInstance()->getEventDispatcher()->notify(new sfEvent($newUser, 'user.sign_up', array('user' => $newUser, 'plainPassword' => $password))); return $newUser; }