def test_invalid_fetch_user(setup): usecase, created_domain_user = setup usecase: FetchUserUseCase created_domain_user: DomainUser # by invalid selector assert usecase.execute( fetch_by_selector="invalid_selector", fetch_by_data="invalid_data(doesn't matter)" ) == Failure( error= "Fetch selector should be within this list ['id', 'name', 'email']") # by id assert usecase.execute( fetch_by_selector="id", fetch_by_data="1") == Failure( error='There is no user with id 1 to be fetched') # by name assert usecase.execute( fetch_by_selector="name", fetch_by_data="invalid") == Failure( error='There is no user with name invalid to be fetched') # by email assert usecase.execute( fetch_by_selector="email", fetch_by_data="invalid") == Failure( error='There is no user with email invalid to be fetched')
def __wrapper(*args, **kwargs) -> Either[Failure, Any]: try: return func(*args, **kwargs) except ValidationError as ex: return Failure(error=str(ex).split("\n")[0].strip()) except Exception as ex: return Failure(error=str(ex))
def test_invalid_update_user(setup): _add_usecase, delete_usecase, created_domain_user = setup _add_usecase: AddUserUseCase delete_usecase: DeleteUserUseCase created_domain_user: DomainUser # by invalid selector assert delete_usecase.execute( delete_by_selector="invalid_selector", delete_by_data="invalid_data" ) == Failure( error= "Delete selector should be within this list ['id', 'name', 'email']") # by id assert delete_usecase.execute( delete_by_selector="id", delete_by_data="invalid") == Failure( error='There is no user with id invalid to be deleted') # by name assert delete_usecase.execute( delete_by_selector="name", delete_by_data="invalid") == Failure( error='There is no user with name invalid to be deleted') # by email assert delete_usecase.execute( delete_by_selector="email", delete_by_data="invalid") == Failure( error='There is no user with email invalid to be deleted')
def execute(self, *, username: str, age: int, password: str, email: Maybe[str], role: UserRole) -> Either[Failure, ApplicationUser]: domain_user_creation_status: Either[Failure, DomainUser] = create_user( name=username, age=age, password=password, email=email, role=role) if isinstance(domain_user_creation_status, Failure): return Failure(error=domain_user_creation_status.error) database_user_creation_status: Either[ Failure, ApplicationUser] = self.__persistence.persist_user( user=domain_user_creation_status) if isinstance(database_user_creation_status, Failure): return Failure(error=database_user_creation_status.error) return database_user_creation_status
def id(self, *, user_id: str) -> Either[Failure, ApplicationUser]: fetch_status: Maybe[ApplicationUser] = db["ids"].get(user_id) if isinstance(fetch_status, ApplicationUser): return fetch_status return Failure( error=f"There is no user with id {user_id} to be fetched")
def fetch_access_token(self, *, username: str) -> Either[Failure, AccessToken]: fetch_access_token_status = self.__db["tokens"].get(username, None) if fetch_access_token_status is not None: return fetch_access_token_status return Failure(error=f"There is no access token for user {username}")
def id(self, *, user_id: str) -> Either[Failure, Success]: fetch_status: Maybe[ApplicationUser] = db["ids"].get(user_id) if isinstance(fetch_status, ApplicationUser): self.__inner_delete_user(user=fetch_status) return Success() return Failure( error=f"There is no user with id {user_id} to be deleted")
def email(self, *, user_email: str) -> Either[Failure, Success]: user_id: Maybe[str] = db["emails"].get(user_email) if user_id is not None: self.__inner_delete_user(user=db["ids"][user_id]) return Success() return Failure( error= f"There is no user with email {user_email} to be deleted")
def name(self, *, user_name: str) -> Either[Failure, Success]: user_id: Maybe[str] = db["names"].get(user_name) if user_id is not None: self.__inner_delete_user(user=db["ids"][user_id]) return Success() return Failure( error= f"There is no user with name {user_name} to be deleted")
def email(self, *, user_email: str) -> Either[Failure, ApplicationUser]: user_id: str = db["emails"].get(user_email) if user_id is not None: user: ApplicationUser = db["ids"][user_id] return user return Failure( error= f"There is no user with email {user_email} to be fetched")
def name(self, *, user_name: str) -> Either[Failure, ApplicationUser]: user_id: str = db["names"].get(user_name) if user_id is not None: user: ApplicationUser = db["ids"][user_id] return user return Failure( error= f"There is no user with name {user_name} to be fetched")
def test_invalid_update_user(setup): usecase, created_domain_user = setup usecase: UpdateUserUseCase created_domain_user: DomainUser updated_domain_user: DomainUser = create_user( name="newname", age=created_domain_user.age + 10, password=created_domain_user.password, email=created_domain_user.email, role=created_domain_user.role) # by invalid selector assert usecase.execute( update_by_selector="invalid_selector", update_by_data="invalid_data", updated_user=updated_domain_user ) == Failure( error= "Update selector should be within this list ['id', 'name', 'email']") # by id assert usecase.execute( update_by_selector="id", update_by_data="invalid", updated_user=updated_domain_user) == Failure( error='There is no user with id invalid to be updated') # by name assert usecase.execute( update_by_selector="name", update_by_data="invalid", updated_user=updated_domain_user) == Failure( error='There is no user with name invalid to be updated') # by email assert usecase.execute( update_by_selector="email", update_by_data="invalid", updated_user=updated_domain_user) == Failure( error='There is no user with email invalid to be updated')
def test_invalid_add_user(setup): name = "test" age = 26 password = "******" email = "*****@*****.**" role = UserRole.USER usecase: AddUserUseCase = setup # other variety of invalid data is covered on the user_tests itself assert usecase.execute( username=name, age=age, password=password, email=email, role=role) == Failure(error='password should be stronger.')
def email( self, *, user_email: str, updated_user: DomainUser ) -> Either[Failure, ApplicationUser]: user_id: Maybe[str] = db["emails"].get(user_email) if user_id is not None: db["ids"][ user_id] = PersistenceInterface.from_domain_user_to_database_user( user=updated_user, user_id=user_id) return db["ids"][user_id] return Failure( error= f"There is no user with email {user_email} to be updated")
def persist_user(self, *, user: DomainUser) -> Either[Failure, ApplicationUser]: if self.__db["names"].get(user.name, None) is not None: return Failure( error= f"Username {user.name} is already exist, please use a different name." ) persisted_user = PersistenceInterface.from_domain_user_to_database_user( user=user, user_id=str(self.__last_id)) self.__db['ids'][str(self.__last_id)] = persisted_user self.__db['names'][user.name] = str(self.__last_id) self.__db['emails'][user.email] = str(self.__last_id) self.__last_id += 1 return persisted_user
def execute(self, *, fetch_by_selector: str, fetch_by_data: str) -> Either[Failure, ApplicationUser]: if fetch_by_selector not in _fetch_selectors: return Failure(error=f"Fetch selector should be within this list {_fetch_selectors}") selector_mapping = { "id": self.__persistence.fetch_user_by.id, "name": self.__persistence.fetch_user_by.name, "email": self.__persistence.fetch_user_by.email } fetch_user_status: Either[Failure, ApplicationUser] = selector_mapping[fetch_by_selector]( **{f"user_{fetch_by_selector}": fetch_by_data} ) return fetch_user_status
def persist_access_token(self, *, username: str, password: str) -> Either[Failure, AccessToken]: fetch_user_status = self._fetch_user_by().name(user_name=username) if isinstance(fetch_user_status, Failure): return fetch_user_status if fetch_user_status.password != password: return Failure(error=f"Invalid password for user {username}") # will make the generation better and generic later ;) access_token = AccessToken( token=encode({ "username": username }, password, algorithm='HS256').decode("utf-8")) self.__db["tokens"][username] = access_token return access_token
def id(self, *, user_id: str, updated_user: DomainUser ) -> Either[Failure, ApplicationUser]: fetch_status: Maybe[ApplicationUser] = db["ids"].get(user_id) if isinstance(fetch_status, ApplicationUser): db["ids"][ fetch_status. id] = PersistenceInterface.from_domain_user_to_database_user( user=updated_user, user_id=fetch_status.id) access_token_status = db["tokens"].get( fetch_status.name, None) if access_token_status is not None: del db["tokens"][fetch_status.name] db["tokens"][updated_user.name] = access_token_status return db["ids"][fetch_status.id] return Failure( error=f"There is no user with id {user_id} to be updated")
def execute(self, *, delete_by_selector: str, delete_by_data: str) -> Either[Failure, Success]: if delete_by_selector not in _delete_selectors: return Failure( error= f"Delete selector should be within this list {_delete_selectors}" ) selector_mapping = { "id": self.__persistence.delete_user_by.id, "name": self.__persistence.delete_user_by.name, "email": self.__persistence.delete_user_by.email } delete_user_status: Either[ Failure, Success] = selector_mapping[delete_by_selector]( **{ f"user_{delete_by_selector}": delete_by_data }) return delete_user_status
def execute(self, *, update_by_selector: str, update_by_data: str, updated_user: DomainUser) -> Either[Failure, ApplicationUser]: if update_by_selector not in _update_selectors: return Failure( error= f"Update selector should be within this list {_update_selectors}" ) selector_mapping = { "id": self.__persistence.update_user_by.id, "name": self.__persistence.update_user_by.name, "email": self.__persistence.update_user_by.email } update_user_status: Either[ Failure, ApplicationUser] = selector_mapping[update_by_selector]( **{ f"user_{update_by_selector}": update_by_data, "updated_user": updated_user }) return update_user_status
async def delete_user( *, delete_user_usecase: DeleteUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase, request: Request) -> Callable[..., JsonEntity.of(_type=_A)]: username = request.headers.get("username", None) token = request.headers.get("access-token", None) if username is not None and token is not None: current_logged_user_fetch_status = fetch_user_usecase.execute( fetch_by_selector='name', fetch_by_data=username) access_token_status = fetch_access_token_usecase.execute( username=username) if isinstance(access_token_status, Failure): return JSONResponse(access_token_status.as_dict(), 401) if access_token_status.token != token: return JSONResponse( Failure(error=f"Invalid access token for the user {username}"). as_dict(), 401) if isinstance(current_logged_user_fetch_status, ApplicationUser): params = request.query_params if len(params) > 0: selector_key = list(params.keys())[0] selector_value = params[selector_key] if current_logged_user_fetch_status.role.name == UserRole.ADMIN.name: pass elif current_logged_user_fetch_status.role.name == UserRole.USER.name: permission_error_json = JSONResponse(Failure( error= "Your current user permission is not satisfying this operation." ).as_dict(), status_code=401) if selector_key == "id": if current_logged_user_fetch_status.id != selector_value: return permission_error_json if selector_key == "name": if current_logged_user_fetch_status.name != selector_value: return permission_error_json if selector_key == "email": if current_logged_user_fetch_status.email != selector_value: return permission_error_json delete_user_status = delete_user_usecase.execute( delete_by_selector=selector_key, delete_by_data=selector_value) return JSONResponse(delete_user_status.as_dict(), status_code=200) return JSONResponse(Failure( error= "You should provide params as one of these [id, name, email]"). as_dict(), status_code=400) return JSONResponse(current_logged_user_fetch_status.as_dict(), 401) return JSONResponse( Failure( error= "You should provide username and access-token into the headers."). as_dict(), 401)
def test_invalid_user_creation(): name: str = "name" age: int = 26 email: str = "*****@*****.**" password: str = "StrongPassw0rd" # empty name assert create_user( name="", age=age, password=password, email=email, role=UserRole.USER ) == Failure(error="name can't be empty.\n" "name should be at least 2 characters.\n" "name should be alpha or alpha numeric.") # one char name assert create_user( name="a", age=age, password=password, email=email, role=UserRole.USER ) == Failure(error='name should be at least 2 characters.') # less than 16 age <just a number to have limit in the app :D> assert create_user( name=name, age=15, password=password, email=email, role=UserRole.USER ) == Failure(error='age should be between 16 and 150.') # more than 150 age <just a number to have limit in the app :D> assert create_user( name=name, age=151, password=password, email=email, role=UserRole.USER ) == Failure(error='age should be between 16 and 150.') # weak password assert create_user( name=name, age=26, password="******", email=email, role=UserRole.USER ) == Failure(error='password should be stronger.') # invalid email assert create_user( name=name, age=26, password=password, email="invalid_email", role=UserRole.USER ) == Failure(error='email should be a valid one.')
async def update_user(*, update_user_usecase: UpdateUserUseCase, fetch_user_usecase: FetchUserUseCase, fetch_access_token_usecase: FetchAccessTokenUseCase, json_schema: Dict[str, Any], json_schema_validator: JsonValidatorInterface, request: Request) -> Callable[..., JsonEntity.of(_type=_A)]: # simple validation for now, will be better later ;) username = request.headers.get("username", None) token = request.headers.get("access-token", None) if username is not None and token is not None: current_logged_user_fetch_status = fetch_user_usecase.execute( fetch_by_selector='name', fetch_by_data=username ) access_token_status = fetch_access_token_usecase.execute( username=username ) if isinstance(access_token_status, Failure): return JSONResponse(access_token_status.as_dict(), 401) if access_token_status.token != token: return JSONResponse(Failure(error=f"Invalid access token for the user {username}").as_dict(), 401) if isinstance(current_logged_user_fetch_status, ApplicationUser): json_data: Dict[Any, Any] = await request.json() json_validation_status: Either[Failure, Success] = json_schema_validator.validate( schema=json_schema, data=json_data ) if isinstance(json_validation_status, Success): # will make this better later ;) json_data["updated_user"]["role"] = UserRole.USER create_domain_user_status = create_user( **json_data["updated_user"] ) if isinstance(create_domain_user_status, Failure): return JSONResponse(create_domain_user_status.as_dict()) if current_logged_user_fetch_status.role.name == UserRole.ADMIN.name: pass elif current_logged_user_fetch_status.role.name == UserRole.USER.name: if current_logged_user_fetch_status.name != username: return JSONResponse( Failure( error="Your current user permission is not satisfying this operation." ).as_dict(), status_code=401 ) update_user_status = update_user_usecase.execute( update_by_selector=json_data["update_by_selector"], update_by_data=json_data["update_by_data"], updated_user=create_domain_user_status ) if isinstance(update_user_status, ApplicationUser): user_json = from_application_user_to_json_user( application_user=update_user_status ) return JSONResponse(user_json.as_dict(), status_code=200) return JSONResponse(update_user_status.as_dict(), status_code=400) return JSONResponse(json_validation_status.as_dict(), status_code=400) return JSONResponse(current_logged_user_fetch_status.as_dict(), 401) return JSONResponse( Failure(error="You should provide username and access-token into the headers.").as_dict(), 401 )