def login(self, log=DEFAULT, **kwargs): """ Login a user Keyword Args: username/email/name_of_your_username_field (string) - username password/name_of_your_passfield (string) - user's password remember_me (boolean) - extend the duration of the login to settings.long_expiration """ settings = self.settings session = current.session table_user = self.table_user() if 'username' in table_user.fields or \ not settings.login_email_validate: userfield_validator = IS_NOT_EMPTY( error_message=self.messages.is_empty) if not settings.username_case_sensitive: userfield_validator = [IS_LOWER(), userfield_validator] else: userfield_validator = IS_EMAIL( error_message=self.messages.invalid_email) if not settings.email_case_sensitive: userfield_validator = [IS_LOWER(), userfield_validator] passfield = settings.password_field if log is DEFAULT: log = self.messages['login_log'] user = None # Setup the default field used for the userfield if self.settings.login_userfield: userfield = self.settings.login_userfield else: if 'username' in table_user.fields: userfield = 'username' else: userfield = 'email' # Get the userfield from kwargs and validate it userfield_value = kwargs.get(userfield) if userfield_value is None: raise KeyError('%s not found in kwargs' % userfield) validated, error = self.__validate(userfield_value, userfield_validator) if error: return { 'errors': { userfield: error }, 'message': self.messages.invalid_login, 'user': None } # Get the user for this userfield and check it user = table_user(**{userfield: validated}) if user is None: return { 'errors': { userfield: self.messages.invalid_user }, 'message': self.messages.invalid_login, 'user': None } if (user.registration_key or '').startswith('pending'): return { 'errors': None, 'message': self.messages.registration_pending, 'user': None } elif user.registration_key in ('disabled', 'blocked'): return { 'errors': None, 'message': self.messages.login_disabled, 'user': None } elif (user.registration_key is not None and user.registration_key.strip()): return { 'errors': None, 'message': self.messages.registration_verifying, 'user': None } # Finally verify the password passfield = settings.password_field password = table_user[passfield].validate(kwargs.get(passfield, ''))[0] if password == user[passfield]: self.login_user(user) session.auth.expiration = \ kwargs.get('remember_me', False) and \ settings.long_expiration or \ settings.expiration session.auth.remember_me = kwargs.get('remember_me', False) self.log_event(log, user) return { 'errors': None, 'message': self.messages.logged_in, 'user': { k: user[k] for k in table_user.fields if table_user[k].readable } } else: self.log_event(self.messages['login_failed_log'], kwargs) return { 'errors': { passfield: self.messages.invalid_password }, 'message': self.messages.invalid_login, 'user': None }
def define_tables(self, username=None, signature=None, migrate=None, fake_migrate=None): """ To be called unless tables are defined manually Examples: Use as:: # defines all needed tables and table files # 'myprefix_auth_user.table', ... auth.define_tables(migrate='myprefix_') # defines all needed tables without migration/table files auth.define_tables(migrate=False) """ db = self.db if migrate is None: migrate = db._migrate if fake_migrate is None: fake_migrate = db._fake_migrate settings = self.settings if username is None: username = settings.use_username else: settings.use_username = username if not self.signature: self.define_signature() if signature is True: signature_list = [self.signature] elif not signature: signature_list = [] elif isinstance(signature, Table): signature_list = [signature] else: signature_list = signature self._table_signature_list = signature_list # Should it defined in __init__ first?? is_not_empty = IS_NOT_EMPTY(error_message=self.messages.is_empty) is_crypted = CRYPT(key=settings.hmac_key, min_length=settings.password_min_length) is_unique_email = [ IS_EMAIL(error_message=self.messages.invalid_email), IS_NOT_IN_DB(db, '%s.email' % settings.table_user_name, error_message=self.messages.email_taken) ] if not settings.email_case_sensitive: is_unique_email.insert(1, IS_LOWER()) if settings.table_user_name not in db.tables: passfield = settings.password_field extra_fields = settings.extra_fields.get(settings.table_user_name, []) + signature_list # cas_provider Will always be None here but we compare it anyway so subclasses can use our define_tables if username or settings.cas_provider: is_unique_username = \ [IS_MATCH('[\w\.\-]+', strict=True, error_message=self.messages.invalid_username), IS_NOT_IN_DB(db, '%s.username' % settings.table_user_name, error_message=self.messages.username_taken)] if not settings.username_case_sensitive: is_unique_username.insert(1, IS_LOWER()) db.define_table( settings.table_user_name, Field('first_name', length=128, default='', label=self.messages.label_first_name, requires=is_not_empty), Field('last_name', length=128, default='', label=self.messages.label_last_name, requires=is_not_empty), Field('email', length=512, default='', label=self.messages.label_email, requires=is_unique_email), Field('username', length=128, default='', label=self.messages.label_username, requires=is_unique_username), Field(passfield, 'password', length=512, readable=False, label=self.messages.label_password, requires=[is_crypted]), Field('registration_key', length=512, writable=False, readable=False, default='', label=self.messages.label_registration_key), Field('reset_password_key', length=512, writable=False, readable=False, default='', label=self.messages.label_reset_password_key), Field('registration_id', length=512, writable=False, readable=False, default='', label=self.messages.label_registration_id), *extra_fields, **dict(migrate=self._get_migrate(settings.table_user_name, migrate), fake_migrate=fake_migrate, format='%(username)s')) else: db.define_table( settings.table_user_name, Field('first_name', length=128, default='', label=self.messages.label_first_name, requires=is_not_empty), Field('last_name', length=128, default='', label=self.messages.label_last_name, requires=is_not_empty), Field('email', length=512, default='', label=self.messages.label_email, requires=is_unique_email), Field(passfield, 'password', length=512, readable=False, label=self.messages.label_password, requires=[is_crypted]), Field('registration_key', length=512, writable=False, readable=False, default='', label=self.messages.label_registration_key), Field('reset_password_key', length=512, writable=False, readable=False, default='', label=self.messages.label_reset_password_key), Field('registration_id', length=512, writable=False, readable=False, default='', label=self.messages.label_registration_id), *extra_fields, **dict(migrate=self._get_migrate(settings.table_user_name, migrate), fake_migrate=fake_migrate, format='%(first_name)s %(last_name)s (%(id)s)')) reference_table_user = '******' % settings.table_user_name if settings.table_group_name not in db.tables: extra_fields = settings.extra_fields.get(settings.table_group_name, []) + signature_list db.define_table( settings.table_group_name, Field('role', length=512, default='', label=self.messages.label_role, requires=IS_NOT_IN_DB( db, '%s.role' % settings.table_group_name)), Field('description', 'text', label=self.messages.label_description), *extra_fields, **dict(migrate=self._get_migrate(settings.table_group_name, migrate), fake_migrate=fake_migrate, format='%(role)s (%(id)s)')) reference_table_group = 'reference %s' % settings.table_group_name if settings.table_membership_name not in db.tables: extra_fields = settings.extra_fields.get( settings.table_membership_name, []) + signature_list db.define_table( settings.table_membership_name, Field('user_id', reference_table_user, label=self.messages.label_user_id), Field('group_id', reference_table_group, label=self.messages.label_group_id), *extra_fields, **dict(migrate=self._get_migrate( settings.table_membership_name, migrate), fake_migrate=fake_migrate)) if settings.table_permission_name not in db.tables: extra_fields = settings.extra_fields.get( settings.table_permission_name, []) + signature_list db.define_table( settings.table_permission_name, Field('group_id', reference_table_group, label=self.messages.label_group_id), Field('name', default='default', length=512, label=self.messages.label_name, requires=is_not_empty), Field('table_name', length=512, label=self.messages.label_table_name), Field('record_id', 'integer', default=0, label=self.messages.label_record_id, requires=IS_INT_IN_RANGE(0, 10**9)), *extra_fields, **dict(migrate=self._get_migrate( settings.table_permission_name, migrate), fake_migrate=fake_migrate)) if settings.table_event_name not in db.tables: db.define_table( settings.table_event_name, Field('time_stamp', 'datetime', default=current.request.now, label=self.messages.label_time_stamp), Field('client_ip', default=current.request.client, label=self.messages.label_client_ip), Field('user_id', reference_table_user, default=None, label=self.messages.label_user_id), Field('origin', default='auth', length=512, label=self.messages.label_origin, requires=is_not_empty), Field('description', 'text', default='', label=self.messages.label_description, requires=is_not_empty), *settings.extra_fields.get(settings.table_event_name, []), **dict(migrate=self._get_migrate(settings.table_event_name, migrate), fake_migrate=fake_migrate)) return self