changeset 585:8ab5ad68c04b annotations

taking user roles into consideration in UserLayer::IsSharedWith()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 04 Sep 2026 16:25:01 +0200
parents 0b45bebe7926
children 28ad390fb2e3
files ViewerPlugin/Annotations/AnnotationsWorkspace.cpp ViewerPlugin/Annotations/AnnotationsWorkspace.h ViewerPlugin/Annotations/UserLayer.cpp ViewerPlugin/Annotations/UserLayer.h
diffstat 4 files changed, 87 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/ViewerPlugin/Annotations/AnnotationsWorkspace.cpp	Fri Sep 04 15:29:50 2026 +0200
+++ b/ViewerPlugin/Annotations/AnnotationsWorkspace.cpp	Fri Sep 04 16:25:01 2026 +0200
@@ -75,6 +75,21 @@
       }
     }
 
+    void SanityCheck() const
+    {
+#if !defined(NDEBUG)
+      for (std::set<UserId>::const_iterator it = activeInstructors_.begin(); it != activeInstructors_.end(); ++it)
+      {
+        assert(activeLearners_.find(*it) == activeLearners_.end());
+      }
+
+      for (std::set<UserId>::const_iterator it = activeLearners_.begin(); it != activeLearners_.end(); ++it)
+      {
+        assert(activeInstructors_.find(*it) == activeInstructors_.end());
+      }
+#endif
+    }
+
   public:
     PersistentInfo()
     {
@@ -92,6 +107,8 @@
 
       ParseActiveUsers(activeInstructors_, serialized[KEY_ACTIVE_INSTRUCTORS]);
       ParseActiveUsers(activeLearners_, serialized[KEY_ACTIVE_LEARNERS]);
+
+      SanityCheck();
     }
 
 
