async def _authorize_user(cmd: Dict[str, Any]) -> str: res = await container().get(TokenGeneratorService)( **{ 'email': UserEmailMother.create(cmd['email']), 'password': cmd['password'], }) return f'{res.token_type} {res.access_token}'
def test_user_password_forgotten_event_mapper() -> None: mapper = UserPasswordForgottenEventMapper() msg = UserPasswordForgotten( UserPasswordForgotten.Attributes( UserIdMother.random(), UserEmailMother.random(), UserRefreshTokenMother.random(), UserRefreshTokenExpirationInMother.random(), )) assert mapper.belongs_to(msg) assert mapper.service_name == 'project.account' assert mapper.event_name == 'users.password_forgotten' data = { 'id': msg.attributes.id.value(), 'email': msg.attributes.email.value(), 'refresh_token': msg.attributes.refresh_token.value(), 'refresh_token_expiration_in': msg.attributes.refresh_token_expiration_in.value(), } evt: UserPasswordForgotten = mapper.decode(data) assert evt.attributes.id.value() == data['id'] assert evt.attributes.email.value() == data['email'] assert evt.attributes.refresh_token.value() == data['refresh_token'] assert evt.attributes.refresh_token_expiration_in.value( ) == data['refresh_token_expiration_in'] assert mapper.map_attributes(msg.attributes) == data
def random_with_forgotten_password(cls) -> User: return cls.create( UserIdMother.random(), UserEmailMother.random(), UserPasswordMother.random(), UserRefreshTokenMother.random(), UserRefreshTokenExpirationInMother.random(), )
async def test_find_user_get_controller() -> None: async with APIContext() as ctx: cmd = { 'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value(), } ctx.token = await UserContext.an_existent_authenticated_user_with( cmd=cmd) await ctx.i_send_json_request(method='GET', url=f'/api/protected/users/{cmd["id"]}') await ctx.the_response_status_code_should_be(status_code=200) await ctx.the_response_content_should_be(data=cmd)
async def test_register_user_put_controller() -> None: async with APIContext() as ctx: await ctx.i_send_json_request( method='PUT', url='/api/public/users', data={ 'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value(), 'password': UserPasswordMother.random().value(), }, ) await ctx.the_response_status_code_should_be(status_code=201) await ctx.the_response_content_should_be(data=None)
def setup(self) -> None: self._mock_command_bus = mock(CommandBus, ['dispatch']) self._sut = NotifyUserRegisteredOnUserRegisteredEventHandler( self._mock_command_bus) self._kwargs = { 'events': [ UserRegistered( UserRegistered.Attributes( UserIdMother.random(), UserEmailMother.random(), )), ], }
def from_password_and_forgotten_password( cls, user_password: UserPassword, user_refresh_token: UserRefreshToken, user_refresh_token_expiration_in: UserRefreshTokenExpirationIn, ) -> User: return cls.create( UserIdMother.random(), UserEmailMother.random(), user_password, user_refresh_token, user_refresh_token_expiration_in, )
async def _register_user(cls, cmd: Dict[str, Any], do_authorize: bool) -> Optional[str]: plain_email = (UserEmailMother.create(cmd['email']) if 'email' in cmd else UserEmailMother.random()).value() plain_password = cmd[ 'password'] if 'password' in cmd else UserPasswordMother.random( ).value() await container().get(CommandBus).dispatch( RegisterUserCommand( **{ 'id': (UserIdMother.create(cmd['id']) if 'id' in cmd else UserIdMother.random()).value(), 'email': plain_email, 'password': plain_password, })) if do_authorize: return await cls._authorize_user(cmd={ 'email': plain_email, 'password': plain_password }) return None
async def test_generate_token_fails_when_user_not_found(self) -> None: self._mock_auth_repository.find.side_effect = UserNotFoundError.create( ) kwargs = { 'email': UserEmailMother.random(), 'password': '******', } with pytest.raises(UserUnauthorizedError): await self._sut(**kwargs) self._mock_auth_repository.find.assert_called_once_with( kwargs['email']) self._mock_token_factory.generate.assert_not_called()
async def test_register_successfully(self) -> None: self._mock_user_repository.search.return_value = None self._mock_user_repository.save_and_publish.return_value = None kwargs = { 'user_id': UserIdMother.random(), 'email': UserEmailMother.random(), 'password': UserPasswordMother.random(), } await self._sut(**kwargs) self._mock_user_repository.search.assert_called_once_with( kwargs['user_id']) self._mock_user_repository.save_and_publish.assert_called_once()
def test_user_password_changed_event_mapper() -> None: mapper = UserPasswordChangedEventMapper() msg = UserPasswordChanged( UserPasswordChanged.Attributes(UserIdMother.random(), UserEmailMother.random())) assert mapper.belongs_to(msg) assert mapper.service_name == 'project.account' assert mapper.event_name == 'users.password_changed' data = { 'id': msg.attributes.id.value(), 'email': msg.attributes.email.value(), } evt: UserPasswordChanged = mapper.decode(data) assert evt.attributes.id.value() == data['id'] assert evt.attributes.email.value() == data['email'] assert mapper.map_attributes(msg.attributes) == data
async def test_forget_user_password_post_controller() -> None: async with APIContext() as ctx: cmd = { 'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value(), 'password': UserPasswordMother.random().value(), } await UserContext.an_existent_user_with(cmd=cmd) await ctx.i_send_json_request( method='POST', url='/api/public/users/forget-password', data={ 'email': cmd['email'], }, ) await ctx.the_response_status_code_should_be(status_code=200) await ctx.the_response_content_should_be(data=None)
async def test_change_user_password_post_controller() -> None: async with APIContext() as ctx: cmd = { 'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value(), 'password': UserPasswordMother.random().value(), } ctx.token = await UserContext.an_existent_authenticated_user_with( cmd=cmd) await ctx.i_send_json_request( method='POST', url='/api/protected/users/change-password', data={ 'id': cmd['id'], 'old_password': cmd['password'], 'new_password': UserPasswordMother.random().value(), }, ) await ctx.the_response_status_code_should_be(status_code=200) await ctx.the_response_content_should_be(data=None)
async def test_notify_user_registered_successfully(self) -> None: async with MailContext(user=self._cnf.host_user, ui_host=self._cnf.host, ui_port=self._email_ui_port) as ctx: user_id = UserIdMother.random() user_email = UserEmailMother.random() await self._sut.notify_user_registered(user_id, user_email) await ctx.i_send_get_request(user_email=user_email.value()) def assert_response(headers: Dict[str, Any], body: Optional[str]) -> bool: assert headers['X-UserId'][0] == user_id.value() assert headers['From'][0] == self._cnf.from_user assert headers['Subject'][0] == 'Welcome to Project' assert headers['To'][0] == user_email.value() assert body == f'Welcome {user_email.value()}' return True await ctx.the_response_content_should(callback=assert_response)
async def test_reset_user_password_post_controller() -> None: async with APIContext() as ctx: cmd = { 'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value(), 'password': UserPasswordMother.random().value(), } ctx.token = await UserContext.an_existent_authenticated_user_with(cmd=cmd) await UserContext.forget_user_password_with_email(cmd['email']) full_user = await UserContext.find_full_user_with_id(cmd['id']) await ctx.i_send_json_request( method='POST', url='/api/public/users/reset-password', data={ 'email': cmd['email'], 'refresh_token': full_user.refresh_token, 'new_password': UserPasswordMother.random().value(), }, ) await ctx.the_response_status_code_should_be(status_code=200) await ctx.the_response_content_should_be(data=None)
async def test_user_password_forgotten_successfully(self) -> None: async with MailContext(user=self._cnf.host_user, ui_host=self._cnf.host, ui_port=self._email_ui_port) as ctx: user_id = UserIdMother.random() user_email = UserEmailMother.random() refresh_token = UserRefreshTokenMother.random() await self._sut.notify_user_password_forgotten( user_id, user_email, refresh_token) await ctx.i_send_get_request(user_email=user_email.value()) def assert_response(headers: Dict[str, Any], body: Optional[str]) -> bool: assert headers['X-UserId'][0] == user_id.value() assert headers['From'][0] == self._cnf.from_user assert headers['Subject'][ 0] == 'Project - Here you have your reset password code' assert headers['To'][0] == user_email.value() assert body == f'Here you have your reset password code: {refresh_token.value()}' return True await ctx.the_response_content_should(callback=assert_response)
async def test_token_auth_post_controller() -> None: async with APIContext() as ctx: cmd = { 'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value(), 'password': UserPasswordMother.random().value(), } await UserContext.an_existent_user_with(cmd=cmd) await ctx.i_send_x_www_form_urlencoded_request( method='POST', url='/api/public/users/auth', data={ 'grant_type': 'password', 'username': cmd['email'], 'password': cmd['password'], }, ) await ctx.the_response_status_code_should_be(status_code=200) await ctx.the_response_content_should_be_contains( data={ 'user_id': cmd['id'], 'token_type': 'Bearer', } )
def from_password(cls, user_password: UserPassword) -> User: return cls.create(UserIdMother.random(), UserEmailMother.random(), user_password, None, None)
def random(cls) -> User: return cls.create(UserIdMother.random(), UserEmailMother.random(), UserPasswordMother.random(), None, None)
def from_id(cls, user_id: UserId) -> User: return cls.create(user_id, UserEmailMother.random(), UserPasswordMother.random(), None, None)
def test_auth_guard_fails_when_user_unauthorized() -> None: with pytest.raises(UserUnauthorizedError): auth_guard( UserIdMother.random().value(), UserAuth(**{'id': UserIdMother.random().value(), 'email': UserEmailMother.random().value()}), )
async def _forget_user_password(cmd: Dict[str, Any]) -> None: await container().get(CommandBus).dispatch( ForgetUserPasswordCommand( **{ 'email': UserEmailMother.create(cmd['email']).value(), }))
def test_register() -> None: user = User.register(UserIdMother.random(), UserEmailMother.random(), UserPasswordMother.random()) events = user.pull_aggregate_events() assert len(events) == 1 assert isinstance(events[0], UserRegistered)
async def test_mongodb_user_repository( mongodb_disposable_connection: MongoDBConnection) -> None: sut = MongoDBUserRepository( mongodb_disposable_connection, MongoDBUserMapper(), InternalEventPublisher(SimpleEventBus([])), ) user = UserMother.random() user_id = user.id() assert await sut.search(user_id) is None await sut.save_and_publish(user) user = await sut.find(user_id) assert user.id().value() == user_id.value() await sut.save_and_publish(user) users_ids = [user.id().value() for user in await sut.find_all()] assert user_id.value() in users_ids user = await sut.find_email(user.email()) assert user.id().value() == user_id.value() user = await sut.find_id_and_email(user_id, user.email()) assert user.id().value() == user_id.value() await sut.delete_and_publish(user) with pytest.raises(UserNotFoundError): await sut.find(user_id) with pytest.raises(UserNotFoundError): await sut.find_email(UserEmailMother.random()) with pytest.raises(UserNotFoundError): await sut.find_id_and_email(user_id, UserEmailMother.random()) with pytest.raises(UserNotFoundError): await sut.find_email_and_refresh_token(UserEmailMother.random(), UserRefreshTokenMother.random()) user_mock = Mock() user_mock.id.side_effect = [lambda: raise_(Exception()), user_id] with pytest.raises(UserNotSavedError): await sut.save_and_publish(user_mock) user_mock = Mock() user_mock.id.side_effect = [lambda: raise_(Exception()), user_id] with pytest.raises(UserNotDeletedError): await sut.delete_and_publish(user_mock) user = UserMother.random_with_forgotten_password() await sut.save_and_publish(user) user_response = await sut.find_email_and_refresh_token( user.email(), user.refresh_token()) assert user.id().value() == user_response.id().value() assert user.refresh_token().value() == user_response.refresh_token().value( ) assert user.refresh_token_expiration_in().value( ) == user_response.refresh_token_expiration_in().value() await sut.delete_and_publish(user_response)