From 3eb19e1c078dd900fb28a723b8e2e5ae80288cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de> Date: Thu, 30 Jun 2022 16:22:35 +0200 Subject: [PATCH] Add endpoint to update a permission #9 --- ProxyAPI/app/api/dependencies.py | 2 +- .../app/api/endpoints/bucket_permissions.py | 54 +++++++++++++++++-- ProxyAPI/app/crud/crud_bucket_permission.py | 27 ++++++++++ ProxyAPI/app/models/bucket_permission.py | 18 +++++++ ProxyAPI/app/schemas/bucket_permission.py | 15 ++++-- 5 files changed, 108 insertions(+), 8 deletions(-) diff --git a/ProxyAPI/app/api/dependencies.py b/ProxyAPI/app/api/dependencies.py index 7da9fa5..b69ddf7 100644 --- a/ProxyAPI/app/api/dependencies.py +++ b/ProxyAPI/app/api/dependencies.py @@ -201,6 +201,6 @@ async def get_authorized_user_for_permission( raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found") elif current_user != user and current_user.uid != bucket.owner_id: raise HTTPException( - status.HTTP_403_FORBIDDEN, detail="Only the owner or the grantee can delete a bucket permission" + status.HTTP_403_FORBIDDEN, detail="Only the owner or the grantee can access a bucket permission" ) return user diff --git a/ProxyAPI/app/api/endpoints/bucket_permissions.py b/ProxyAPI/app/api/endpoints/bucket_permissions.py index f491dd4..906643f 100644 --- a/ProxyAPI/app/api/endpoints/bucket_permissions.py +++ b/ProxyAPI/app/api/endpoints/bucket_permissions.py @@ -12,6 +12,7 @@ from app.crud.crud_bucket_permission import CRUDBucketPermission, DuplicateError from app.models.bucket import Bucket as BucketDB from app.models.user import User as UserDB from app.schemas.bucket_permission import BucketPermission as PermissionSchema +from app.schemas.bucket_permission import BucketPermissionParameters as PermissionParametersSchema router = APIRouter() @@ -38,7 +39,7 @@ async def get_permission_for_bucket( db : sqlalchemy.ext.asyncio.AsyncSession. Async database session to perform query on. Dependency Injection. user : app.models.user.User - Current user. Dependency Injection. + User with the username in the URL. Dependency Injection. Returns ------- @@ -75,7 +76,7 @@ async def delete_permission_for_bucket( db : sqlalchemy.ext.asyncio.AsyncSession. Async database session to perform query on. Dependency Injection. user : app.models.user.User - Current user. Dependency Injection. + User with the username in the URL. Dependency Injection. Returns ------- @@ -174,7 +175,7 @@ async def create_permission( Information about the permission which should be created. HTTP Body parameter. db : sqlalchemy.ext.asyncio.AsyncSession. Async database session to perform query on. Dependency Injection. - current_user : : app.models.user.User + current_user : app.models.user.User Current user. Dependency Injection. Returns ------- @@ -196,3 +197,50 @@ async def create_permission( ) except KeyError: raise HTTPException(status.HTTP_404_NOT_FOUND, detail=f"User with username={permission.username} not found") + + +@router.put( + "/bucket/{bucket_name}/user/{username}", + status_code=status.HTTP_200_OK, + response_model=PermissionSchema, + summary="Get permissions for bucket and user combination.", + response_model_exclude_none=True, +) +async def update_permission( + permission_parameters: PermissionParametersSchema = Body(..., description="Permission to create"), + user: UserDB = Depends(get_authorized_user_for_permission), + bucket: BucketDB = Depends(get_current_bucket), + db: AsyncSession = Depends(get_db), + current_user: UserDB = Depends(get_current_user), +) -> PermissionSchema: + """ + Update a permission for a bucket and user. + \f + Parameters + ---------- + permission_parameters : app.schemas.bucket_permission.BucketPermission + Information about the permission which should be updated. HTTP Body parameter. + user : app.models.user.User + User with the username in the URL. Dependency Injection. + bucket : app.models.bucket.Bucket + Bucket with the name provided in the URL path. Dependency Injection. + db : sqlalchemy.ext.asyncio.AsyncSession. + Async database session to perform query on. Dependency Injection. + current_user : app.models.user.User + Current user. Dependency Injection. + Returns + ------- + permissions : app.schemas.bucket_permission.BucketPermission + Updated permission. + """ + if not await CRUDBucketPermission.check_permission(db, bucket.name, current_user.uid, only_own=True): + raise HTTPException(status.HTTP_403_FORBIDDEN, "You can only modify permissions on your own bucket") + bucket_permission = await CRUDBucketPermission.get(db, bucket.name, user.uid) + + if bucket_permission is None: + raise HTTPException( + status.HTTP_404_NOT_FOUND, + detail=f"Permission for combination of bucket={bucket.name} and user={user.username} doesn't exists", + ) + updated_permission = await CRUDBucketPermission.update_permission(db, bucket_permission, permission_parameters) + return PermissionSchema.from_db_model(updated_permission) diff --git a/ProxyAPI/app/crud/crud_bucket_permission.py b/ProxyAPI/app/crud/crud_bucket_permission.py index 0b5ff8b..d4f9306 100644 --- a/ProxyAPI/app/crud/crud_bucket_permission.py +++ b/ProxyAPI/app/crud/crud_bucket_permission.py @@ -7,6 +7,7 @@ from app.crud.crud_bucket import CRUDBucket from app.crud.crud_user import CRUDUser from app.models.bucket_permission import BucketPermission as BucketPermissionDB from app.schemas.bucket_permission import BucketPermission as BucketPermissionSchema +from app.schemas.bucket_permission import BucketPermissionParameters as BucketPermissionParametersSchema class CRUDBucketPermission: @@ -156,6 +157,32 @@ class CRUDBucketPermission: await db.delete(permission) await db.commit() + @staticmethod + async def update_permission( + db: AsyncSession, permission: BucketPermissionDB, new_params: BucketPermissionParametersSchema + ) -> BucketPermissionDB: + """ + Update a permission in the database. + + Parameters + ---------- + db : sqlalchemy.ext.asyncio.AsyncSession + Async database session to perform query on. + permission : app.schemas.bucket_permission.BucketPermission + The permission to update. + new_params : app.schemas.bucket_permission.BucketPermissionParameters + The parameters which should be updated. + + Returns + ------- + permission : app.models.bucket_permission.BucketPermission + Updated permission model from the db. + """ + permission.update_parameters(new_params) + await db.commit() + await db.refresh(permission) + return permission + class DuplicateError(Exception): pass diff --git a/ProxyAPI/app/models/bucket_permission.py b/ProxyAPI/app/models/bucket_permission.py index b081f0b..7b26d80 100644 --- a/ProxyAPI/app/models/bucket_permission.py +++ b/ProxyAPI/app/models/bucket_permission.py @@ -9,8 +9,12 @@ from sqlalchemy.orm import relationship from app.db.base_class import Base if TYPE_CHECKING: + from app.schemas.bucket_permission import BucketPermissionParameters + from .bucket import Bucket from .user import User +else: + BucketPermissionParameters = object @unique @@ -40,5 +44,19 @@ class BucketPermission(Base): grantee: "User" = relationship("User", back_populates="permissions") bucket: "Bucket" = relationship("Bucket", back_populates="permissions") + def update_parameters(self, params: BucketPermissionParameters) -> None: # pragma: no cover + """ + Update the object with the new parameters. + + Parameters + ---------- + params : app.schemas.bucket_permission.BucketPermissionParameters + The parameters which should be updated. + """ + self.from_ = params.from_timestamp + self.to = params.to_timestamp + self.file_prefix = params.file_prefix + self.permissions = params.permission + def __repr__(self) -> str: return f"BucketPermission(uid={self.user_id} bucket_name={self.bucket_name})" diff --git a/ProxyAPI/app/schemas/bucket_permission.py b/ProxyAPI/app/schemas/bucket_permission.py index cfc9750..12b8e37 100644 --- a/ProxyAPI/app/schemas/bucket_permission.py +++ b/ProxyAPI/app/schemas/bucket_permission.py @@ -6,13 +6,11 @@ from app.models.bucket_permission import BucketPermission as BucketPermissionDB from app.models.bucket_permission import PermissionEnum -class BucketPermission(BaseModel): +class BucketPermissionParameters(BaseModel): """ - Schema for the bucket permissions. + Schema for the parameters of a bucket permission. """ - username: str = Field(..., description="Name of User", example="baggins") - bucket_name: str = Field(..., description="Name of Bucket", example="test-bucket") from_timestamp: datetime | None = Field( None, description="Start date of permission", example=datetime(2022, 1, 1, 0, 0) ) @@ -22,6 +20,15 @@ class BucketPermission(BaseModel): file_prefix: str | None = Field(None, description="Prefix of subfolder", example="pseudo/sub/folder/") permission: PermissionEnum | str = Field(PermissionEnum.READ, description="Permission", example=PermissionEnum.READ) + +class BucketPermission(BucketPermissionParameters): + """ + Schema for the bucket permissions. + """ + + username: str = Field(..., description="Name of User", example="baggins") + bucket_name: str = Field(..., description="Name of Bucket", example="test-bucket") + @staticmethod def from_db_model(permission: BucketPermissionDB, username: str | None = None) -> "BucketPermission": """ -- GitLab