changeset 507:142b9ddc9d28 annotations

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 19 Aug 2026 14:59:26 +0200
parents 178c6acccfdb
children 971c7c1ca617
files ViewerPlugin/Annotations/IAuthenticatedUser.cpp ViewerPlugin/Annotations/IAuthenticatedUser.h ViewerPlugin/Annotations/UserId.cpp ViewerPlugin/Annotations/UserId.h ViewerPlugin/CMakeLists.txt ViewerPlugin/IAuthenticatedUser.cpp ViewerPlugin/IAuthenticatedUser.h ViewerPlugin/Plugin.cpp ViewerPlugin/UserId.cpp ViewerPlugin/UserId.h
diffstat 10 files changed, 481 insertions(+), 481 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ViewerPlugin/Annotations/IAuthenticatedUser.cpp	Wed Aug 19 14:59:26 2026 +0200
@@ -0,0 +1,220 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
+ * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "../../Framework/PrecompiledHeadersWSI.h"
+#include "IAuthenticatedUser.h"
+
+#include <Compatibility.h>
+#include <OrthancException.h>
+#include <SerializationToolbox.h>
+#include <Toolbox.h>
+
+#include "../../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h"
+
+#include <cassert>
+#include <json/reader.h>
+
+namespace
+{
+  // If Orthanc runs without an authentication plugin
+  class RootUser : public IAuthenticatedUser
+  {
+  public:
+    virtual UserId GetAnnotatingId() const ORTHANC_OVERRIDE
+    {
+      return UserId(UserId::Type_Administrator);
+    }
+
+    virtual std::string Format() const ORTHANC_OVERRIDE
+    {
+      return "(root)";
+    }
+
+    virtual ProjectRole GetRoleInProject(const std::string& projectId) const ORTHANC_OVERRIDE
+    {
+      return ProjectRole_Instructor;
+    }
+  };
+
+
+  class GuestUser : public IAuthenticatedUser
+  {
+  public:
+    virtual UserId GetAnnotatingId() const ORTHANC_OVERRIDE
+    {
+      // Anonymous users cannot save annotations
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ForbiddenAccess);
+    }
+
+    virtual std::string Format() const ORTHANC_OVERRIDE
+    {
+      return "(guest)";
+    }
+
+    virtual ProjectRole GetRoleInProject(const std::string& projectId) const ORTHANC_OVERRIDE
+    {
+      return ProjectRole_Guest;
+    }
+  };
+
+
+  class EducationPluginAuthenticatedUser : public IAuthenticatedUser
+  {
+  public:
+    enum EducationRole
+    {
+      EducationRole_Administrator,
+      EducationRole_Standard,
+      EducationRole_Guest
+    };
+
+  private:
+    std::string            id_;
+    EducationRole          role_;
+    std::set<std::string>  instructorOfProjects_;
+    std::set<std::string>  learnerOfProjects_;
+
+  public:
+    explicit EducationPluginAuthenticatedUser(const Json::Value& authentication)
+    {
+      assert(Orthanc::SerializationToolbox::ReadString(authentication, "source") == "orthanc-education");
+
+      id_ = Orthanc::SerializationToolbox::ReadString(authentication, "id");
+
+      const std::string role = Orthanc::SerializationToolbox::ReadString(authentication, "role");
+
+      if (role == "admin")
+      {
+        role_ = EducationRole_Administrator;
+      }
+      else if (role == "standard")
+      {
+        role_ = EducationRole_Standard;
+      }
+      else if (role == "guest")
+      {
+        role_ = EducationRole_Guest;
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+      }
+
+      Orthanc::SerializationToolbox::ReadSetOfStrings(instructorOfProjects_, authentication, "instructor_of");
+      Orthanc::SerializationToolbox::ReadSetOfStrings(learnerOfProjects_, authentication, "learner_of");
+    }
+
+    virtual UserId GetAnnotatingId() const ORTHANC_OVERRIDE
+    {
+      switch (role_)
+      {
+      case EducationRole_Administrator:
+        return UserId(UserId::Type_Administrator);
+
+      case EducationRole_Standard:
+        return UserId(UserId::Type_Standard, id_);
+
+      case EducationRole_Guest:
+        // Anonymous users cannot save annotations
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ForbiddenAccess);
+
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+    }
+
+    virtual std::string Format() const ORTHANC_OVERRIDE
+    {
+      return id_;
+    }
+
+    virtual ProjectRole GetRoleInProject(const std::string& projectId) const ORTHANC_OVERRIDE
+    {
+      switch (role_)
+      {
+      case EducationRole_Administrator:
+        return ProjectRole_Instructor;
+
+      case EducationRole_Standard:
+        if (instructorOfProjects_.find(projectId) != instructorOfProjects_.end())
+        {
+          return ProjectRole_Instructor;
+        }
+        else if (learnerOfProjects_.find(projectId) != learnerOfProjects_.end())
+        {
+          return ProjectRole_Learner;
+        }
+        else
+        {
+          return ProjectRole_Guest;
+        }
+
+      case EducationRole_Guest:
+        return ProjectRole_Guest;
+
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+    }
+  };
+}
+
+
+IAuthenticatedUser* IAuthenticatedUser::FromHttpRequest(const OrthancPluginHttpRequest* request)
+{
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 9)
+
+  if (request->authenticationPayloadSize == 0)
+  {
+    // No authentication plugin is installed
+    return new RootUser;
+  }
+  else
+  {
+    const char* payload = reinterpret_cast<const char*>(request->authenticationPayload);
+
+    // We use "Json::Reader" as "Orthanc::ReadJson()" would write an
+    // error log if the authentication payload is not a JSON string
+    Json::Reader reader;
+
+    Json::Value authentication;
+    if (reader.parse(payload, payload + request->authenticationPayloadSize, authentication, false))
+    {
+      const std::string source = Orthanc::SerializationToolbox::ReadString(authentication, "source", "");
+
+      if (source == "orthanc-education")
+      {
+        return new EducationPluginAuthenticatedUser(authentication);
+      }
+    }
+
+    return new GuestUser;
+  }
+
+#else
+
+  // SDK is too old to support per-user authentication
+  return new RootUser;
+
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ViewerPlugin/Annotations/IAuthenticatedUser.h	Wed Aug 19 14:59:26 2026 +0200
@@ -0,0 +1,53 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
+ * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "UserId.h"
+
+#include <orthanc/OrthancCPlugin.h>
+
+#include <boost/noncopyable.hpp>
+
+class IAuthenticatedUser : public boost::noncopyable
+{
+public:
+  enum ProjectRole
+  {
+    ProjectRole_Instructor,
+    ProjectRole_Learner,
+    ProjectRole_Guest
+  };
+
+  virtual ~IAuthenticatedUser()
+  {
+  }
+
+  virtual UserId GetAnnotatingId() const = 0;
+
+  virtual std::string Format() const = 0;
+
+  virtual ProjectRole GetRoleInProject(const std::string& projectId) const = 0;
+
+  static IAuthenticatedUser* FromHttpRequest(const OrthancPluginHttpRequest* request);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ViewerPlugin/Annotations/UserId.cpp	Wed Aug 19 14:59:26 2026 +0200
@@ -0,0 +1,125 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
+ * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "../../Framework/PrecompiledHeadersWSI.h"
+#include "UserId.h"
+
+#include <OrthancException.h>
+#include <SerializationToolbox.h>
+#include <Toolbox.h>
+
+
+static const char* const KEY_TYPE = "type";
+static const char* const KEY_NAME = "name";
+
+
+void UserId::Setup(Type type,
+                   const std::string& name)
+{
+  type_ = type;
+  name_ = name;
+
+  switch (type_)
+  {
+  case Type_Invalid:
+  case Type_Administrator:
+    if (!name.empty())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+    break;
+
+  case Type_Standard:
+    if (name.empty())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+    break;
+
+  default:
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+  }
+}
+
+
+UserId::UserId(const Json::Value& serialized)
+{
+  Setup(static_cast<Type>(Orthanc::SerializationToolbox::ReadInteger(serialized, KEY_TYPE)),
+        Orthanc::SerializationToolbox::ReadString(serialized, KEY_NAME));
+}
+
+
+bool UserId::operator<(const UserId& other) const
+{
+  if (type_ < other.type_)
+  {
+    return true;
+  }
+  else if (type_ > other.type_)
+  {
+    return false;
+  }
+  else
+  {
+    return name_ < other.name_;
+  }
+}
+
+
+std::string UserId::GetKey() const
+{
+  switch (type_)
+  {
+  case Type_Administrator:
+    return "root";
+
+  case Type_Standard:
+  {
+    // The pipe character "|" is not part of Base64, so we can safely use it to separate components
+    std::string s;
+    Orthanc::Toolbox::EncodeBase64(s, name_);
+    return "user_" + s;
+  }
+
+  case Type_Invalid:
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+
+  default:
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+  }
+}
+
+
+void UserId::Serialize(Json::Value& target) const
+{
+  if (type_ == Type_Invalid)
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+  }
+  else
+  {
+    target = Json::objectValue;
+    target[KEY_TYPE] = static_cast<int>(type_);
+    target[KEY_NAME] = name_;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ViewerPlugin/Annotations/UserId.h	Wed Aug 19 14:59:26 2026 +0200
@@ -0,0 +1,80 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
+ * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include <json/value.h>
+#include <string>
+
+class UserId
+{
+public:
+  enum Type
+  {
+    Type_Administrator,
+    Type_Standard,
+    Type_Invalid
+  };
+
+private:
+  Type         type_;
+  std::string  name_;
+
+  void Setup(Type type,
+             const std::string& name);
+
+public:
+  explicit UserId()
+  {
+    Setup(Type_Invalid, "");
+  }
+
+  explicit UserId(Type type)
+  {
+    Setup(type, "");
+  }
+
+  UserId(Type type,
+         const std::string& name)
+  {
+    Setup(type, name);
+  }
+
+  explicit UserId(const Json::Value& serialized);
+
+  Type GetType() const
+  {
+    return type_;
+  }
+
+  const std::string& GetName() const
+  {
+    return name_;
+  }
+
+  bool operator<(const UserId& other) const;
+
+  std::string GetKey() const;
+
+  void Serialize(Json::Value& target) const;
+};
--- a/ViewerPlugin/CMakeLists.txt	Wed Aug 19 14:54:26 2026 +0200
+++ b/ViewerPlugin/CMakeLists.txt	Wed Aug 19 14:59:26 2026 +0200
@@ -186,14 +186,14 @@
 #####################################################################
 
 set(ORTHANC_WSI_SOURCES
+  Annotations/IAuthenticatedUser.cpp
+  Annotations/UserId.cpp
   DicomPyramidCache.cpp
-  IAuthenticatedUser.cpp
   IIIF.cpp
   OrthancPluginConnection.cpp
   OrthancPyramidFrameFetcher.cpp
   Plugin.cpp
   RawTile.cpp
-  UserId.cpp
 
   ${ORTHANC_WSI_DIR}/Framework/ColorSpaces.cpp
   ${ORTHANC_WSI_DIR}/Framework/DicomToolbox.cpp
--- a/ViewerPlugin/IAuthenticatedUser.cpp	Wed Aug 19 14:54:26 2026 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
- * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "IAuthenticatedUser.h"
-
-#include <Compatibility.h>
-#include <OrthancException.h>
-#include <SerializationToolbox.h>
-#include <Toolbox.h>
-
-#include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h"
-
-#include <cassert>
-#include <json/reader.h>
-
-namespace
-{
-  // If Orthanc runs without an authentication plugin
-  class RootUser : public IAuthenticatedUser
-  {
-  public:
-    virtual UserId GetAnnotatingId() const ORTHANC_OVERRIDE
-    {
-      return UserId(UserId::Type_Administrator);
-    }
-
-    virtual std::string Format() const ORTHANC_OVERRIDE
-    {
-      return "(root)";
-    }
-
-    virtual ProjectRole GetRoleInProject(const std::string& projectId) const ORTHANC_OVERRIDE
-    {
-      return ProjectRole_Instructor;
-    }
-  };
-
-
-  class GuestUser : public IAuthenticatedUser
-  {
-  public:
-    virtual UserId GetAnnotatingId() const ORTHANC_OVERRIDE
-    {
-      // Anonymous users cannot save annotations
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ForbiddenAccess);
-    }
-
-    virtual std::string Format() const ORTHANC_OVERRIDE
-    {
-      return "(guest)";
-    }
-
-    virtual ProjectRole GetRoleInProject(const std::string& projectId) const ORTHANC_OVERRIDE
-    {
-      return ProjectRole_Guest;
-    }
-  };
-
-
-  class EducationPluginAuthenticatedUser : public IAuthenticatedUser
-  {
-  public:
-    enum EducationRole
-    {
-      EducationRole_Administrator,
-      EducationRole_Standard,
-      EducationRole_Guest
-    };
-
-  private:
-    std::string            id_;
-    EducationRole          role_;
-    std::set<std::string>  instructorOfProjects_;
-    std::set<std::string>  learnerOfProjects_;
-
-  public:
-    explicit EducationPluginAuthenticatedUser(const Json::Value& authentication)
-    {
-      assert(Orthanc::SerializationToolbox::ReadString(authentication, "source") == "orthanc-education");
-
-      id_ = Orthanc::SerializationToolbox::ReadString(authentication, "id");
-
-      const std::string role = Orthanc::SerializationToolbox::ReadString(authentication, "role");
-
-      if (role == "admin")
-      {
-        role_ = EducationRole_Administrator;
-      }
-      else if (role == "standard")
-      {
-        role_ = EducationRole_Standard;
-      }
-      else if (role == "guest")
-      {
-        role_ = EducationRole_Guest;
-      }
-      else
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
-      }
-
-      Orthanc::SerializationToolbox::ReadSetOfStrings(instructorOfProjects_, authentication, "instructor_of");
-      Orthanc::SerializationToolbox::ReadSetOfStrings(learnerOfProjects_, authentication, "learner_of");
-    }
-
-    virtual UserId GetAnnotatingId() const ORTHANC_OVERRIDE
-    {
-      switch (role_)
-      {
-      case EducationRole_Administrator:
-        return UserId(UserId::Type_Administrator);
-
-      case EducationRole_Standard:
-        return UserId(UserId::Type_Standard, id_);
-
-      case EducationRole_Guest:
-        // Anonymous users cannot save annotations
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ForbiddenAccess);
-
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-      }
-    }
-
-    virtual std::string Format() const ORTHANC_OVERRIDE
-    {
-      return id_;
-    }
-
-    virtual ProjectRole GetRoleInProject(const std::string& projectId) const ORTHANC_OVERRIDE
-    {
-      switch (role_)
-      {
-      case EducationRole_Administrator:
-        return ProjectRole_Instructor;
-
-      case EducationRole_Standard:
-        if (instructorOfProjects_.find(projectId) != instructorOfProjects_.end())
-        {
-          return ProjectRole_Instructor;
-        }
-        else if (learnerOfProjects_.find(projectId) != learnerOfProjects_.end())
-        {
-          return ProjectRole_Learner;
-        }
-        else
-        {
-          return ProjectRole_Guest;
-        }
-
-      case EducationRole_Guest:
-        return ProjectRole_Guest;
-
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-      }
-    }
-  };
-}
-
-
-IAuthenticatedUser* IAuthenticatedUser::FromHttpRequest(const OrthancPluginHttpRequest* request)
-{
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 9)
-
-  if (request->authenticationPayloadSize == 0)
-  {
-    // No authentication plugin is installed
-    return new RootUser;
-  }
-  else
-  {
-    const char* payload = reinterpret_cast<const char*>(request->authenticationPayload);
-
-    // We use "Json::Reader" as "Orthanc::ReadJson()" would write an
-    // error log if the authentication payload is not a JSON string
-    Json::Reader reader;
-
-    Json::Value authentication;
-    if (reader.parse(payload, payload + request->authenticationPayloadSize, authentication, false))
-    {
-      const std::string source = Orthanc::SerializationToolbox::ReadString(authentication, "source", "");
-
-      if (source == "orthanc-education")
-      {
-        return new EducationPluginAuthenticatedUser(authentication);
-      }
-    }
-
-    return new GuestUser;
-  }
-
-#else
-
-  // SDK is too old to support per-user authentication
-  return new RootUser;
-
-#endif
-}
--- a/ViewerPlugin/IAuthenticatedUser.h	Wed Aug 19 14:54:26 2026 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
- * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "UserId.h"
-
-#include <orthanc/OrthancCPlugin.h>
-
-#include <boost/noncopyable.hpp>
-
-class IAuthenticatedUser : public boost::noncopyable
-{
-public:
-  enum ProjectRole
-  {
-    ProjectRole_Instructor,
-    ProjectRole_Learner,
-    ProjectRole_Guest
-  };
-
-  virtual ~IAuthenticatedUser()
-  {
-  }
-
-  virtual UserId GetAnnotatingId() const = 0;
-
-  virtual std::string Format() const = 0;
-
-  virtual ProjectRole GetRoleInProject(const std::string& projectId) const = 0;
-
-  static IAuthenticatedUser* FromHttpRequest(const OrthancPluginHttpRequest* request);
-};
--- a/ViewerPlugin/Plugin.cpp	Wed Aug 19 14:54:26 2026 +0200
+++ b/ViewerPlugin/Plugin.cpp	Wed Aug 19 14:59:26 2026 +0200
@@ -23,8 +23,8 @@
 
 #include "../Framework/PrecompiledHeadersWSI.h"
 
