async def get_alternate_accounts( self, user: User, current_account: Account ) -> List[Account]: _, UserTable = await user.to_alchemy_obj() _, AccountTable = await current_account.to_alchemy_obj() _join = UserTable.__table__.join( UserHasAccount, UserTable.id == UserHasAccount.c.user_id, isouter=True, ).join( AccountTable.__table__, AccountTable.id == UserHasAccount.c.account_id, isouter=True, ) async with AsgardDBSession() as s: accounts = ( await s.query(AccountTable) .join(_join) .filter(UserTable.tx_email == user.email) .filter(AccountTable.id != current_account.id) .all() ) all_acc = [await Account.from_alchemy_obj(acc) for acc in accounts] return all_acc
async def get_user_by_id(self, user_id: int) -> Optional[User]: try: async with AsgardDBSession() as s: user = await s.query(UserDB).filter(UserDB.id == user_id).one() return await User.from_alchemy_obj(user) except NoResultFound: return None
async def get_accounts(self) -> List[Account]: async with AsgardDBSession() as s: result: List[AccountDB] = await s.query(AccountDB).all() accounts: List[Account] = [ await Account.from_alchemy_obj(item) for item in result ] return accounts
async def add_user(self, user: User, account: Account) -> None: if not await account.user_has_permission(user): async with AsgardDBSession() as s: insert: Insert = UserHasAccount.insert().values( user_id=user.id, account_id=account.id ) await s.execute(insert)
async def get_users_from_account(self, account: Account) -> List[User]: async with AsgardDBSession() as s: users: List[UserDB] = (await s.query(UserDB).join( UserHasAccount.join(UserDB, UserHasAccount.c.user_id == UserDB.id) ).filter(UserHasAccount.c.account_id == account.id).all()) return [await User.from_alchemy_obj(u) for u in users]
async def remove_user(self, user: User, account: Account) -> None: async with AsgardDBSession() as s: delete: Delete = ( UserHasAccount.delete() .where(UserHasAccount.c.account_id == account.id) .where(UserHasAccount.c.user_id == user.id) ) await s.execute(delete)
async def get_account_by_id(self, acc_id: int) -> Optional[Account]: try: async with AsgardDBSession() as s: result: AccountDB = (await s.query(AccountDB).filter( AccountDB.id == acc_id).one()) return await Account.from_alchemy_obj(result) except NoResultFound: return None
async def test_user_trasnform_from_alchemy_object(self): user = User(**USER_WITH_MULTIPLE_ACCOUNTS_DICT) _, UserDB = await user.to_alchemy_obj() async with AsgardDBSession() as s: user_db = (await s.query(UserDB).filter( UserDB.id == USER_WITH_MULTIPLE_ACCOUNTS_ID).one()) user = await User.from_alchemy_obj(user_db) self.assertEqual(user.name, USER_WITH_MULTIPLE_ACCOUNTS_NAME) self.assertEqual(user.email, USER_WITH_MULTIPLE_ACCOUNTS_EMAIL)
async def get_users(self) -> List[User]: """ Lista todos os usuários do sistema, independente de qual conta esses usuários estão vinculados """ async with AsgardDBSession() as s: return [ await User.from_alchemy_obj(u) for u in await s.query(UserDB).all() ]
async def update_user(self, user: User) -> User: async with AsgardDBSession() as s: user_db, userTable = await user.to_alchemy_obj() update = (userTable.__table__.update().where( userTable.id == user.id).values(tx_name=user.name, tx_email=user.email)) try: await s.execute(update) except psycopg2.IntegrityError as e: raise DuplicateEntity(e.pgerror) return user
async def delete_user(self, user: User) -> User: async with AsgardDBSession() as s: _, userTable = await user.to_alchemy_obj() delete_acc_relation = UserHasAccount.delete().where( UserHasAccount.c.user_id == user.id) delete_user = userTable.__table__.delete().where( userTable.id == user.id) await s.execute(delete_acc_relation) await s.execute(delete_user) return user
async def test_trasnform_to_alchemy_object(self): account = Account(**ACCOUNT_DEV_DICT) _, AccountTable = await account.to_alchemy_obj() async with AsgardDBSession() as s: account_db = (await s.query(AccountTable).filter( AccountTable.id == ACCOUNT_DEV_ID).one()) account = await Account.from_alchemy_obj(account_db) self.assertEqual(account.id, ACCOUNT_DEV_ID) self.assertEqual(account.name, ACCOUNT_DEV_NAME) self.assertEqual(account.namespace, ACCOUNT_DEV_NAMESPACE) self.assertEqual(account.owner, ACCOUNT_DEV_OWNER)
async def get_accounts_from_user(self, user: User) -> List[Account]: async with AsgardDBSession() as s: _join = UserDB.__table__.join( UserHasAccount, UserDB.id == UserHasAccount.c.user_id).join( AccountDB.__table__, AccountDB.__table__.c.id == UserHasAccount.c.account_id, ) accounts = (await s.query( AccountDB.__table__ ).join(_join).filter(UserHasAccount.c.user_id == user.id).all()) return [await Account.from_alchemy_obj(a) for a in accounts]
async def create_user(self, user: User) -> User: user_db, userTable = await user.to_alchemy_obj() try: async with AsgardDBSession() as s: returned_values = await s.execute( userTable.__table__.insert().values( tx_name=user.name, tx_email=user.email).return_defaults(userTable.id)) created_id = list(returned_values)[0].id return User(id=created_id, name=user.name, email=user.email) except psycopg2.IntegrityError as e: raise DuplicateEntity(e.pgerror)
async def user_has_permission(self, user: User) -> bool: _join = UserHasAccount.join( UserDB, UserHasAccount.c.user_id == UserDB.id ) async with AsgardDBSession() as s: has_permission = ( await s.query(UserHasAccount.c.id) .join(_join) .filter(UserDB.tx_email == user.email) .filter(UserHasAccount.c.account_id == self.id) .exists() ) return has_permission
async def test_user_transform_to_alchemy_object(self): user = User(**USER_WITH_MULTIPLE_ACCOUNTS_DICT) user_db, UserDB = await user.to_alchemy_obj() self.assertEqual(user_db.id, USER_WITH_MULTIPLE_ACCOUNTS_ID) self.assertEqual(user_db.tx_name, USER_WITH_MULTIPLE_ACCOUNTS_NAME) self.assertEqual(user_db.tx_email, USER_WITH_MULTIPLE_ACCOUNTS_EMAIL) async with AsgardDBSession() as s: result = (await s.query(UserDB).filter( UserDB.id == USER_WITH_MULTIPLE_ACCOUNTS_ID).one()) user_model = await User.from_alchemy_obj(result) self.assertEqual(user_model.name, USER_WITH_MULTIPLE_ACCOUNTS_NAME) self.assertEqual(user_model.email, USER_WITH_MULTIPLE_ACCOUNTS_EMAIL)
async def test_serialize_all_fields(self): """ Confere que é possível serializar um UsersMeResources a apartir dos outros modelos necessários. data = UsersMeResources(user=..., current_account=..., accounts=...) """ async with AsgardDBSession() as s: account = (await s.query(AccountDB).filter(AccountDB.id == ACCOUNT_DEV_ID ).one()) other_accounts = (await s.query(AccountDB).filter( AccountDB.id == ACCOUNT_INFRA_ID).one()) user = (await s.query(UserDB).filter( UserDB.id == USER_WITH_MULTIPLE_ACCOUNTS_ID).one()) users_me_resource = UserResource( user=await User.from_alchemy_obj(user), current_account=await Account.from_alchemy_obj(account), accounts=[await Account.from_alchemy_obj(other_accounts)], ) self.assertDictEqual( { "accounts": [{ "errors": {}, "id": ACCOUNT_INFRA_ID, "name": ACCOUNT_INFRA_NAME, "namespace": ACCOUNT_INFRA_NAMESPACE, "owner": ACCOUNT_INFRA_OWNER, "type": "ASGARD", }], "current_account": { "errors": {}, "id": ACCOUNT_DEV_ID, "name": ACCOUNT_DEV_NAME, "namespace": ACCOUNT_DEV_NAMESPACE, "owner": ACCOUNT_DEV_OWNER, "type": "ASGARD", }, "user": { "email": USER_WITH_MULTIPLE_ACCOUNTS_EMAIL, "errors": {}, "id": USER_WITH_MULTIPLE_ACCOUNTS_ID, "name": USER_WITH_MULTIPLE_ACCOUNTS_NAME, "type": "ASGARD", }, }, users_me_resource.dict(), )
async def test_accounts_add_user_user_already_in_account(self): """ Não adicionamos caso o usuário já esteja na conta Mas também não retornamos nenhum erro """ account = Account(**ACCOUNT_DEV_DICT) user = User(**USER_WITH_ONE_ACCOUNT_DICT) self.assertTrue(await account.user_has_permission(user)) await self.backend.add_user(user, account) self.assertTrue(await account.user_has_permission(user)) async with AsgardDBSession() as s: total = (await s.query(UserHasAccount).filter( UserHasAccount.c.account_id == account.id ).filter(UserHasAccount.c.user_id == user.id).all()) self.assertEqual(1, len(total), "Registro duplicado em user_has_account")