diff --git a/lib/galaxy/managers/quotas.py b/lib/galaxy/managers/quotas.py index 3ad48f09545..10b52a71b0a 100644 --- a/lib/galaxy/managers/quotas.py +++ b/lib/galaxy/managers/quotas.py @@ -23,7 +23,6 @@ from galaxy.quota._schema import ( DefaultQuotaValues, QuotaOperation, ) -from galaxy.schema.fields import EncodedDatabaseIdField from galaxy.structured_app import StructuredApp log = logging.getLogger(__name__) @@ -257,5 +256,5 @@ class QuotaManager: message += ", ".join(names) return message - def get_quota(self, trans, id: EncodedDatabaseIdField, deleted: Optional[bool] = None) -> model.Quota: + def get_quota(self, trans, id: int, deleted: Optional[bool] = None) -> model.Quota: return base.get_object(trans, id, "Quota", check_ownership=False, check_accessible=False, deleted=deleted) diff --git a/lib/galaxy/quota/_schema.py b/lib/galaxy/quota/_schema.py index 11d3b29e45b..5b20d908bdf 100644 --- a/lib/galaxy/quota/_schema.py +++ b/lib/galaxy/quota/_schema.py @@ -4,17 +4,15 @@ from typing import ( Optional, ) -from pydantic import ( - BaseModel, - Field, -) +from pydantic import Field from galaxy.schema.fields import ( - EncodedDatabaseIdField, + DecodedDatabaseIdField, ModelClassField, ) from galaxy.schema.schema import ( GroupModel, + Model, UserModel, ) @@ -67,7 +65,7 @@ QuotaOperationField = Field( ) -class DefaultQuota(BaseModel): # TODO: should this replace lib.galaxy.model.DefaultQuotaAssociation at some point? +class DefaultQuota(Model): # TODO: should this replace lib.galaxy.model.DefaultQuotaAssociation at some point? model_class: str = ModelClassField(DEFAULT_QUOTA_ASSOCIATION_MODEL_CLASS_NAME) type: DefaultQuotaTypes = Field( ..., @@ -80,7 +78,7 @@ class DefaultQuota(BaseModel): # TODO: should this replace lib.galaxy.model.Def ) -class UserQuota(BaseModel): +class UserQuota(Model): model_class: str = ModelClassField(USER_QUOTA_ASSOCIATION_MODEL_CLASS_NAME) user: UserModel = Field( ..., @@ -89,7 +87,7 @@ class UserQuota(BaseModel): ) -class GroupQuota(BaseModel): +class GroupQuota(Model): model_class: str = ModelClassField(GROUP_QUOTA_ASSOCIATION_MODEL_CLASS_NAME) group: GroupModel = Field( ..., @@ -98,11 +96,11 @@ class GroupQuota(BaseModel): ) -class QuotaBase(BaseModel): +class QuotaBase(Model): """Base model containing common fields for Quotas.""" model_class: str = ModelClassField(QUOTA_MODEL_CLASS_NAME) - id: EncodedDatabaseIdField = Field( + id: DecodedDatabaseIdField = Field( ..., title="ID", description="The `encoded identifier` of the quota.", @@ -121,7 +119,7 @@ class QuotaSummary(QuotaBase): ) -class QuotaSummaryList(BaseModel): +class QuotaSummaryList(Model): __root__: List[QuotaSummary] = Field( default=[], title="List with summary information of Quotas.", @@ -166,7 +164,7 @@ class CreateQuotaResult(QuotaSummary): ) -class CreateQuotaParams(BaseModel): +class CreateQuotaParams(Model): name: str = QuotaNameField description: str = QuotaDescriptionField amount: str = Field( @@ -196,7 +194,7 @@ class CreateQuotaParams(BaseModel): ) -class UpdateQuotaParams(BaseModel): +class UpdateQuotaParams(Model): name: Optional[str] = Field( default=None, title="Name", @@ -243,7 +241,7 @@ class UpdateQuotaParams(BaseModel): ) -class DeleteQuotaPayload(BaseModel): +class DeleteQuotaPayload(Model): purge: bool = Field( False, title="Purge", diff --git a/lib/galaxy/schema/schema.py b/lib/galaxy/schema/schema.py index 4bc64159532..32ab6edd54e 100644 --- a/lib/galaxy/schema/schema.py +++ b/lib/galaxy/schema/schema.py @@ -196,7 +196,7 @@ class Model(BaseModel): class UserModel(Model): """User in a transaction context.""" - id: EncodedDatabaseIdField = Field(title="ID", description="User ID") + id: DecodedDatabaseIdField = Field(title="ID", description="User ID") username: str = Field(title="Username", description="User username") email: str = Field(title="Email", description="User email") active: bool = Field(title="Active", description="User is active") @@ -205,11 +205,11 @@ class UserModel(Model): model_class: str = ModelClassField(USER_MODEL_CLASS_NAME) -class GroupModel(BaseModel): +class GroupModel(Model): """User group model""" model_class: str = ModelClassField(GROUP_MODEL_CLASS_NAME) - id: EncodedDatabaseIdField = Field( + id: DecodedDatabaseIdField = Field( ..., # Required title="ID", description="Encoded group ID", diff --git a/lib/galaxy/webapps/galaxy/api/quotas.py b/lib/galaxy/webapps/galaxy/api/quotas.py index 33d4c208b42..7043ec13d0b 100644 --- a/lib/galaxy/webapps/galaxy/api/quotas.py +++ b/lib/galaxy/webapps/galaxy/api/quotas.py @@ -15,13 +15,13 @@ from galaxy.quota._schema import ( QuotaSummaryList, UpdateQuotaParams, ) -from galaxy.schema.fields import EncodedDatabaseIdField -from galaxy.webapps.galaxy.services.quotas import QuotasService -from . import ( +from galaxy.schema.fields import DecodedDatabaseIdField +from galaxy.webapps.galaxy.api import ( depends, DependsOnTrans, Router, ) +from galaxy.webapps.galaxy.services.quotas import QuotasService log = logging.getLogger(__name__) @@ -29,7 +29,7 @@ log = logging.getLogger(__name__) router = Router(tags=["quotas"]) -QuotaIdPathParam: EncodedDatabaseIdField = Path( +QuotaIdPathParam: DecodedDatabaseIdField = Path( ..., title="Quota ID", description="The encoded identifier of the Quota." # Required ) @@ -64,24 +64,26 @@ class FastAPIQuota: @router.get( "/api/quotas/{id}", + name="quota", summary="Displays details on a particular active quota.", require_admin=True, ) def show( - self, trans: ProvidesUserContext = DependsOnTrans, id: EncodedDatabaseIdField = QuotaIdPathParam + self, trans: ProvidesUserContext = DependsOnTrans, id: DecodedDatabaseIdField = QuotaIdPathParam ) -> QuotaDetails: """Displays details on a particular active quota.""" return self.service.show(trans, id) @router.get( "/api/quotas/deleted/{id}", + name="deleted_quota", summary="Displays details on a particular quota that has been deleted.", require_admin=True, ) def show_deleted( self, trans: ProvidesUserContext = DependsOnTrans, - id: EncodedDatabaseIdField = QuotaIdPathParam, + id: DecodedDatabaseIdField = QuotaIdPathParam, ) -> QuotaDetails: """Displays details on a particular quota that has been deleted.""" return self.service.show(trans, id, deleted=True) @@ -107,7 +109,7 @@ class FastAPIQuota: def update( self, payload: UpdateQuotaParams, - id: EncodedDatabaseIdField = QuotaIdPathParam, + id: DecodedDatabaseIdField = QuotaIdPathParam, trans: ProvidesUserContext = DependsOnTrans, ) -> str: """Updates an existing quota.""" @@ -120,7 +122,7 @@ class FastAPIQuota: ) def delete( self, - id: EncodedDatabaseIdField = QuotaIdPathParam, + id: DecodedDatabaseIdField = QuotaIdPathParam, trans: ProvidesUserContext = DependsOnTrans, payload: DeleteQuotaPayload = Body(None), # Optional ) -> str: @@ -134,7 +136,7 @@ class FastAPIQuota: ) def undelete( self, - id: EncodedDatabaseIdField = QuotaIdPathParam, + id: DecodedDatabaseIdField = QuotaIdPathParam, trans: ProvidesUserContext = DependsOnTrans, ) -> str: """Restores a previously deleted quota.""" diff --git a/lib/galaxy/webapps/galaxy/services/quotas.py b/lib/galaxy/webapps/galaxy/services/quotas.py index 0c4c2018c7e..ca6ef054592 100644 --- a/lib/galaxy/webapps/galaxy/services/quotas.py +++ b/lib/galaxy/webapps/galaxy/services/quotas.py @@ -21,7 +21,7 @@ from galaxy.quota._schema import ( QuotaSummaryList, UpdateQuotaParams, ) -from galaxy.schema.fields import EncodedDatabaseIdField +from galaxy.schema.fields import DecodedDatabaseIdField from galaxy.security.idencoding import IdEncodingHelper from galaxy.web import url_for from galaxy.webapps.galaxy.services.base import ServiceBase @@ -37,7 +37,7 @@ class QuotasService(ServiceBase): self.quota_manager = quota_manager def index(self, trans: ProvidesUserContext, deleted: bool = False) -> QuotaSummaryList: - """Displays a collection (list) of quotas.""" + """Displays a list of quotas.""" rval = [] query = trans.sa_session.query(model.Quota) if deleted: @@ -47,29 +47,31 @@ class QuotasService(ServiceBase): route = "quota" query = query.filter(model.Quota.deleted == false()) for quota in query: - item = quota.to_dict(value_mapper={"id": trans.security.encode_id}) - encoded_id = trans.security.encode_id(quota.id) - item["url"] = self._url_for(route, id=encoded_id) + item = quota.to_dict(value_mapper={"id": DecodedDatabaseIdField.encode}) + encoded_id = DecodedDatabaseIdField.encode(quota.id) + item["url"] = url_for(route, id=encoded_id) rval.append(item) - return QuotaSummaryList.parse_obj(rval) + return QuotaSummaryList.construct(__root__=rval) - def show(self, trans: ProvidesUserContext, id: EncodedDatabaseIdField, deleted: bool = False) -> QuotaDetails: + def show(self, trans: ProvidesUserContext, id: DecodedDatabaseIdField, deleted: bool = False) -> QuotaDetails: """Displays information about a quota.""" quota = self.quota_manager.get_quota(trans, id, deleted=deleted) - rval = quota.to_dict(view="element", value_mapper={"id": trans.security.encode_id, "total_disk_usage": float}) - return QuotaDetails.parse_obj(rval) + rval = quota.to_dict( + view="element", value_mapper={"id": DecodedDatabaseIdField.encode, "total_disk_usage": float} + ) + return QuotaDetails.construct(**rval) def create(self, trans: ProvidesUserContext, params: CreateQuotaParams) -> CreateQuotaResult: """Creates a new quota.""" payload = params.dict() self.validate_in_users_and_groups(trans, payload) quota, message = self.quota_manager.create_quota(payload) - item = quota.to_dict(value_mapper={"id": trans.security.encode_id}) - item["url"] = self._url_for("quota", id=trans.security.encode_id(quota.id)) + item = quota.to_dict(value_mapper={"id": DecodedDatabaseIdField.encode}) + item["url"] = url_for("quota", id=DecodedDatabaseIdField.encode(quota.id)) item["message"] = message - return CreateQuotaResult.parse_obj(item) + return CreateQuotaResult.construct(**item) - def update(self, trans: ProvidesUserContext, id: EncodedDatabaseIdField, params: UpdateQuotaParams) -> str: + def update(self, trans: ProvidesUserContext, id: DecodedDatabaseIdField, params: UpdateQuotaParams) -> str: """Modifies a quota.""" payload = params.dict() self.validate_in_users_and_groups(trans, payload) @@ -96,7 +98,7 @@ class QuotasService(ServiceBase): return "; ".join(messages) def delete( - self, trans: ProvidesUserContext, id: EncodedDatabaseIdField, payload: Optional[DeleteQuotaPayload] = None + self, trans: ProvidesUserContext, id: DecodedDatabaseIdField, payload: Optional[DeleteQuotaPayload] = None ) -> str: """Marks a quota as deleted.""" quota = self.quota_manager.get_quota( @@ -107,7 +109,7 @@ class QuotasService(ServiceBase): message += self.quota_manager.purge_quota(quota) return message - def undelete(self, trans: ProvidesUserContext, id: EncodedDatabaseIdField) -> str: + def undelete(self, trans: ProvidesUserContext, id: DecodedDatabaseIdField) -> str: """Restores a previously deleted quota.""" quota = self.quota_manager.get_quota(trans, id, deleted=True) return self.quota_manager.undelete_quota(quota) @@ -146,9 +148,3 @@ class QuotasService(ServiceBase): raise Exception(msg) payload["in_users"] = list(map(str, new_in_users)) payload["in_groups"] = list(map(str, new_in_groups)) - - def _url_for(self, *args, **kargs): - try: - return url_for(*args, **kargs) - except AttributeError: - return "*deprecated attribute not filled in by FastAPI server*"