Mercurial > hg > orthanc-authorization
comparison Plugin/PermissionParser.cpp @ 71:30fb3ce960d9
configurable user permissions
author | Alain Mazy <am@osimis.io> |
---|---|
date | Wed, 22 Feb 2023 13:13:38 +0100 |
parents | |
children | aa73b10c2db9 |
comparison
equal
deleted
inserted
replaced
70:786b202ef24e | 71:30fb3ce960d9 |
---|---|
1 /** | |
2 * Advanced authorization plugin for Orthanc | |
3 * Copyright (C) 2017-2023 Osimis S.A., Belgium | |
4 * | |
5 * This program is free software: you can redistribute it and/or | |
6 * modify it under the terms of the GNU Affero General Public License | |
7 * as published by the Free Software Foundation, either version 3 of | |
8 * the License, or (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, but | |
11 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Affero General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Affero General Public License | |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 **/ | |
18 | |
19 #include "PermissionParser.h" | |
20 | |
21 #include <Toolbox.h> | |
22 #include <OrthancException.h> | |
23 #include <Logging.h> | |
24 | |
25 namespace OrthancPlugins | |
26 { | |
27 PermissionPattern::PermissionPattern(const OrthancPluginHttpMethod& method, const std::string& patternRegex, const std::string& permissions) : | |
28 method(method), | |
29 pattern(patternRegex) | |
30 { | |
31 std::vector<std::string> permissionsVector; | |
32 Orthanc::Toolbox::TokenizeString(permissionsVector, permissions, '|'); | |
33 | |
34 for (size_t i = 0; i < permissionsVector.size(); ++i) | |
35 { | |
36 this->permissions.insert(permissionsVector[i]); | |
37 } | |
38 } | |
39 | |
40 | |
41 static void Replace(std::string& text, const std::string& findText, const std::string& replaceText) | |
42 { | |
43 size_t pos = text.find(findText); | |
44 if (pos != std::string::npos) | |
45 { | |
46 text = text.replace(pos, findText.size(), replaceText); | |
47 } | |
48 } | |
49 | |
50 | |
51 static void StripLeadingAndTrailingSlashes(std::string& text) | |
52 { | |
53 if (text.size() > 1 && text[0] == '/') | |
54 { | |
55 text = text.substr(1, text.size() -1); | |
56 } | |
57 if (text.size() > 1 && text[text.size() - 1] == '/') | |
58 { | |
59 text = text.substr(0, text.size() -1); | |
60 } | |
61 } | |
62 | |
63 | |
64 PermissionParser::PermissionParser(const std::string& dicomWebRoot, const std::string& oe2Root) : | |
65 dicomWebRoot_(dicomWebRoot), | |
66 oe2Root_(oe2Root) | |
67 { | |
68 } | |
69 | |
70 void PermissionParser::Add(const Json::Value& configuration) | |
71 { | |
72 if (configuration.type() != Json::arrayValue) | |
73 { | |
74 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType, "Permissions should be an array."); | |
75 } | |
76 | |
77 for (Json::ArrayIndex i = 0; i < configuration.size(); ++i) | |
78 { | |
79 const Json::Value& permission = configuration[i]; | |
80 if (permission.type() != Json::arrayValue || permission.size() < 3) | |
81 { | |
82 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType, "Permissions elements should be an array of min size 3."); | |
83 } | |
84 | |
85 Add(permission[0].asString(), // 0 = HTTP method | |
86 permission[1].asString(), // 1 = pattern | |
87 permission[2].asString() // 2 = list of | separated permissions (no space) | |
88 // 3 = optional comment | |
89 ); | |
90 } | |
91 | |
92 } | |
93 | |
94 void PermissionParser::Add(const std::string& method, | |
95 const std::string& patternRegex, | |
96 const std::string& permission) | |
97 { | |
98 std::string lowerCaseMethod; | |
99 Orthanc::Toolbox::ToLowerCase(lowerCaseMethod, method); | |
100 OrthancPluginHttpMethod parsedMethod = OrthancPluginHttpMethod_Get; | |
101 | |
102 if (lowerCaseMethod == "post") | |
103 { | |
104 parsedMethod = OrthancPluginHttpMethod_Post; | |
105 } | |
106 else if (lowerCaseMethod == "put") | |
107 { | |
108 parsedMethod = OrthancPluginHttpMethod_Put; | |
109 } | |
110 else if (lowerCaseMethod == "delete") | |
111 { | |
112 parsedMethod = OrthancPluginHttpMethod_Delete; | |
113 } | |
114 else if (lowerCaseMethod == "get") | |
115 { | |
116 parsedMethod = OrthancPluginHttpMethod_Get; | |
117 } | |
118 else | |
119 { | |
120 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, std::string("Invalid HTTP method ") + method); | |
121 } | |
122 | |
123 std::string regex = patternRegex; | |
124 std::string strippedDicomWebRoot = dicomWebRoot_; | |
125 | |
126 StripLeadingAndTrailingSlashes(strippedDicomWebRoot); | |
127 Replace(regex, "DICOM_WEB_ROOT", strippedDicomWebRoot); | |
128 | |
129 LOG(WARNING) << "Authorization plugin: adding a new permission pattern: " << lowerCaseMethod << " " << regex << " - " << permission; | |
130 | |
131 permissionsPattern_.push_back(PermissionPattern(parsedMethod, regex, permission)); | |
132 } | |
133 | |
134 bool PermissionParser::Parse(std::set<std::string>& permissions, | |
135 std::string& matchedPattern, | |
136 const OrthancPluginHttpMethod& method, | |
137 const std::string& uri) const | |
138 { | |
139 // The mutex below should not be necessary, but we prefer to | |
140 // ensure thread safety in boost::regex | |
141 boost::mutex::scoped_lock lock(mutex_); | |
142 | |
143 | |
144 for (std::list<PermissionPattern>::const_iterator it = permissionsPattern_.begin(); | |
145 it != permissionsPattern_.end(); ++it) | |
146 { | |
147 if (method == it->method) | |
148 { | |
149 boost::smatch what; | |
150 if (boost::regex_match(uri, what, it->pattern)) | |
151 { | |
152 matchedPattern = it->pattern.expression(); | |
153 permissions = it->permissions; | |
154 return true; | |
155 } | |
156 } | |
157 } | |
158 | |
159 return false; | |
160 } | |
161 } |