Mercurial > hg > orthanc-authorization
annotate Plugin/CachedAuthorizationService.cpp @ 143:98f22123512a
sync
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 20 Dec 2023 21:52:33 +0100 |
parents | 0eed78c1e177 |
children | 9be1ee2b8fe1 |
rev | line source |
---|---|
1 | 1 /** |
2 * Advanced authorization plugin for Orthanc | |
68 | 3 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
1 | 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 "CachedAuthorizationService.h" | |
115
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
20 #include "AuthorizationWebService.h" |
1 | 21 |
32 | 22 #include <OrthancException.h> |
71 | 23 #include <Toolbox.h> |
1 | 24 |
25 #include <boost/lexical_cast.hpp> | |
26 | |
27 namespace OrthancPlugins | |
28 { | |
29 std::string CachedAuthorizationService::ComputeKey(OrthancPluginHttpMethod method, | |
30 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
|
31 const Token* token, |
1 | 32 const std::string& tokenValue) const |
33 { | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
34 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
|
35 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
36 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
|
37 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
|
38 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
|
39 } |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
40 else |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
41 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
42 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
|
43 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
|
44 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
|
45 } |
1 | 46 } |
47 | |
48 | |
71 | 49 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
|
50 const Token* token, |
71 | 51 const std::string& tokenValue) const |
52 { | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
53 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
|
54 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
55 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
|
56 } |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
57 else |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
58 { |
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
59 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
|
60 } |
71 | 61 } |
62 | |
63 | |
64 CachedAuthorizationService::CachedAuthorizationService(BaseAuthorizationService* decorated /* takes ownership */, | |
1 | 65 ICacheFactory& factory) : |
66 decorated_(decorated), | |
67 cache_(factory.Create()) | |
68 { | |
69 if (decorated_.get() == NULL) | |
70 { | |
71 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
72 } | |
73 } | |
74 | |
75 | |
71 | 76 bool CachedAuthorizationService::IsGrantedInternal(unsigned int& validity, |
77 OrthancPluginHttpMethod method, | |
78 const AccessedResource& access, | |
79 const Token* token, | |
80 const std::string& tokenValue) | |
1 | 81 { |
82 assert(decorated_.get() != NULL); | |
83 | |
72
e381ba725669
new PUT auth/tokens/{token-type} API route + updated interface with WebService
Alain Mazy <am@osimis.io>
parents:
71
diff
changeset
|
84 std::string key = ComputeKey(method, access, token, tokenValue); |
1 | 85 std::string value; |
86 | |
87 if (cache_->Retrieve(value, key)) | |
88 { | |
89 // Return the previously cached value | |
90 return (value == "1"); | |
91 } | |
92 | |
71 | 93 bool granted = decorated_->IsGrantedInternal(validity, method, access, token, tokenValue); |
1 | 94 |
95 if (granted) | |
96 { | |
97 if (validity > 0) | |
98 { | |
99 cache_->Store(key, "1", validity); | |
100 } | |
101 | |
102 return true; | |
103 } | |
104 else | |
105 { | |
106 if (validity > 0) | |
107 { | |
108 cache_->Store(key, "0", validity); | |
109 } | |
110 | |
111 return false; | |
112 } | |
113 } | |
114 | |
115 | |
115
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
116 bool CachedAuthorizationService::GetUserProfileInternal(unsigned int& validityNotUsed, |
109 | 117 UserProfile& profile /* out */, |
71 | 118 const Token* token, |
119 const std::string& tokenValue) | |
120 { | |
115
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
121 assert(decorated_.get() != NULL); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
122 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
123 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
|
124 std::string serializedProfile; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
125 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
126 if (cache_->Retrieve(serializedProfile, key)) |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
127 { |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
128 // Return the previously cached profile |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
129 Json::Value jsonProfile; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
130 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
131 Orthanc::Toolbox::ReadJson(jsonProfile, serializedProfile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
132 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
133 AuthorizationWebService::FromJson(profile, jsonProfile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
134 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
135 profile.tokenKey = token->GetKey(); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
136 profile.tokenType = token->GetType(); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
137 profile.tokenValue = tokenValue; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
138 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
139 return true; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
140 } |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
141 else |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
142 { |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
143 unsigned int validity; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
144 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
145 if (decorated_->GetUserProfileInternal(validity, profile, token, tokenValue)) |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
146 { |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
147 Json::Value jsonProfile; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
148 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
149 AuthorizationWebService::ToJson(jsonProfile, profile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
150 Orthanc::Toolbox::WriteFastJson(serializedProfile, jsonProfile); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
151 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
152 cache_->Store(key, serializedProfile, validity); |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
153 |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
154 return true; |
0eed78c1e177
cache the UserProfile + updated http filter logic
Alain Mazy <am@osimis.io>
parents:
113
diff
changeset
|
155 } |
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 return false; |
71 | 159 } |
160 | |
161 bool CachedAuthorizationService::HasUserPermissionInternal(unsigned int& validity, | |
162 const std::string& permission, | |
113 | 163 const UserProfile& profile) |
1 | 164 { |
165 assert(decorated_.get() != NULL); | |
166 | |
113 | 167 Token token(profile.tokenType, profile.tokenKey); |
168 std::string key = ComputeKey(permission, &token, profile.tokenValue); | |
71 | 169 std::string value; |
170 | |
171 if (cache_->Retrieve(value, key)) | |
172 { | |
173 // Return the previously cached value | |
174 return (value == "1"); | |
175 } | |
176 | |
113 | 177 bool granted = decorated_->HasUserPermissionInternal(validity, permission, profile); |
71 | 178 |
179 if (granted) | |
180 { | |
181 if (validity > 0) | |
182 { | |
183 cache_->Store(key, "1", validity); | |
184 } | |
185 | |
186 return true; | |
187 } | |
188 else | |
189 { | |
190 if (validity > 0) | |
191 { | |
192 cache_->Store(key, "0", validity); | |
193 } | |
194 | |
195 return false; | |
196 } | |
1 | 197 } |
69
af44dce56328
new 'auth/user-profile' Rest API route
Alain Mazy <am@osimis.io>
parents:
68
diff
changeset
|
198 |
71 | 199 |
69
af44dce56328
new 'auth/user-profile' Rest API route
Alain Mazy <am@osimis.io>
parents:
68
diff
changeset
|
200 |
1 | 201 } |