Beispiel #1
0
    def test_invalid_request_already_submitted(
        self,
        fake_new_account_request,
        fake_credentials,
        mock_valid_calnet_uid,
        session,
    ):
        # test where username has already been requested
        with mock.patch('ocflib.account.submission.username_pending',
                        return_value=True):
            errors, warnings = validate_request(
                fake_new_account_request,
                fake_credentials,
                session,
            )
        assert errors

        # test where this user (calnet/callink oid) has already submitted a request
        with mock.patch('ocflib.account.submission.user_has_request_pending',
                        return_value=True):
            errors, warnings = validate_request(
                fake_new_account_request,
                fake_credentials,
                session,
            )
        assert errors
    def test_invalid_request_already_submitted(
        self, fake_new_account_request, fake_credentials, mock_valid_calnet_uid, session
    ):
        # test where username has already been requested
        with mock.patch("ocflib.account.submission.username_pending", return_value=True):
            errors, warnings = validate_request(fake_new_account_request, fake_credentials, session)
        assert errors

        # test where this user (calnet/callink oid) has already submitted a request
        with mock.patch("ocflib.account.submission.user_has_request_pending", return_value=True):
            errors, warnings = validate_request(fake_new_account_request, fake_credentials, session)
        assert errors
Beispiel #3
0
    def create_account(request):
        # TODO: docstring
        # lock account creation for up to 5 minutes
        r = redis.from_url(credentials.redis_uri)
        lock = r.lock('ocflib.account.submission.create_account', timeout=60 * 5)
        try:
            if not lock.acquire(blocking=True, blocking_timeout=60 * 5):
                raise RuntimeError('Couldn\'t lock account creation, abandoning.')

            # status reporting
            status = []

            class report_status:

                def __init__(self, *args):
                    if len(args) == 1:
                        self(*args)
                    else:
                        self.start, self.stop, self.task = args

                def __call__(self, line):
                    status.append(line)
                    create_account.update_state(meta={'status': status})

                def __enter__(self, *args):
                    self(self.start + ' ' + self.task)

                def __exit__(self, *args):
                    self(self.stop + ' ' + self.task)

            with report_status('Validating', 'Validated', 'request'), \
                    get_session() as session:
                errors, warnings = validate_request(request, credentials, session)

            if errors:
                send_rejected_mail(request, str(errors))
                return NewAccountResponse(
                    status=NewAccountResponse.REJECTED,
                    errors=(errors + warnings),
                )

            # actual account creation
            kwargs = {}
            known_uid = r.get('known_uid')
            if known_uid:
                kwargs['known_uid'] = int(known_uid)
            new_uid = real_create_account(request, credentials, report_status, **kwargs)
            r.set('known_uid', new_uid)

            dispatch_event('ocflib.account_created', request=request.to_dict())
            return NewAccountResponse(
                status=NewAccountResponse.CREATED,
                errors=[],
            )
        finally:
            try:
                lock.release()
            except LockError:
                pass
Beispiel #4
0
    def create_account(request):
        # TODO: docstring
        # lock account creation for up to 5 minutes
        r = redis.from_url(credentials.redis_uri)
        lock = r.lock('ocflib.account.submission.create_account', timeout=60 * 5)
        try:
            if not lock.acquire(blocking=True, blocking_timeout=60 * 5):
                raise RuntimeError('Couldn\'t lock account creation, abandoning.')

            # status reporting
            status = []

            class report_status:

                def __init__(self, *args):
                    if len(args) == 1:
                        self(*args)
                    else:
                        self.start, self.stop, self.task = args

                def __call__(self, line):
                    status.append(line)
                    create_account.update_state(meta={'status': status})

                def __enter__(self, *args):
                    self(self.start + ' ' + self.task)

                def __exit__(self, *args):
                    self(self.stop + ' ' + self.task)

            with report_status('Validating', 'Validated', 'request'), \
                    get_session() as session:
                errors, warnings = validate_request(request, credentials, session)

            if errors:
                send_rejected_mail(request, str(errors))
                return NewAccountResponse(
                    status=NewAccountResponse.REJECTED,
                    errors=(errors + warnings),
                )

            # actual account creation
            kwargs = {}
            known_uid = r.get('known_uid')
            if known_uid:
                kwargs['known_uid'] = int(known_uid)
            new_uid = real_create_account(request, credentials, report_status, **kwargs)
            r.set('known_uid', new_uid)

            dispatch_event('ocflib.account_created', request=request.to_dict())
            return NewAccountResponse(
                status=NewAccountResponse.CREATED,
                errors=[],
            )
        finally:
            try:
                lock.release()
            except LockError:
                pass
