changeset 819:276a054d7c32

new auth tests
author Alain Mazy <am@orthanc.team>
date Mon, 26 May 2025 19:37:15 +0200
parents 1aa6cfc19cc8
children d665c049308e
files NewTests/Authorization/auth_service.py NewTests/Authorization/models.py NewTests/Authorization/test_authorization.py
diffstat 3 files changed, 46 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/NewTests/Authorization/auth_service.py	Tue May 20 10:53:53 2025 +0200
+++ b/NewTests/Authorization/auth_service.py	Mon May 26 19:37:15 2025 +0200
@@ -78,3 +78,21 @@
 
     logging.info("validate token: " + response.json())
     return response
+
+@app.post("/tokens/decode")
+def decode_token(request: TokenDecoderRequest):
+
+    logging.info("decoding token: " + request.json())
+    response = TokenDecoderResponse(resources=[])
+
+    if request.token_value == "token-a-study" or request.token_value == "token-both-studies":
+        response.resources.append(OrthancResource(level=Levels.STUDY,
+                                                    orthanc_id="b9c08539-26f93bde-c81ab0d7-bffaf2cb-a4d0bdd0",
+                                                    dicom_uid="1.2.840.113619.2.176.2025.1499492.7391.1171285944.390"))
+    if request.token_value == "token-b-study" or request.token_value == "token-both-studies":
+        response.resources.append(OrthancResource(level=Levels.STUDY,
+                                                    orthanc_id="27f7126f-4f66fb14-03f4081b-f9341db2-53925988",
+                                                    dicom_uid="2.16.840.1.113669.632.20.1211.10000357775"))
+
+    logging.info("decoded token: " + response.json())
+    return response
--- a/NewTests/Authorization/models.py	Tue May 20 10:53:53 2025 +0200
+++ b/NewTests/Authorization/models.py	Mon May 26 19:37:15 2025 +0200
@@ -1,4 +1,4 @@
-from typing import Optional, List
+from typing import Optional, List, Dict
 from pydantic import BaseModel, Field
 from enum import Enum
 from datetime import datetime
@@ -31,6 +31,7 @@
     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
+    VOLVIEW_VIEWER_PUBLICATION = 'volview-viewer-publication'  # a link to open the VolView 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
 
@@ -80,7 +81,6 @@
     level: Optional[Levels]
     method: Methods
     uri: Optional[str] = None
-#     labels: Optional[List[str]]
 
 
 class TokenValidationResponse(BaseModel):
@@ -97,7 +97,7 @@
     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)
-
+    resources: List[OrthancResource]
 
 class UserProfileRequest(BaseModel):
     token_key: Optional[str] = Field(alias="token-key", default=None)
@@ -118,16 +118,30 @@
     SETTINGS = 'settings'
     API_VIEW = 'api-view'
     EDIT_LABELS = 'edit-labels'
+    ADMIN_PERMISSIONS = 'admin-permissions'
 
     SHARE = 'share'
 
 
-class UserProfileResponse(BaseModel):
-    name: str
+class RolePermissions(BaseModel):
     authorized_labels: List[str] = Field(alias="authorized-labels", default_factory=list)
     permissions: List[UserPermissions] = Field(default_factory=list)
+
+    class Config:
+        use_enum_values = True
+        populate_by_name = True  # allow creating object from dict (used when deserializing the permission file)
+
+
+class UserProfileResponse(RolePermissions):
+    name: str
+    # authorized_labels: List[str] = Field(alias="authorized-labels", default_factory=list)
+    # permissions: List[UserPermissions] = Field(default_factory=list)
     validity: int
 
     class Config:
         use_enum_values = True
-        populate_by_name = True
\ No newline at end of file
+        populate_by_name = True
+
+class RolesConfigurationModel(BaseModel):
+    roles: Dict[str, RolePermissions]                                                # role/permissions mapping
+    available_labels: List[str] = Field(alias="available-labels", default_factory=list)  # if empty, everyone can create additionnal labels, if not, they can only add/remove the listed labels
--- a/NewTests/Authorization/test_authorization.py	Tue May 20 10:53:53 2025 +0200
+++ b/NewTests/Authorization/test_authorization.py	Mon May 26 19:37:15 2025 +0200
@@ -371,9 +371,11 @@
         # with a resource token, we can access only the given resource, not generic resources or resources from other studies
 
         # generic resources are forbidden
+        # note: even tools/find is still forbidden in 0.9.3 (but not /dicom-web/studies -> see below)
         self.assert_is_forbidden(lambda: o.studies.find(query={"PatientName": "KNIX"},  # tools/find is forbidden with a resource token
                                                         labels=['label_b'],
                                                         labels_constraint='Any'))
+
         self.assert_is_forbidden(lambda: o.get_all_labels())
         self.assert_is_forbidden(lambda: o.studies.get_all_ids())
         self.assert_is_forbidden(lambda: o.patients.get_all_ids())
@@ -415,6 +417,12 @@
         o.get_json(f"dicom-web/series?0020000D={self.label_a_study_dicom_id}")
         o.get_json(f"dicom-web/instances?0020000D={self.label_a_study_dicom_id}")
 
+        if o.is_plugin_version_at_least("authorization", 0, 9, 3):
+            # equivalent to the prior studies request in OHIF
+            self.assertEqual(1, len(o.get_json(f"dicom-web/studies?PatientID={self.label_a_patient_dicom_id}")))
+            self.assertEqual(0, len(o.get_json(f"dicom-web/studies?PatientID={self.label_b_patient_dicom_id}")))
+
+
         if self.o.is_orthanc_version_at_least(1, 12, 2):
             o.get_binary(f"tools/create-archive?resources={self.label_a_study_id}")
             o.get_binary(f"tools/create-archive?resources={self.label_a_series_id}")