@@ -101,6 +118,8 @@
     bool AddActiveUser(const UserId& user,
                        ProjectRole role)
     {
+      SanityCheck();
+
       switch (role)
       {
         case ProjectRole_Instructor:
@@ -108,6 +127,7 @@
           {
             activeLearners_.erase(user);  // Accomodate with change in the role
             activeInstructors_.insert(user);
+            SanityCheck();
             return true;
           }
           else
@@ -120,6 +140,7 @@
           {
             activeInstructors_.erase(user);  // Accomodate with change in the role
             activeLearners_.insert(user);
+            SanityCheck();
             return true;
           }
           else
@@ -135,6 +156,28 @@
     }
 
 
+    bool LookupUserRole(ProjectRole& role,
+                        const UserId& user) const
+    {
+      if (activeInstructors_.find(user) != activeInstructors_.end())
+      {
+        assert(activeLearners_.find(user) == activeLearners_.end());
+        role = ProjectRole_Instructor;
+        return true;
+      }
+      else if (activeLearners_.find(user) != activeLearners_.end())
+      {
+        assert(activeInstructors_.find(user) == activeInstructors_.end());
+        role = ProjectRole_Learner;
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+
+
     virtual void Serialize(Json::Value& serialized) const ORTHANC_OVERRIDE
     {
       serialized = Json::objectValue;
@@ -158,6 +201,7 @@
         learnersIterator_(that.activeLearners_.begin()),
         learnersEnd_(that.activeLearners_.end())
       {
+        that.SanityCheck();
       }
 
       bool IsDone() const
@@ -217,6 +261,7 @@
   };
 
 
+
   void AnnotationsWorkspace::Load(const UserId& user)
   {
     const std::string key = id_.GetSettingsKey(user);
@@ -234,6 +279,25 @@
   }
 
 
+  bool AnnotationsWorkspace::IsSharedWith(const UserLayer& layer,
+                                          const UserId& layerAuthorId,
+                                          const UserId& viewerId,
+                                          ProjectRole viewerRole) const
+  {
+    assert(persistentInfo_.get() != NULL);
+
+    ProjectRole authorRole;
+    if (persistentInfo_->LookupUserRole(authorRole, layerAuthorId))
+    {
+      return layer.IsSharedWith(authorRole, viewerId, viewerRole);
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+
   AnnotationsWorkspace::AnnotationsWorkspace(const AnnotationsWorkspaceId& id) :
     id_(id),
     projectInformation_(id.GetProjectId())
@@ -338,7 +402,7 @@
   {
     target.clear();
 
-    // Loop over all the users in this workspace
+    // Loop over all the users (i.e., all the possible authors) in this workspace
     for (Content::const_iterator it = that_.content_.begin(); it != that_.content_.end(); ++it)
     {
       assert(it->second != NULL);
@@ -352,7 +416,7 @@
         {
           const UserLayer& layer = dynamic_cast<const UserLayer&>(iterator.GetLayer());
 
-          if (layer.IsSharedWith(userId_))
+          if (that_.IsSharedWith(layer, it->first, userId_, userRole_))
           {
             target.insert(it->first);
             break;
@@ -385,7 +449,7 @@
         {
           const UserLayer& layer = dynamic_cast<const UserLayer&>(iterator.GetLayer());
 
-          if (layer.IsSharedWith(userId_))
+          if (that_.IsSharedWith(layer, author, userId_, userRole_))
           {
             Json::Value item;
             layer.Serialize(item);
@@ -425,7 +489,7 @@
           {
             const UserLayer& authorLayer = found->second->GetUserLayer(layer.GetId());
 
-            if (authorLayer.IsSharedWith(userId_))
+            if (that_.IsSharedWith(authorLayer, layer.GetAuthor(), userId_, userRole_))
             {
               authors.insert(layer.GetAuthor());
               layerIds.insert(layer.GetId());
@@ -522,7 +586,7 @@
     const UserAnnotationsSettings& authorData = *found->second;
 
     const UserLayer& layer = authorData.GetUserLayer(layerId);
-    if (!layer.IsSharedWith(userId_))
+    if (!that_.IsSharedWith(layer, author, userId_, userRole_))
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ForbiddenAccess);
     }
--- a/ViewerPlugin/Annotations/AnnotationsWorkspace.h	Fri Sep 04 15:29:50 2026 +0200
+++ b/ViewerPlugin/Annotations/AnnotationsWorkspace.h	Fri Sep 04 16:25:01 2026 +0200
@@ -39,8 +39,6 @@
   private:
     class PersistentInfo;
 
-    void Load(const UserId& user);
-
     typedef std::map<UserId, UserAnnotationsSettings*>   Content;
 
     Orthanc::ReaderWriterLock        mutex_;
@@ -49,6 +47,13 @@
     Content                          content_;
     ProjectInformation               projectInformation_;
 
+    void Load(const UserId& user);
+
+    bool IsSharedWith(const UserLayer& layer,
+                      const UserId& layerAuthorId,
+                      const UserId& viewerId,
+                      ProjectRole viewerRole) const;
+
   public:
     explicit AnnotationsWorkspace(const AnnotationsWorkspaceId& id);
 
--- a/ViewerPlugin/Annotations/UserLayer.cpp	Fri Sep 04 15:29:50 2026 +0200
+++ b/ViewerPlugin/Annotations/UserLayer.cpp	Fri Sep 04 16:25:01 2026 +0200
@@ -75,14 +75,16 @@
   }
 
 
-  bool UserLayer::IsSharedWith(const UserId& user) const
+  bool UserLayer::IsSharedWith(ProjectRole authorRole,
+                               const UserId& viewerId,
+                               ProjectRole viewerRole) const
   {
-    assert(user.GetType() == UserId::Type_Root ||
-           user.GetType() == UserId::Type_Standard);
+    assert(viewerId.GetType() == UserId::Type_Root ||
+           viewerId.GetType() == UserId::Type_Standard);
 
     return (isPublic_ ||
-            user.GetType() == UserId::Type_Root ||
-            sharedWith_.find(user) != sharedWith_.end());
+            viewerId.GetType() == UserId::Type_Root ||
+            sharedWith_.find(viewerId) != sharedWith_.end());
   }
 
 
--- a/ViewerPlugin/Annotations/UserLayer.h	Fri Sep 04 15:29:50 2026 +0200
+++ b/ViewerPlugin/Annotations/UserLayer.h	Fri Sep 04 16:25:01 2026 +0200
@@ -24,6 +24,7 @@
 #pragma once
 
 #include "../../Framework/BackgroundColor.h"
+#include "../ViewerConfiguration.h"
 #include "ILayer.h"
 #include "UserId.h"
 
@@ -70,7 +71,9 @@
       return name_;
     }
 
-    bool IsSharedWith(const UserId& user) const;
+    bool IsSharedWith(ProjectRole authorRole,
+                      const UserId& viewerId,
+                      ProjectRole viewerRole) const;
 
     void Assign(const UserLayer& other);