def email_change_POST(self): ''' Processes POST requests to generate change email hash ''' if self.check_csrf: token = self.request.session.get_csrf_token() else: token = '' if self.check_csrf and token != self.request.POST.get('token'): return {'status': False, 'msg': self.request._('csrf-mismatch', default='CSRF token did not match.', domain='pyramid_fullauth'), 'token': token} try: Session.query(User).filter(User.email == self.request.POST.get('email', '')).one() return {'status': False, 'msg': self.request._('User with this email exists', domain='pyramid_fullauth'), 'token': token} except NoResultFound: pass user = self.request.user try: result = self.request.registry.notify(BeforeEmailChange(self.request, user)) except AttributeError as e: return {'status': False, 'msg': e.message, 'token': token} try: user.set_new_email(self.request.POST.get('email', '')) except EmptyError: return {'status': False, 'msg': self.request._( 'E-mail is empty', domain='pyramid_fullauth'), 'token': token} except EmailValidationError: return {'status': False, 'msg': self.request._( 'Incorrect e-mail format', domain='pyramid_fullauth'), 'token': token} response_values = {'status': True, 'msg': self.request._('We sent you email to activate your new email address', domain='pyramid_fullauth')} try: self.request.registry.notify(AfterEmailChange(self.request, user)) except HTTPFound as redirect: if self.request.is_xhr: response_values['url'] = redirect.location return response_values else: return redirect else: if self.request.is_xhr: return response_values else: return HTTPFound(location='/')
def reset_continue(self): ''' Method that serves password reset page ''' user = self.request.matchdict.get('user') if self.check_csrf: token = self.request.session.get_csrf_token() else: token = '' if self.request.method == 'POST': # if turned on, check for csrf token if self.check_csrf and token != self.request.POST.get('token'): return {'status': False, 'msg': self.request._('csrf-mismatch', default='CSRF token did not match.', domain='pyramid_fullauth'), 'token': token} password = self.request.POST.get('password', None) password_confirm = self.request.POST.get('confirm_password', None) if password == password_confirm: try: self.request.registry.notify(BeforeReset(self.request, user)) validate_passsword(self.request, password, user) user.reset_key = None try: Session.query(AuthenticationProvider).filter( AuthenticationProvider.user_id == user.id, AuthenticationProvider.provider == u'email').one() except NoResultFound: user.providers.append( AuthenticationProvider(provider=u'email', provider_id=user.id)) Session.flush() except (ValidateError, AttributeError) as e: return {'status': False, 'msg': str(e), 'token': token} try: self.request.registry.notify(AfterReset(self.request, user)) except HTTPFound as redirect: return redirect else: return {'status': False, 'msg': self.request._('password-mismatch', default='Password doesn\'t match', domain='pyramid_fullauth'), 'token': token} return {'status': True, 'token': token}
def rank(self): """Rank by the number of promote and cover offers.""" logger.warn('XXX how do we retire offers?') # Start with a rank of zero and ignore everything that's over a week old. n = 0 now = datetime.datetime.utcnow() one_week_ago = get_one_week_ago() # For each promote offer. query = Session.query(PromoteOffer.created) query = query.filter(PromoteOffer.assignment==self) query = query.filter(PromoteOffer.created>one_week_ago) results = query.all() self.promote_offer_count = len(results) for item in results: created_date = item[0] delta = now - created_date # Make sure the diff is at least one second (n.b.: # ``timedelta.total_seconds`` requires Python>=2.7) if hasattr(delta, 'total_seconds'): tot_seconds = delta.total_seconds() else: secs = delta.seconds + delta.days * 24.0 * 3600.0 tot_seconds = (delta.microseconds + secs * 10.0**6) / 10.0**6 seconds = max(tot_seconds, 1) # Half life of 1 day. score = 1440 / seconds n += score # For each cover offer. query = Session.query(CoverOffer.created) query = query.filter(CoverOffer.assignment==self) query = query.filter(CoverOffer.created>one_week_ago) results = query.all() self.cover_offer_count = len(results) for item in results: created_date = item[0] delta = now - created_date if hasattr(delta, 'total_seconds'): tot_seconds = delta.total_seconds() else: secs = delta.seconds + delta.days * 24.0 * 3600.0 tot_seconds = (delta.microseconds + secs * 10.0**6) / 10.0**6 seconds = max(tot_seconds, 1) # Three times as important as promote offers. score = 3 * 1440 / seconds n += score return n
def includeme(config): registry = config.registry settings = registry.settings config.include('pyramid_basemodel') config.include('pyramid_tm') models = [ (IActivationClass, Activation), (IUserClass, User), (IUIStrings, UIStringsBase), (IConsumerClass, Consumer), (IDBSession, Session) ] for iface, imp in models: if not registry.queryUtility(iface): registry.registerUtility(imp, iface) if asbool(settings.get('basemodel.should_create_all', True)): key = settings['api.key'] secret = settings.get('api.secret') ttl = settings.get('api.ttl', auth.DEFAULT_TTL) session = Session() consumer = session.query(Consumer).filter(Consumer.key == key).first() if not consumer: with transaction.manager: consumer = Consumer(key=key, secret=secret, ttl=ttl) session.add(consumer) session.flush()
def reset_POST(self): ''' Processes POST requests to generate reset password hashes ''' if self.check_csrf: token = self.request.session.get_csrf_token() else: token = '' if self.check_csrf and token != self.request.POST.get('token'): return {'status': False, 'msg': self.request._('csrf-mismatch', default='CSRF token did not match.', domain='pyramid_fullauth'), 'token': token} try: user = Session.query(User).filter( User.email == self.request.POST.get('email', '')).one() except NoResultFound: return {'status': False, 'msg': self.request._('user-not-exists', default='User does not exists', domain='pyramid_fullauth'), 'token': token} user.set_reset() try: self.request.registry.notify(AfterResetRequest(self.request, user)) except HTTPFound as redirect: return redirect return HTTPFound(location='/')
def includeme(config): registry = config.registry settings = registry.settings config.include('pyramid_basemodel') config.include('pyramid_tm') models = [(interfaces.IActivationClass, Activation), (interfaces.IUserClass, User), (interfaces.IUIStrings, UIStringsBase), (IConsumerClass, Consumer), (IDBSession, Session)] for iface, imp in models: if not registry.queryUtility(iface): registry.registerUtility(imp, iface) if asbool(settings.get('basemodel.should_create_all', True)): key = settings['api.key'] secret = settings.get('api.secret') ttl = settings.get('api.ttl', auth.DEFAULT_TTL) session = Session() consumer = session.query(Consumer).filter(Consumer.key == key).first() if not consumer: with transaction.manager: consumer = Consumer(key=key, secret=secret, ttl=ttl) session.add(consumer) session.flush()
def database_locales(request): ''' Returns list of all database locales available :returns: dictionary of Language objects language_code: Language :rtype: dict ''' locales = {} for language in Session.query(Language).all(): locales[language.language_code] = language return locales
def create_api_consumer(target, connection, **kwargs): key = settings['api.key'] secret = settings.get('api.secret') ttl = settings.get('api.ttl', auth.DEFAULT_TTL) session = Session() consumer = session.query(Consumer).filter(Consumer.key == key).first() if not consumer: with transaction.manager: consumer = Consumer(key=key, secret=secret, ttl=ttl) session.add(consumer) session.flush()
def user(request): ''' When called for the first time, it queries for user, which is later available as a pure property overriding this method :returns: logged in user object, or None :rtype: pyramid_fullauth.models.User ''' userid = unauthenticated_userid(request) if userid: try: user = Session.query(User).filter(User.id == userid).one() return user except NoResultFound: # pragma: no cover pass
def activate_hash(info, request): ''' Checks whether activate hash is correct :param dict info: pyramid info dict with path fragments and info :param pyramid.request.Request request: request object ''' activate_hash = info['match'].get('hash', None) if activate_hash: try: info['match']['user'] = Session.query(User).filter(User.activate_key == activate_hash).one() return True except NoResultFound: pass return False
def set_provider(user, provider_name, user_provider_id): ''' Method sets the provider authentication method for user. ''' if user.id: try: provider_auth = Session.query( AuthenticationProvider).filter(AuthenticationProvider.user_id == user.id, AuthenticationProvider.provider == provider_name).one() if provider_auth.provider_id != user_provider_id: return False return True except NoResultFound: pass provider_auth = AuthenticationProvider() provider_auth.provider = provider_name provider_auth.provider_id = user_provider_id user.providers.append(provider_auth) return True
def get_all( class_, order_by='email', order_direction='asc', filter_by=None, offset=None, search=None, limit=None, request=None, security=None, ): """Return all users. filter_by: dict -> {'name': 'foo'} By default, order by User.email. """ User = class_ q = Session.query(User) # Set correct order_by for timestamps if order_by == 'modified': order_by = 'm' elif order_by == 'created': order_by = 'c' q = q.order_by('{} {}'.format(order_by, order_direction)) if filter_by: q = q.filter_by(**filter_by) if search: q = q.filter( or_( User.email.ilike(u'%{}%'.format(search)), User.fullname.ilike(u'%{}%'.format(search)), )) if offset: q = q.slice(offset[0], offset[1]) elif limit: q = q.limit(limit) return q
def activate(self): ''' Process account activation ''' activate_hash = self.request.matchdict.get('hash') user = None response = {} response['status'] = True if activate_hash: try: user = Session.query(User).filter(User.activate_key == activate_hash).one() if not user.is_active: user.is_active = True except NoResultFound: response['status'] = False try: self.request.registry.notify(AfterActivate(self.request, user)) except HTTPFound as e: # it's a redirect, let's follow it! return e return response
def login(self): ''' Login action ''' if self.check_csrf: token = self.request.session.get_csrf_token() else: token = '' after = self.request.params.get('after') or self.request.referer return_dict = {'status': False, 'msg': self.request._('Login error', domain='pyramid_fullauth'), 'after': after, 'token': token} if authenticated_userid(self.request): try: self.request.registry.notify(AlreadyLoggedIn(self.request)) except HTTPFound as redirect: if self.request.is_xhr: return_dict['status'] = True del return_dict['msg'] return_dict['after'] = redirect.location return return_dict else: return redirect # Code copied from alternative. Not yes implemented if self.request.method == 'POST': if self.check_csrf and token != self.request.POST.get('token'): return_dict['msg'] = self.request._('csrf-mismatch', default='CSRF token did not match.', domain='pyramid_fullauth') return return_dict email = self.request.POST.get('email', '') password = self.request.POST.get('password', '') try: user = Session.query(User).filter(User.email == email).one() try: self.request.registry.notify(BeforeLogIn(self.request, user)) except AttributeError as e: return_dict['msg'] = str(e) return return_dict if user.check_password(password): try: # if remember in POST set cookie timeout to one month remember_me = self.request.POST.get('remember') self.request.registry.notify(AfterLogIn(self.request, user)) except HTTPFound as redirect: redirect_return = self.request.login_perform( user, location=redirect.location, remember_me=remember_me) if self.request.is_xhr: return_dict['status'] = True del return_dict['msg'] return_dict['after'] = redirect_return.location return return_dict else: return redirect_return except AttributeError as e: return_dict['msg'] = str(e) return return_dict else: redirect = self.request.login_perform(user, remember_me=remember_me) if self.request.is_xhr: return_dict['status'] = True del return_dict['msg'] return_dict['after'] = redirect.location return return_dict else: return redirect else: return_dict['msg'] = self.request._('Wrong e-mail or password.', domain='pyramid_fullauth') return return_dict except NoResultFound: self.request.registry.notify(BeforeLogIn(self.request, None)) return_dict['msg'] = self.request._('Wrong e-mail or password.', domain='pyramid_fullauth') return return_dict else: self.request.registry.notify(BeforeLogIn(self.request, None)) return_dict['status'] = True del return_dict['msg'] return return_dict
def login(self): """ Login action """ after = self.request.params.get("after") or self.request.referer return_dict = { "status": False, "msg": self.request._("Login error", domain="pyramid_fullauth"), "after": after, "csrf_token": self.request.session.get_csrf_token(), } if authenticated_userid(self.request): try: self.request.registry.notify(AlreadyLoggedIn(self.request)) except HTTPFound as redirect: if self.request.is_xhr: return_dict["status"] = True del return_dict["msg"] return_dict["after"] = redirect.location return return_dict else: return redirect # Code copied from alternative. Not yes implemented if self.request.method == "POST": email = self.request.POST.get("email", "") password = self.request.POST.get("password", "") try: user = Session.query(User).filter(User.email == email).one() try: self.request.registry.notify(BeforeLogIn(self.request, user)) except AttributeError as e: return_dict["msg"] = str(e) return return_dict if user.check_password(password): try: # if remember in POST set cookie timeout to one month remember_me = self.request.POST.get("remember") self.request.registry.notify(AfterLogIn(self.request, user)) except HTTPFound as redirect: redirect_return = self.request.login_perform( user, location=redirect.location, remember_me=remember_me ) if self.request.is_xhr: return_dict["status"] = True del return_dict["msg"] return_dict["after"] = redirect_return.location return return_dict else: return redirect_return except AttributeError as e: return_dict["msg"] = str(e) return return_dict else: redirect = self.request.login_perform(user, remember_me=remember_me) if self.request.is_xhr: return_dict["status"] = True del return_dict["msg"] return_dict["after"] = redirect.location return return_dict else: return redirect else: return_dict["msg"] = self.request._("Wrong e-mail or password.", domain="pyramid_fullauth") return return_dict except NoResultFound: self.request.registry.notify(BeforeLogIn(self.request, None)) return_dict["msg"] = self.request._("Wrong e-mail or password.", domain="pyramid_fullauth") return return_dict else: self.request.registry.notify(BeforeLogIn(self.request, None)) return_dict["status"] = True del return_dict["msg"] return return_dict
def register_POST(self): ''' Process POST register request ''' invalid_fields = {} response_values = { 'status': False, 'msg': self.request._('You have an error in your registration form', domain='pyramid_fullauth'), 'csrf_token': self.request.session.get_csrf_token()} response_values['errors'] = invalid_fields email = self.request.POST.get('email', u'') # here if e-mail is already in database try: Session.query(User).filter(User.email == email).one() invalid_fields['email'] = self.request._('User with given e-mail already exists!', domain='pyramid_fullauth') except NoResultFound: pass try: user = User() try: user.email = email except ValidateError as e: # do not overwrite existing error if not 'email' in invalid_fields: invalid_fields['email'] = str(e) user.address_ip = self.request.remote_addr if self.request.config.fullauth.register.password.require: try: tools.validate_passsword(self.request, self.request.POST.get('password', u''), user) except ValidateError as e: invalid_fields['password'] = e.message else: user.password = tools.password_generator( self.request.config.fullauth.register.password.length_min) self.request.registry.notify(BeforeRegister(self.request, user, invalid_fields)) if not invalid_fields: Session.add(user) Session.flush() # lets add AuthenticationProvider as email! user.providers.append( AuthenticationProvider(provider=u'email', provider_id=user.id)) else: return response_values except AttributeError as e: invalid_fields['msg'] = str(e) return response_values response_values['status'] = True response_values['msg'] = self.request._('You have successfully registered', domain='pyramid_fullauth') try: self.request.registry.notify(AfterRegister(self.request, user, response_values)) except HTTPFound as redirect: return redirect return response_values
def read_user(self, email): ''' Reads user ''' return Session.query(User).filter(User.email == email).first()
def register_social(self): ''' Action provides social authorization functionality. When authorization with facebook or twitter is done successfully action tries to find existing user in database, if it exists - login this user, otherwise creates new user. ''' def set_provider(user, provider_name, user_provider_id): ''' Method sets the provider authentication method for user. ''' if user.id: try: provider_auth = Session.query( AuthenticationProvider).filter(AuthenticationProvider.user_id == user.id, AuthenticationProvider.provider == provider_name).one() if provider_auth.provider_id != user_provider_id: return False return True except NoResultFound: pass provider_auth = AuthenticationProvider() provider_auth.provider = provider_name provider_auth.provider_id = user_provider_id user.providers.append(provider_auth) return True context = self.request.context response_values = {'status': False, 'csrf_token': self.request.session.get_csrf_token()} user = self.request.user if user: # when user is logged in already, just connect social account to # this app account try: if set_provider(user, context.provider_name, context.profile['accounts'][0]['userid']): Session.flush() else: response_values['msg'] = 'Your account is already connected to other {provider} account.'.format( provider=context.provider_name) return response_values except IntegrityError: response_values['msg'] = 'This {provider} account is already connected with other account.'.format( provider=context.provider_name) try: self.request.registry.notify(SocialAccountAlreadyConnected( self.request, user, context.profile, response_values)) except HTTPFound as redirect: # it's a redirect, let's follow it! return redirect return response_values else: # getting verified email from provider if 'verifiedEmail' in context.profile: email = context.profile['verifiedEmail'] # getting first of the emails provided by social login provider elif 'emails' in context.profile and context.profile['emails'] and 'value' in context.profile['emails'][0]: email = context.profile['emails'][0]['value'] # generating some random email address based on social userid and provider domain else: email = u'{0}@{1}'.format(context.profile['accounts'][ 0]['userid'], context.profile['accounts'][0]['domain']) try: user = Session.query( User).join(AuthenticationProvider).filter(AuthenticationProvider.provider == context.provider_name, AuthenticationProvider.provider_id == context.profile['accounts'][0]['userid']).one() except NoResultFound: user = None # If the user for the provider was not found then check if in the DB exists user with the same email if not user: try: user = Session.query(User).filter(User.email == email).one() # If we are here that means that in the DB exists user with the same email but without the provider # then we connect social account to this user set_provider(user, context.provider_name, context.profile['accounts'][0]['userid']) Session.flush() except NoResultFound: length_min = self.request.config.fullauth.register.password.length_min user = User(email=email, password=tools.password_generator(length_min), address_ip=self.request.remote_addr) self.request.registry.notify(BeforeSocialRegister(self.request, user, context.profile)) set_provider(user, context.provider_name, context.profile['accounts'][0]['userid']) Session.add(user) Session.flush() user.is_active = True try: self.request.registry.notify(AfterSocialRegister( self.request, user, context.profile, response_values)) except HTTPFound as redirect: # it's a redirect, let's follow it! return redirect # if we're here, user exists try: self.request.registry.notify(AfterSocialLogIn(self.request, user, context.profile)) except HTTPFound as redirect: # it's a redirect, let's follow it! return self.request.login_perform(user, location=redirect.location) else: return self.request.login_perform(user)