Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • ActivateOperation
  • AvailableSitesBlock
  • ConfigBlock
  • ConfigOperation
  • DeactivateOperation
  • DeleteBlock
  • DeleteOperation
  • EditBlock
  • Hooks
  • IsUniqueOperation
  • LoginComboElement
  • LoginForm
  • LoginOperation
  • LogoutOperation
  • ManageBlock
  • Model
  • Module
  • OwnershipResolver
  • PermissionResolver
  • ProfileController
  • QueryOperationOperation
  • SaveOperation
  • UnlockLoginOperation
  • Update20131021
  • User
  • ViewProvider

Interfaces

  • OwnershipResolverInterface
  • PermissionResolverInterface

Traits

  • LoggedAtProperty

Exceptions

  • WebsiteAdminNotAccessible
  1 <?php
  2 
  3 /*
  4  * This file is part of the Icybee package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
  7  *
  8  * For the full copyright and license information, please view the LICENSE
  9  * file that was distributed with this source code.
 10  */
 11 
 12 namespace Icybee\Modules\Users;
 13 
 14 use ICanBoogie\I18n;
 15 use ICanBoogie\I18n\Translator\Proxi;
 16 
 17 /**
 18  * @property-read User $record The logged user.
 19  */
 20 class LoginOperation extends \ICanBoogie\Operation
 21 {
 22     /**
 23      * Adds form control.
 24      */
 25     protected function get_controls()
 26     {
 27         return [
 28 
 29             self::CONTROL_FORM => true
 30 
 31         ] + parent::get_controls();
 32     }
 33 
 34     /**
 35      * Returns the "connect" form of the target module.
 36      */
 37     protected function lazy_get_form()
 38     {
 39         return new LoginForm();
 40     }
 41 
 42     protected function validate(\ICanboogie\Errors $errors)
 43     {
 44         global $core;
 45 
 46         $request = $this->request;
 47         $username = $request[User::USERNAME];
 48         $password = $request[User::PASSWORD];
 49 
 50         $uid = $core->models['users']
 51         ->select('uid')
 52         ->where('username = ? OR email = ?', $username, $username)
 53         ->rc;
 54 
 55         if (!$uid)
 56         {
 57             $errors[User::PASSWORD] = $errors->format('Unknown username/password combination.');
 58 
 59             return false;
 60         }
 61 
 62         $user = $core->models['users'][$uid];
 63 
 64         $now = time();
 65         $login_unlock_time = $user->metas['login_unlock_time'];
 66 
 67         if ($login_unlock_time)
 68         {
 69             if ($login_unlock_time > $now)
 70             {
 71                 throw new \ICanBoogie\HTTP\HTTPError
 72                 (
 73                     \ICanBoogie\format("The user account has been locked after multiple failed login attempts.
 74                     An e-mail has been sent to unlock the account. Login attempts are locked until %time,
 75                     unless you unlock the account using the email sent.", [
 76 
 77                         '%count' => $user->metas['failed_login_count'],
 78                         '%time' => I18n\format_date($login_unlock_time, 'HH:mm')
 79 
 80                     ]),
 81 
 82                     403
 83                 );
 84             }
 85 
 86             $user->metas['login_unlock_time'] = null;
 87         }
 88 
 89         if (!$user->verify_password($password))
 90         {
 91             $errors[User::PASSWORD] = $errors->format('Unknown username/password combination.');
 92 
 93             $user->metas['failed_login_count'] += 1;
 94             $user->metas['failed_login_time'] = $now;
 95 
 96             if ($user->metas['failed_login_count'] >= 10)
 97             {
 98                 $token = \ICanBoogie\generate_token(40, \ICanBoogie\TOKEN_ALPHA . \ICanBoogie\TOKEN_NUMERIC);
 99 
100                 $user->metas['login_unlock_token'] = $token;
101                 $user->metas['login_unlock_time'] = $now + 3600;
102 
103                 $until = I18n\format_date($now + 3600, 'HH:mm');
104 
105                 $url = $core->site->url . '/api/users/unlock_login?' . http_build_query([
106 
107                     'username' => $username,
108                     'token' => $token,
109                     'continue' => $request->uri
110 
111                 ]);
112 
113                 $t = new Proxi([ 'scope' => [ \ICanBoogie\normalize($user->constructor, '_'), 'connect', 'operation' ] ]);
114 
115                 $core->mail([
116 
117                     'destination' => $user->email,
118                     'from' => 'no-reply@' . $_SERVER['HTTP_HOST'],
119                     'subject' => "Your account has been locked",
120                     'body' => <<<EOT
121 You receive this message because your account has been locked.
122 
123 After multiple failed login attempts your account has been locked until $until. You can use the
124 following link to unlock your account and try to login again:
125 
126 <$url>
127 
128 If you forgot your password, you'll be able to request a new one.
129 
130 If you didn't try to login neither forgot your password, this message might be the result of an
131 attack attempt on the website. If you think this is the case, please contact its admin.
132 
133 The remote address of the request was: $request->ip.
134 EOT
135                 ]);
136 
137                 unset($errors[User::PASSWORD]);
138 
139                 $errors[] = $errors->format("Your account has been locked, a message has been sent to your e-mail address.");
140             }
141 
142             return false;
143         }
144 
145         if (!$user->is_admin && !$user->is_activated)
146         {
147             $errors[] = $errors->format('User %username is not activated', [ '%username' => $username ]);
148 
149             return false;
150         }
151 
152         $this->record = $user;
153 
154         return true;
155     }
156 
157     /**
158      * Saves the user id in the session, sets the `user` property of the core object, updates the
159      * user's last connection date and finaly changes the operation location to the same request
160      * uri.
161      *
162      * @return bool `true` if the user is logged.
163      */
164     protected function process()
165     {
166         $user = $this->record;
167         $user->metas['failed_login_count'] = null;
168         $user->metas['failed_login_time'] = null;
169         $user->login();
170         $user->logged_at = 'now';
171         $user->save();
172 
173         $redirect_to = ($this->request['redirect_to'] ?: $this->request['continue']) ?: null;
174 
175         if ($redirect_to)
176         {
177             $this->response->location = $redirect_to;
178         }
179 
180         return true;
181     }
182 }
Autodoc API documentation generated by ApiGen 2.8.0