Mercurial > hg > orthanc-education
view Sources/Permissions/AuthenticatedUser.cpp @ 77:80b663d5f8fe default tip
replaced boost::math::iround() by Orthanc::Math::llround()
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Tue, 27 Jan 2026 17:05:03 +0100 |
| parents | 0f8c46d755e2 |
| children |
line wrap: on
line source
/** * SPDX-FileCopyrightText: 2024-2026 Sebastien Jodogne, EPL UCLouvain, Belgium * SPDX-License-Identifier: AGPL-3.0-or-later */ /** * Orthanc for Education * Copyright (C) 2024-2026 Sebastien Jodogne, EPL 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 "AuthenticatedUser.h" #include "../HttpToolbox.h" #include <SerializationToolbox.h> static const char* const FIELD_ROLE = "role"; static const char* const FIELD_INSTRUCTOR = "instructor_of"; static const char* const FIELD_LEARNER = "learner_of"; static const char* const FIELD_ID = "id"; static const char* const FIELD_LTI_PROJECT_ID = "lti_project_id"; void AuthenticatedUser::Serialize(Json::Value& payload) const { payload = Json::objectValue; payload[FIELD_ROLE] = EnumerationToString(role_); if (hasUserId_) { payload[FIELD_ID] = userId_; } Orthanc::SerializationToolbox::WriteSetOfStrings(payload, projectsAsInstructor_, FIELD_INSTRUCTOR); Orthanc::SerializationToolbox::WriteSetOfStrings(payload, projectsAsLearner_, FIELD_LEARNER); if (hasLtiProjectId_) { payload[FIELD_LTI_PROJECT_ID] = boost::lexical_cast<std::string>(ltiProjectId_); } } AuthenticatedUser* AuthenticatedUser::Unserialize(const Json::Value& payload) { Role role = ParseRole(Orthanc::SerializationToolbox::ReadString(payload, FIELD_ROLE)); std::unique_ptr<AuthenticatedUser> user(new AuthenticatedUser(role)); if (payload.isMember(FIELD_ID)) { user->SetUserId(Orthanc::SerializationToolbox::ReadString(payload, FIELD_ID)); } Orthanc::SerializationToolbox::ReadSetOfStrings(user->projectsAsInstructor_, payload, FIELD_INSTRUCTOR); Orthanc::SerializationToolbox::ReadSetOfStrings(user->projectsAsLearner_, payload, FIELD_LEARNER); if (payload.isMember(FIELD_LTI_PROJECT_ID)) { user->SetLtiProjectId(Orthanc::SerializationToolbox::ReadString(payload, FIELD_LTI_PROJECT_ID)); } return user.release(); } AuthenticatedUser::AuthenticatedUser(Role role) : role_(role), hasUserId_(false), hasLtiProjectId_(false) { } void AuthenticatedUser::SetUserId(const std::string& id) { hasUserId_ = true; userId_ = id; } const std::string& AuthenticatedUser::GetUserId() const { if (hasUserId_) { return userId_; } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } } void AuthenticatedUser::SetLtiProjectId(const std::string& projectId) { if (projectId.empty()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { hasLtiProjectId_ = true; ltiProjectId_ = projectId; } } const std::string& AuthenticatedUser::GetLtiProjectId() const { if (hasLtiProjectId_) { return ltiProjectId_; } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } } std::string AuthenticatedUser::Format() const { std::string s = std::string(hasUserId_ ? userId_ : "?") + " with role " + EnumerationToString(role_); if (hasLtiProjectId_) { s += " in LTI project " + boost::lexical_cast<std::string>(ltiProjectId_); } return s; } void AuthenticatedUser::ToHttpRequest(OrthancPlugins::MemoryBuffer& payload) const { Json::Value json; Serialize(json); payload.AssignJson(json); } void AuthenticatedUser::ForgeJWT(std::string& jwt, LTIContext& context, unsigned int maxAge /* in seconds */) const { Json::Value payload; Serialize(payload); context.ForgeJWT(jwt, payload, maxAge); } AuthenticatedUser* AuthenticatedUser::FromLti(const IPermissionContext& context, const Json::Value& payload) { Json::Value ltiContext; int64_t contextId; if (!HttpToolbox::LookupJsonObject(ltiContext, payload, "https://purl.imsglobal.org/spec/lti/claim/context") || !Orthanc::SerializationToolbox::ParseInteger64(contextId, Orthanc::SerializationToolbox::ReadString(ltiContext, "id"))) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, "Missing LTI context ID"); } std::string projectId; if (!context.LookupProjectFromLtiContext(projectId, contextId)) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, "Unknown LTI context ID: " + boost::lexical_cast<std::string>(contextId)); } std::unique_ptr<AuthenticatedUser> user(new AuthenticatedUser(Role_Standard)); user->SetLtiProjectId(projectId); std::set<std::string> roles; Orthanc::SerializationToolbox::ReadSetOfStrings(roles, payload, "https://purl.imsglobal.org/spec/lti/claim/roles"); if (roles.find("http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor") != roles.end()) { user->AddInstructorOfProject(projectId); } else if (roles.find("http://purl.imsglobal.org/vocab/lis/v2/membership#Learner") != roles.end()) { user->AddLearnerOfProject(projectId); } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, "Unknown user type in LTI"); } const std::string email = Orthanc::SerializationToolbox::ReadString(payload, "email", ""); if (!email.empty()) { /** * This only happens if option "Share launcher's email with * tool" is set to "Always" in the Moodle configuration (in the * "Privacy" tab"). **/ user->SetUserId(email); } return user.release(); } AuthenticatedUser* AuthenticatedUser::FromHttpRequest(const OrthancPluginHttpRequest* request) { Json::Value payload; if (Orthanc::Toolbox::ReadJson(payload, request->authenticationPayload, request->authenticationPayloadSize)) { return Unserialize(payload); } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_Unauthorized); } } AuthenticatedUser* AuthenticatedUser::FromJWT(LTIContext& context, const std::string& jwt) { JWT parsed(jwt); if (context.VerifyJWT(parsed)) { return Unserialize(parsed.GetPayload()); } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); } } AuthenticatedUser* AuthenticatedUser::CreateAdministrator(const std::string& userId) { std::unique_ptr<AuthenticatedUser> user(new AuthenticatedUser(Role_Administrator)); user->SetUserId(userId); return user.release(); } AuthenticatedUser* AuthenticatedUser::CreateStandardUser(const IPermissionContext& context, const std::string& userId) { std::unique_ptr<AuthenticatedUser> user(new AuthenticatedUser(Role_Standard)); user->SetUserId(userId); context.LookupRolesOfUser(user->projectsAsInstructor_, user->projectsAsLearner_, userId); return user.release(); }