Beispiel #5
0
    def validate_then_create_account(request):
        """First run validation, then create.

        This is handy because this task runs quickly, so you can wait for it to
        finish (unlike create_account, which is slow and uses a global lock).

        If this task succeeds, it will launch create_account, and returns you
        the new task ID.

        Assuming this task succeeds, it is almost certain that create_account
        will succeed. However, create_account runs validation again, so it is
        possible for it to fail (just exceedingly unlikely).
        """
        # TODO: docstring is not 100% correct
        with get_session() as session:
            errors, warnings = validate_request(request, credentials, session)
        if errors:
            # Fatal errors; cannot be bypassed, even with staff approval
            return NewAccountResponse(
                status=NewAccountResponse.REJECTED,
                errors=(errors + warnings),
            )
        elif warnings:
            # Non-fatal errors; the frontend can choose to create the account
            # anyway, submit the account for staff approval, or get a response
            # with a list of warnings for further inspection.
            if request.handle_warnings == NewAccountRequest.WARNINGS_SUBMIT:
                stored_request = StoredNewAccountRequest.from_request(
                    request, str(warnings))

                try:
                    with get_session() as session:
                        session.add(stored_request)  # TODO: error handling
                        session.commit()
                except sqlalchemy.exc.IntegrityError:
                    # If there's an integrity constraint, it's okay -- the
                    # account was already submitted, so we can still return a
                    # "pending" response.
                    pass
                else:
                    dispatch_event(
                        'ocflib.account_submitted',
                        request=dict(request.to_dict(), reasons=warnings),
                    )

                return NewAccountResponse(
                    status=NewAccountResponse.PENDING,
                    errors=warnings,
                )
            elif request.handle_warnings == NewAccountRequest.WARNINGS_WARN:
                return NewAccountResponse(
                    status=NewAccountResponse.FLAGGED,
                    errors=warnings,
                )

        return create_account.delay(request).id
Beispiel #6
0
 def test_valid_request(
     self,
     fake_new_account_request,
     fake_credentials,
     mock_valid_calnet_uid,
     session,
 ):
     assert validate_request(
         fake_new_account_request,
         fake_credentials,
         session,
     ) == ([], [])
Beispiel #7
0
 def test_valid_request(
     self,
     fake_new_account_request,
     fake_credentials,
     mock_valid_calnet_uid,
     session,
 ):
     assert validate_request(
         fake_new_account_request,
         fake_credentials,
         session,
     ) == ([], [])
Beispiel #8
0
 def test_invalid_request_error(
     self,
     fake_new_account_request,
     fake_credentials,
     mock_valid_calnet_uid,
     attrs,
     session,
 ):
     errors, warnings = validate_request(
         fake_new_account_request._replace(**attrs),
         fake_credentials,
         session,
     )
     assert errors
Beispiel #9
0
 def test_invalid_request_error(
     self,
     fake_new_account_request,
     fake_credentials,
     mock_valid_calnet_uid,
     attrs,
     session,
 ):
     errors, warnings = validate_request(
         fake_new_account_request._replace(**attrs),
         fake_credentials,
         session,
     )
     assert errors
Beispiel #10
0
    def validate_then_create_account(request):
        """First run validation, then create.

        This is handy because this task runs quickly, so you can wait for it to
        finish (unlike create_account, which is slow and uses a global lock).

        If this task succeeds, it will launch create_account, and returns you
        the new task ID.

        Assuming this task succeeds, it is almost certain that create_account
        will succeed. However, create_account runs validation again, so it is
        possible for it to fail (just exceedingly unlikely).
        """
        # TODO: docstring is not 100% correct
        with get_session() as session:
            errors, warnings = validate_request(request, credentials, session)
        if errors:
            # Fatal errors; cannot be bypassed, even with staff approval
            return NewAccountResponse(
                status=NewAccountResponse.REJECTED,
                errors=(errors + warnings),
            )
        elif warnings:
            # Non-fatal errors; the frontend can choose to create the account
            # anyway, submit the account for staff approval, or get a response
            # with a list of warnings for further inspection.
            if request.handle_warnings == NewAccountRequest.WARNINGS_SUBMIT:
                stored_request = StoredNewAccountRequest.from_request(request, str(warnings))

                with get_session() as session:
                    session.add(stored_request)  # TODO: error handling
                    session.commit()

                dispatch_event(
                    'ocflib.account_submitted',
                    request=dict(request.to_dict(), reasons=warnings),
                )
                return NewAccountResponse(
                    status=NewAccountResponse.PENDING,
                    errors=warnings,
                )
            elif request.handle_warnings == NewAccountRequest.WARNINGS_WARN:
                return NewAccountResponse(
                    status=NewAccountResponse.FLAGGED,
                    errors=warnings,
                )

        return create_account.delay(request).id
Beispiel #11
0
    def create_account(request):
        # TODO: docstring
        # lock account creation for up to 5 minutes
        r = redis.from_url(credentials.redis_uri)
        lock = r.lock('ocflib.account.submission.create_account', timeout=60 * 5)
        try:
            if not lock.acquire(blocking=True, blocking_timeout=60 * 5):
                raise RuntimeError('Couldn\'t lock account creation, abandoning.')

            # status reporting
            status = []

            def _report_status(line):
                """Update task status by adding the given line."""
                status.append(line)
                create_account.update_state(meta={'status': status})

            @contextmanager
            def report_status(start, stop, task):
                _report_status(start + ' ' + task)
                yield
                _report_status(stop + ' ' + task)

            with report_status('Validating', 'Validated', 'request'), \
                    get_session() as session:
                errors, warnings = validate_request(request, credentials, session)

            if errors:
                send_rejected_mail(request, str(errors))
                return NewAccountResponse(
                    status=NewAccountResponse.REJECTED,
                    errors=(errors + warnings),
                )

            # actual account creation
            real_create_account(request, credentials, report_status)
            dispatch_event('ocflib.account_created', request=request.to_dict())
            return NewAccountResponse(
                status=NewAccountResponse.CREATED,
                errors=[],
            )
        finally:
            try:
                lock.release()
            except LockError:
                pass