Mercurial > hg > orthanc-authorization
annotate Plugin/CachedAuthorizationService.cpp @ 159:12f23fcf3ba6
back to mainline
author | Alain Mazy <am@osimis.io> |
---|---|
date | Mon, 25 Mar 2024 13:04:09 +0100 |
parents | 9be1ee2b8fe1 |
children | c4b908970ae4 |
rev | line source |
---|---|
1 | 1 /** |
2 * Advanced authorization plugin for Orthanc | |
68 | 3 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
150 | 4 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
1 | 5 * |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU Affero General Public License | |
8 * as published by the Free Software Foundation, either version 3 of | |
9 * the License, or (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Affero General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Affero General Public License | |
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 **/ | |
19 | |
20 #include "CachedAuthorizationService.h" | |
115
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
21 #include "AuthorizationWebService.h" |
1 | 22 |
32 | 23 #include <OrthancException.h> |
71 | 24 #include <Toolbox.h> |
1 | 25 |
26 #include <boost/lexical_cast.hpp> | |
27 | |
28 namespace OrthancPlugins | |
29 { | |
30 std::string CachedAuthorizationService::ComputeKey(OrthancPluginHttpMethod method, | |
31 const AccessedResource& access, | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
32 const Token* token, |
1 | 33 const std::string& tokenValue) const |
34 { | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
35 if (token != NULL) |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
36 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
37 return (boost::lexical_cast<std::string>(method) + "|" + |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
38 boost::lexical_cast<std::string>(access.GetLevel()) + "|" + |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
39 access.GetOrthancId() + "|" + token->GetKey() + "|" + tokenValue); |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
40 } |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
41 else |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
42 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
43 return (boost::lexical_cast<std::string>(method) + "|" + |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
44 boost::lexical_cast<std::string>(access.GetLevel()) + "|" + |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
45 access.GetOrthancId() + "|anonymous"); |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
46 } |
1 | 47 } |
48 | |
49 | |
71 | 50 std::string CachedAuthorizationService::ComputeKey(const std::string& permission, |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
51 const Token* token, |
71 | 52 const std::string& tokenValue) const |
53 { | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
54 if (token != NULL) |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
55 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
56 return (permission + "|" + token->GetKey() + "|" + tokenValue); |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
57 } |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
58 else |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
59 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
60 return (permission + "|anonymous"); |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
61 } |
71 | 62 } |
63 | |
64 | |
65 CachedAuthorizationService::CachedAuthorizationService(BaseAuthorizationService* decorated /* takes ownership */, | |
1 | 66 ICacheFactory& factory) : |
67 decorated_(decorated), | |
68 cache_(factory.Create()) | |
69 { | |
70 if (decorated_.get() == NULL) | |
71 { | |
72 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
73 } | |
74 } | |
75 | |
76 | |
71 | 77 bool CachedAuthorizationService::IsGrantedInternal(unsigned int& validity, |
78 OrthancPluginHttpMethod method, | |
79 const AccessedResource& access, | |
80 const Token* token, | |
81 const std::string& tokenValue) | |
1 | 82 { |
83 assert(decorated_.get() != NULL); | |
84 | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
85 std::string key = ComputeKey(method, access, token, tokenValue); |
1 | 86 std::string value; |
87 | |
88 if (cache_->Retrieve(value, key)) | |
89 { | |
90 // Return the previously cached value | |
91 return (value == "1"); | |
92 } | |
93 | |
71 | 94 bool granted = decorated_->IsGrantedInternal(validity, method, access, token, tokenValue); |
1 | 95 |
96 if (granted) | |
97 { | |
98 if (validity > 0) | |
99 { | |
100 cache_->Store(key, "1", validity); | |
101 } | |
102 | |
103 return true; | |
104 } | |
105 else | |
106 { | |
107 if (validity > 0) | |
108 { | |
109 cache_->Store(key, "0", validity); | |
110 } | |
111 | |
112 return false; | |
113 } | |
114 } | |
115 | |
116 | |
115
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
117 bool CachedAuthorizationService::GetUserProfileInternal(unsigned int& validityNotUsed, |
109 | 118 UserProfile& profile /* out */, |
71 | 119 const Token* token, |
120 const std::string& tokenValue) | |
121 { | |
115
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
122 assert(decorated_.get() != NULL); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
123 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
124 std::string key = ComputeKey("user-profile", token, tokenValue); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
125 std::string serializedProfile; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
126 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
127 if (cache_->Retrieve(serializedProfile, key)) |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
128 { |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
129 // Return the previously cached profile |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
130 Json::Value jsonProfile; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
131 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
132 Orthanc::Toolbox::ReadJson(jsonProfile, serializedProfile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
133 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
134 AuthorizationWebService::FromJson(profile, jsonProfile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
135 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
136 profile.tokenKey = token->GetKey(); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
137 profile.tokenType = token->GetType(); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
138 profile.tokenValue = tokenValue; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
139 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
140 return true; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
141 } |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
142 else |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
143 { |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
144 unsigned int validity; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
145 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
146 if (decorated_->GetUserProfileInternal(validity, profile, token, tokenValue)) |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
147 { |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
148 Json::Value jsonProfile; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
149 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
150 AuthorizationWebService::ToJson(jsonProfile, profile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
151 Orthanc::Toolbox::WriteFastJson(serializedProfile, jsonProfile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
152 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
153 cache_->Store(key, serializedProfile, validity); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
154 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
155 return true; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
156 } |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
157 } |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
158 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
159 return false; |
71 | 160 } |
161 | |
162 bool CachedAuthorizationService::HasUserPermissionInternal(unsigned int& validity, | |
163 const std::string& permission, | |
113 | 164 const UserProfile& profile) |
1 | 165 { |
166 assert(decorated_.get() != NULL); | |
167 | |
113 | 168 Token token(profile.tokenType, profile.tokenKey); |
169 std::string key = ComputeKey(permission, &token, profile.tokenValue); | |
71 | 170 std::string value; |
171 | |
172 if (cache_->Retrieve(value, key)) | |
173 { | |
174 // Return the previously cached value | |
175 return (value == "1"); | |
176 } | |
177 | |
113 | 178 bool granted = decorated_->HasUserPermissionInternal(validity, permission, profile); |
71 | 179 |
180 if (granted) | |
181 { | |
182 if (validity > 0) | |
183 { | |
184 cache_->Store(key, "1", validity); | |
185 } | |
186 | |
187 return true; | |
188 } | |
189 else | |
190 { | |
191 if (validity > 0) | |
192 { | |
193 cache_->Store(key, "0", validity); | |
194 } | |
195 | |
196 return false; | |
197 } | |
1 | 198 } |
69
af44dce56328
new 'auth/user-profile' Rest API route
Alain Mazy <am@osimis.io>
parents:
68
diff
changeset
|
199 |
71 | 200 |
69
af44dce56328
new 'auth/user-profile' Rest API route
Alain Mazy <am@osimis.io>
parents:
68
diff
changeset
|
201 |
1 | 202 } |