+#include "Annotations/IAuthenticatedUser.h"
 #include "DicomPyramidCache.h"
-#include "IAuthenticatedUser.h"
 #include "IIIF.h"
 #include "OrthancPyramidFrameFetcher.h"
 #include "RawTile.h"
--- a/ViewerPlugin/UserId.cpp	Wed Aug 19 14:54:26 2026 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
- * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "../Framework/PrecompiledHeadersWSI.h"
-
-#include "UserId.h"
-
-#include <OrthancException.h>
-#include <SerializationToolbox.h>
-#include <Toolbox.h>
-
-
-static const char* const KEY_TYPE = "type";
-static const char* const KEY_NAME = "name";
-
-
-void UserId::Setup(Type type,
-                   const std::string& name)
-{
-  type_ = type;
-  name_ = name;
-
-  switch (type_)
-  {
-  case Type_Invalid:
-  case Type_Administrator:
-    if (!name.empty())
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-    break;
-
-  case Type_Standard:
-    if (name.empty())
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-    break;
-
-  default:
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-  }
-}
-
-
-UserId::UserId(const Json::Value& serialized)
-{
-  Setup(static_cast<Type>(Orthanc::SerializationToolbox::ReadInteger(serialized, KEY_TYPE)),
-        Orthanc::SerializationToolbox::ReadString(serialized, KEY_NAME));
-}
-
-
-bool UserId::operator<(const UserId& other) const
-{
-  if (type_ < other.type_)
-  {
-    return true;
-  }
-  else if (type_ > other.type_)
-  {
-    return false;
-  }
-  else
-  {
-    return name_ < other.name_;
-  }
-}
-
-
-std::string UserId::GetKey() const
-{
-  switch (type_)
-  {
-  case Type_Administrator:
-    return "root";
-
-  case Type_Standard:
-  {
-    // The pipe character "|" is not part of Base64, so we can safely use it to separate components
-    std::string s;
-    Orthanc::Toolbox::EncodeBase64(s, name_);
-    return "user_" + s;
-  }
-
-  case Type_Invalid:
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-
-  default:
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-  }
-}
-
-
-void UserId::Serialize(Json::Value& target) const
-{
-  if (type_ == Type_Invalid)
-  {
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-  }
-  else
-  {
-    target = Json::objectValue;
-    target[KEY_TYPE] = static_cast<int>(type_);
-    target[KEY_NAME] = name_;
-  }
-}
--- a/ViewerPlugin/UserId.h	Wed Aug 19 14:54:26 2026 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2026 Orthanc Team SRL, Belgium
- * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include <json/value.h>
-#include <string>
-
-class UserId
-{
-public:
-  enum Type
-  {
-    Type_Administrator,
-    Type_Standard,
-    Type_Invalid
-  };
-
-private:
-  Type         type_;
-  std::string  name_;
-
-  void Setup(Type type,
-             const std::string& name);
-
-public:
-  explicit UserId()
-  {
-    Setup(Type_Invalid, "");
-  }
-
-  explicit UserId(Type type)
-  {
-    Setup(type, "");
-  }
-
-  UserId(Type type,
-         const std::string& name)
-  {
-    Setup(type, name);
-  }
-
-  explicit UserId(const Json::Value& serialized);
-
-  Type GetType() const
-  {
-    return type_;
-  }
-
-  const std::string& GetName() const
-  {
-    return name_;
-  }
-
-  bool operator<(const UserId& other) const;
-
-  std::string GetKey() const;
-
-  void Serialize(Json::Value& target) const;
-};