def test_transaction_aware_task_throws_exception(celery_worker, init, dbsession): """Test that transaction aware task does not commit if exception is thrown..""" celery_app, request = setup_celery(init) with request.tm: # Do a dummy database write User = get_user_class(init.config.registry) u = User(username="******", email="*****@*****.**") dbsession.add(u) dbsession.flush() failure_task.apply_async(args=[request, u.id]) # Let the task travel in Celery queue time.sleep(0.5) # Task should not fire unless we exit the transaction assert u.username != "set by celery" # Let the transaction commit time.sleep(0.5) # Task has now fired after transaction was committed with transaction.manager: u = dbsession.query(User).get(1) assert u.username == "test"
def test_request_aware_task_success(celery_worker, init, dbsession): """Test that RequestAwareTask executes.""" celery_app, request = setup_celery(init) User = get_user_class(init.config.registry) with request.tm: # Do a dummy database write u = User(username="******", email="*****@*****.**") dbsession.add(u) with request.tm: # Do a dummy database write u = dbsession.query(User).get(1) request_task.apply_async(kwargs={"request": request, "user_id": u.id}) # Let the task travel in Celery queue time.sleep(1.0) # Task should not fire unless we exit the transaction assert u.username != "set by celery" # Let the transaction commit time.sleep(0.5) # Task has now fired after transaction was committed with transaction.manager: u = dbsession.query(User).get(1) assert u.username == "set by celery"
def create(request, username, email, password=None, source="command_line", admin=False): """Create a new site user from command line. :param request: :param username: :param email: :param password: :param source: :param admin: Set this user to admin. The first user is always implicitly admin. :return: """ User = get_user_class(request.registry) dbsession = request.dbsession u = dbsession.query(User).filter_by(email=email).first() if u is not None: return u u = User(email=email, username=username) if password: user_registry = get_user_registry(request) user_registry.set_password(u, password) u.registration_source = source u.activated_at = now() dbsession.add(u) dbsession.flush() request.registry.notify(UserCreated(request, u)) if admin: group = dbsession.query(Group).filter_by(name="admin").one_or_none() group.users.append(u) return u
def test_transaction_aware_task_fail(celery_worker, init, dbsession): """Test that transaction that do not commit do not run tasks.""" celery_app, request = setup_celery(init) with request.tm: # Do a dummy database write User = get_user_class(init.config.registry) u = User(username="******", email="*****@*****.**") dbsession.add(u) try: # Tasks do not execute if transaction is aborted because of exception with request.tm: assert dbsession.query(User).count() == 1 assert dbsession.query(User).get(1).username == "test" success_task_never_called.apply_async(args=[request, 1]) raise RuntimeError("aargh") except RuntimeError: pass # Let the transaction commit (which should not happen) time.sleep(0.5) # Because of exception, Celery never fires with transaction.manager: u = dbsession.query(User).get(1) assert u.username == "test"
def activate(self): """View to activate user after clicking email link.""" code = self.request.matchdict.get('code', None) user_id = self.request.matchdict.get('user_id', None) User = get_user_class(self.request.registry) activation = self.Activation.get_by_code(self.request, code) if activation: user_uuid = slug_to_uuid(user_id) user = self.request.dbsession.query(User).filter_by(uuid=user_uuid).first() if not user or (user.activation != activation): return HTTPNotFound() if user: self.db.delete(activation) self.db.flush() if self.login_after_activation: return authenticated(self.request, user) else: self.request.registry.notify(RegistrationActivatedEvent(self.request, user, activation)) return HTTPFound(location=self.after_activate_url) return HTTPNotFound()
def main(argv=sys.argv): if len(argv) < 3: usage(argv) config_uri = argv[1] request = init_websauna(config_uri) User = get_user_class(request.registry) dbsession = request.dbsession if len(argv) == 4: password = argv[3] else: password = getpass.getpass("Password:"******"Password (again):") if password != password2: sys.exit("Password did not match") with transaction.manager: u = User(email=argv[2], username=argv[2]) u.password = password u.registration_source = "command_line" u.activated_at = now() dbsession.add(u) dbsession.flush() request.registry.notify(UserCreated(request, u)) print("Created user #{}: {}, admin: {}".format(u.id, u.email, u.is_admin()))
def resolve_principals(userid:int, request:Request) -> Optional[List[str]]: """Get applied groups and other for the user. This is a callback for :py:class:`pyramid.authentication.SessionAuthenticationPolicy`. * List all groups as ``group:admin`` style strings * List super user as ``superuser:superuser`` style string """ dbsession = request.dbsession user_class = get_user_class(request.registry) settings = request.registry.settings # Read superuser names from the config superusers = aslist(settings.get("websauna.superusers")) admin_as_superuser = asbool(settings.get("websauna.admin_as_superuser", False)) user = dbsession.query(user_class).get(userid) if user and user.can_login(): principals = ['group:{}'.format(g.name) for g in user.groups] # Allow superuser permission if user.username in superusers or user.email in superusers or (admin_as_superuser and "group:admin" in principals): principals.append("superuser:superuser") return principals # User not found, user disabled return None
def validate_unique_user_email(node, value, **kwargs): """Make sure we cannot enter the same username twice.""" request = node.bindings["request"] dbsession = request.dbsession User = get_user_class(request.registry) if dbsession.query(User).filter_by(email=value).first(): raise c.Invalid(node, "Email address already taken")
def success_task(request, user_id): # TODO: Eliminate global dbsession dbsession = request.dbsession registry = request.registry User = get_user_class(registry) u = dbsession.query(User).get(user_id) u.username = "******"
def failure_task(request, user_id): # TODO: Eliminate global dbsession dbsession = request.dbsession registry = request.registry User = get_user_class(registry) u = dbsession.query(User).get(user_id) u.username = "******" raise RuntimeError("Exception raised")
def validate_unique_user_email(node, value, **kwargs): """Make sure we cannot enter the same username twice.""" request = node.bindings["request"] dbsession = request.dbsession User = get_user_class(request.registry) value = value.strip() if dbsession.query(User).filter_by(email=value).one_or_none(): raise c.Invalid(node, "Email address already taken")
def request_task(request, user_id): # Run transaction manually with transaction.manager: # TODO: Eliminate global dbsession dbsession = request.dbsession registry = request.registry User = get_user_class(registry) u = dbsession.query(User).get(user_id) u.username = "******"
def email_exists(node: c.SchemaNode, value: str): """Colander validator that ensures a User exists with the email. :param node: Colander SchemaNode. :param value: Email address. :raises: c.Invalid if email is not registered for an User. """ request = node.bindings['request'] User = get_user_class(request.registry) exists = request.dbsession.query(User).filter(User.email.ilike(value)).one_or_none() if not exists: raise c.Invalid(node, "Email does not exists: {email}".format(email=value))
def validate_unique_user_email(node: c.SchemaNode, value: str, **kwargs: dict): """Make sure we cannot enter the same username twice. :param node: Colander SchemaNode. :param value: Email address. :param kwargs: Keyword arguments. :raises: c.Invalid if email address already taken. """ request = node.bindings["request"] dbsession = request.dbsession User = get_user_class(request.registry) value = value.strip() if dbsession.query(User).filter_by(email=value).one_or_none(): raise c.Invalid(node, "Email address already taken")
def authenticated(request:Request, user:UserMixin, location:str=None) -> HTTPFound: """Logs in the user. TODO: Make this is a registry component for overriding Sets the auth cookies and redirects to the page defined in horus.login_redirect, which defaults to a view named 'index'. Fills in user last login details. :param request: Current request :param user: User model to log in :param location: Override the redirect page. If none use ``horus.login_redirect`` """ # See that our user model matches one we expect from the configuration registry = request.registry User = get_user_class(registry) assert User assert isinstance(user, User) assert user.id, "Cannot login with invalid user object" if not user.can_login(): raise RuntimeError("Got authenticated() request for disabled user - should not happen") headers = remember(request, user.id) # assert headers, "Authentication backend did not give us any session headers" if not user.last_login_at: e = events.FirstLogin(request, user) request.registry.notify(e) # Update user security details user.last_login_at = now() user.last_login_ip = request.client_addr if not location: location = get_config_route(request, 'horus.login_redirect') messages.add(request, kind="success", msg="You are now logged in.", msg_id="msg-you-are-logged-in") return HTTPFound(location=location, headers=headers)
def get_user(user_id, request:Request) -> User: """Extract the logged in user from the request object using Pyramid's authentication framework.""" # user_id = unauthenticated_userid(request) # TODO: Abstract this to its own service like in Warehouse? user_class = get_user_class(request.registry) if user_id is not None: user = user_class.get_by_id(request, user_id) # Check through conditions why this user would no longer be valid if user: if not user.can_login(): # User account disabled while in mid-session return None return user return None
def create( request, username: str, email: str, password: t.Optional[str]=None, source: str='command_line', admin: bool=False ) -> IUserModel: """Create a new site user from command line. :param request: :param username: Username, usually an email. :param email: User's email. :param password: Password. :param source: Source of this user, in here, command_line. :param admin: Set this user to admin. The first user is always implicitly admin. :return: Newly created user. """ User = get_user_class(request.registry) dbsession = request.dbsession u = dbsession.query(User).filter_by(email=email).first() if u is not None: return u u = User(email=email, username=username) dbsession.add(u) dbsession.flush() # Make sure u.user_data is set if password: user_registry = get_user_registry(request) user_registry.set_password(u, password) u.registration_source = source u.activated_at = now() request.registry.notify(UserCreated(request, u)) if admin: group = dbsession.query(Group).filter_by(name='admin').one_or_none() group.users.append(u) return u
def create(request, username, email, password=None, source="command_line", admin=False): """Create a new site user from command line. :param request: :param username: :param email: :param password: :param source: :param admin: Set this user to admin. The first user is always implicitly admin. :return: """ User = get_user_class(request.registry) dbsession = request.dbsession u = dbsession.query(User).filter_by(email=email).first() if u is not None: return u u = User(email=email, username=username) dbsession.add(u) dbsession.flush() # Make sure u.user_data is set if password: user_registry = get_user_registry(request) user_registry.set_password(u, password) u.registration_source = source u.activated_at = now() request.registry.notify(UserCreated(request, u)) if admin: group = dbsession.query(Group).filter_by(name="admin").one_or_none() group.users.append(u) return u
def get_or_create_user(request, email, password): User = get_user_class(request.registry) dbsession = request.dbsession u = dbsession.query(User).filter_by(email=email).first() if u is not None: return u u = User(email=email, username=email) dbsession.add(u) dbsession.flush() # Make sure u.user_data is set if password: user_registry = get_user_registry(request) user_registry.set_password(u, password) u.registration_source = "command_line" u.activated_at = now() request.registry.notify(UserCreated(request, u)) return u
def check_credentials(self, username, password): allow_email_auth = self.settings.get('horus.allow_email_auth', False) # Check login with username User = get_user_class(self.request.registry) user = User.get_user(self.request, username, password) # Check login with email if allow_email_auth and not user: user = User.get_by_email_password(self.request, username, password) if not user: raise AuthenticationFailure(_('Invalid username or password.')) if not self.allow_inactive_login and self.require_activation \ and not user.is_activated: raise AuthenticationFailure( _('Your account is not active, please check your e-mail.')) if not user.can_login(): raise AuthenticationFailure(_('This user account cannot log in at the moment.')) return user
def User(self): """Currently configured User SQLAlchemy model.""" return get_user_class(self.registry)
def User(self) -> t.Type[IUserModel]: """Currently configured User SQLAlchemy model. :return: Class implementing IUserModel. """ return get_user_class(self.registry)
def newsletter(context: Admin, request: Request): """Newsletter admin form.""" schema = NewsletterSend().bind(request=request) # Create a styled button with some extra Bootstrap 3 CSS classes b = deform.Button(name='process', title="Send", css_class="btn-block btn-lg btn-primary") form = deform.Form(schema, buttons=(b, ), resource_registry=ResourceRegistry(request)) secrets = get_secrets(request.registry) api_key = secrets.get("mailgun.api_key", "") domain = secrets.get("mailgun.domain", "") mailing_list = secrets.get("mailgun.mailing_list", "") preview_url = request.resource_url(context, "newsletter-preview") # TODO: Use user registry here User = get_user_class(request.registry) user_count = request.dbsession.query(User).count() state = NewsletterState(request) rendered_form = None # User submitted this form if request.method == "POST": if 'process' in request.POST: try: appstruct = form.validate(request.POST.items()) if appstruct["preview"]: send_newsletter( request, appstruct["subject"], preview_email=appstruct["email"], import_subscribers=appstruct["import_subscribers"]) messages.add(request, "Preview email sent.") else: send_newsletter( request, appstruct["subject"], import_subscribers=appstruct["import_subscribers"]) messages.add(request, "Newsletter sent.") return httpexceptions.HTTPFound(request.url) except MailgunError as e: # Do a form level error message exc = colander.Invalid(form.widget, "Could not sent newsletter:" + str(e)) form.widget.handle_error(form, exc) except deform.ValidationFailure as e: # Render a form version where errors are visible next to the fields, # and the submitted values are posted back rendered_form = e.render() else: # We don't know which control caused form submission return httpexceptions.HTTPBadRequest("Unknown form button pressed") # Render initial form # Default values for read only fields if rendered_form is None: rendered_form = form.render({ "api_key": api_key, "domain": domain, "mailing_list": mailing_list, }) # This loads widgets specific CSS/JavaScript in HTML code, # if form widgets specify any static assets. form.resource_registry.pull_in_resources(request, form) return locals()