diff NewTests/Authorization/models.py @ 576:80ba6f1d521c

new tests for authorization plugin (native only)
author Alain Mazy <am@osimis.io>
date Wed, 06 Sep 2023 17:04:36 +0200
parents
children 0649a19df194
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NewTests/Authorization/models.py	Wed Sep 06 17:04:36 2023 +0200
@@ -0,0 +1,150 @@
+# SPDX-FileCopyrightText: 2022 - 2023 Orthanc Team SRL <info@orthanc.team>
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from typing import Optional, List
+from pydantic import BaseModel, Field
+from pydantic.datetime_parse import parse_datetime
+from enum import Enum
+from datetime import datetime
+
+
+class StringDateTime(datetime):
+    @classmethod
+    def __get_validators__(cls):
+        yield parse_datetime
+        yield cls.validate
+
+    @classmethod
+    def validate(cls, v: datetime):
+        return v.isoformat()
+
+
+class Levels(str, Enum):
+    PATIENT = 'patient'
+    STUDY = 'study'
+    SERIES = 'series'
+    INSTANCE = 'instance'
+
+    SYSTEM = 'system'
+
+
+class Methods(str, Enum):
+    GET = 'get'
+    POST = 'post'
+    PUT = 'put'
+    DELETE = 'delete'
+
+
+class DecoderErrorCodes(str, Enum):
+    EXPIRED = 'expired'
+    INVALID = 'invalid'
+    UNKNOWN = 'unknown'
+
+
+class TokenType(str, Enum):
+    OSIMIS_VIEWER_PUBLICATION = 'osimis-viewer-publication'  # a link to open the Osimis viewer valid for a long period
+    MEDDREAM_VIEWER_PUBLICATION = 'meddream-viewer-publication'  # a link to open the MedDream viewer valid for a long period
+    STONE_VIEWER_PUBLICATION = 'stone-viewer-publication'  # a link to open the Stone viewer valid for a long period
+    OHIF_VIEWER_PUBLICATION = 'ohif-viewer-publication'  # a link to open the OHIF viewer valid for a long period
+
+    MEDDREAM_INSTANT_LINK = 'meddream-instant-link'  # a direct link to MedDream viewer that is valid only a few minutes to open the viewer directly
+
+    # OSIMIS_VIEWER_INSTANT_LINK = 'osimis-viewer-instant-link'  # a direct link to Osimis viewer that is valid only a few minutes to open the viewer directly
+    # STONE_VIEWER_INSTANT_LINK = 'stone-viewer-instant-link'  # a direct link to Stone viewer that is valid only a few minutes to open the viewer directly
+    #
+    # DOWNLOAD_INSTANT_LINK = 'download-instant-link'  # a link to download a study/series/instance directly
+    VIEWER_INSTANT_LINK = 'viewer-instant-link'             # a link to a resource to be used directly.
+    DOWNLOAD_INSTANT_LINK = 'download-instant-link'         # a link to a resource to be used directly.
+
+
+    INVALID = 'invalid'
+
+class OrthancResource(BaseModel):
+    dicom_uid: Optional[str] = Field(alias="dicom-uid", default=None)
+    orthanc_id: Optional[str] = Field(alias="orthanc-id", default=None)
+    url: Optional[str] = None                                                       # e.g. a download link /studies/.../archive
+    level: Levels
+
+    class Config:  # allow creating object from dict (used when deserializing the JWT)
+        allow_population_by_field_name = True
+
+
+class TokenCreationRequest(BaseModel):
+    id: Optional[str] = None
+    resources: List[OrthancResource]
+    type: TokenType = Field(default=TokenType.INVALID)
+    expiration_date: Optional[StringDateTime] = Field(alias="expiration-date", default=None)
+    validity_duration: Optional[int] = Field(alias='validity-duration', default=None)            # alternate way to provide an expiration_date, more convenient for instant-links since the duration is relative to the server time, not the client time !
+
+    class Config:  # allow creating object from dict (used when deserializing the JWT)
+        allow_population_by_field_name = True
+
+
+class TokenCreationResponse(BaseModel):
+    request: TokenCreationRequest
+    token: str
+    url: Optional[str] = None
+
+
+class TokenValidationRequest(BaseModel):
+    dicom_uid: Optional[str] = Field(alias="dicom-uid", default=None)
+    orthanc_id: Optional[str] = Field(alias="orthanc-id", default=None)
+    token_key: Optional[str] = Field(alias="token-key", default=None)
+    token_value: Optional[str] = Field(alias="token-value", default=None)
+    server_id: Optional[str] = Field(alias="server-id", default=None)
+    level: Optional[Levels]
+    method: Methods
+    uri: Optional[str]
+#     labels: Optional[List[str]]
+
+
+class TokenValidationResponse(BaseModel):
+    granted: bool
+    validity: int
+
+
+class TokenDecoderRequest(BaseModel):
+    token_key: Optional[str] = Field(alias="token-key", default=None)
+    token_value: Optional[str] = Field(alias="token-value", default=None)
+
+
+class TokenDecoderResponse(BaseModel):
+    token_type: Optional[TokenType] = Field(alias="token-type", default=None)
+    error_code: Optional[DecoderErrorCodes] = Field(alias="error-code", default=None)
+    redirect_url: Optional[str] = Field(alias="redirect-url", default=None)
+
+
+class UserProfileRequest(BaseModel):
+    token_key: Optional[str] = Field(alias="token-key", default=None)
+    token_value: Optional[str] = Field(alias="token-value", default=None)
+    server_id: Optional[str] = Field(alias="server-id", default=None)
+
+
+class UserPermissions(str, Enum):
+    ALL = 'all'
+    VIEW = 'view'
+    DOWNLOAD = 'download'
+    DELETE = 'delete'
+    SEND = 'send'
+    MODIFY = 'modify'
+    ANONYMIZE = 'anonymize'
+    UPLOAD = 'upload'
+    Q_R_REMOTE_MODALITIES = 'q-r-remote-modalities'
+    SETTINGS = 'settings'
+    API_VIEW = 'api-view'
+    EDIT_LABELS = 'edit-labels'
+
+    SHARE = 'share'
+
+
+class UserProfileResponse(BaseModel):
+    name: str
+    authorized_labels: List[str] = Field(alias="authorized-labels", default_factory=list)
+    # authorized_labels: List[str] = Field(default_factory=list)
+    permissions: List[UserPermissions] = Field(default_factory=list)
+    validity: int
+
+    class Config:
+        use_enum_values = True
+        allow_population_by_field_name = True
\ No newline at end of file