Esempio n. 1
0
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"
Esempio n. 2
0
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"
Esempio n. 3
0
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
Esempio n. 4
0
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 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"
Esempio n. 7
0
    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 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"
Esempio n. 9
0
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()))
Esempio n. 10
0
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
Esempio n. 11
0
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()))
Esempio n. 12
0
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")
Esempio n. 13
0
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 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 = "******"
Esempio n. 15
0
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 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")
Esempio n. 17
0
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")
Esempio n. 18
0
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 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 = "******"
Esempio n. 20
0
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))
Esempio n. 21
0
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")
Esempio n. 22
0
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)
Esempio n. 23
0
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
Esempio n. 24
0
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
Esempio n. 25
0
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
Esempio n. 26
0
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
Esempio n. 27
0
    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
Esempio n. 28
0
 def User(self):
     """Currently configured User SQLAlchemy model."""
     return get_user_class(self.registry)
Esempio n. 29
0
    def User(self) -> t.Type[IUserModel]:
        """Currently configured User SQLAlchemy model.

        :return: Class implementing IUserModel.
        """
        return get_user_class(self.registry)
Esempio n. 30
0
 def User(self):
     """Currently configured User SQLAlchemy model."""
     return get_user_class(self.registry)
Esempio n. 31
0
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()