Mercurial > hg > orthanc-gcp
comparison Plugin/GoogleAccount.cpp @ 0:520cba9a0d42
initial commit
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 13 Jun 2019 14:57:22 +0200 |
parents | |
children | 798951e457f3 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:520cba9a0d42 |
---|---|
1 /** | |
2 * Google Cloud Platform credentials for DICOMweb and Orthanc | |
3 * Copyright (C) 2019 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 General Public License as | |
7 * published by the Free Software Foundation, either version 3 of the | |
8 * License, or (at your option) any later version. | |
9 * | |
10 * In addition, as a special exception, the copyright holders of this | |
11 * program give permission to link the code of its release with the | |
12 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
13 * that use the same license as the "OpenSSL" library), and distribute | |
14 * the linked executables. You must obey the GNU General Public License | |
15 * in all respects for all of the code used other than "OpenSSL". If you | |
16 * modify file(s) with this exception, you may extend this exception to | |
17 * your version of the file(s), but you are not obligated to do so. If | |
18 * you do not wish to do so, delete this exception statement from your | |
19 * version. If you delete this exception statement from all source files | |
20 * in the program, then also delete it here. | |
21 * | |
22 * This program is distributed in the hope that it will be useful, but | |
23 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
25 * General Public License for more details. | |
26 * | |
27 * You should have received a copy of the GNU General Public License | |
28 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
29 **/ | |
30 | |
31 | |
32 #include "GoogleAccount.h" | |
33 | |
34 | |
35 void GoogleAccount::LoadAuthorizedUser(const std::string& json) | |
36 { | |
37 google::cloud::StatusOr<google::cloud::storage::oauth2::AuthorizedUserCredentialsInfo> info = | |
38 google::cloud::storage::oauth2::ParseAuthorizedUserCredentials(json, "memory"); | |
39 | |
40 if (!info) | |
41 { | |
42 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
43 "Cannot parse authorized user configuration"); | |
44 } | |
45 else | |
46 { | |
47 type_ = Type_AuthorizedUser; | |
48 authorizedUser_.reset(new google::cloud::storage::oauth2::AuthorizedUserCredentialsInfo(*info)); | |
49 } | |
50 } | |
51 | |
52 | |
53 bool GoogleAccount::LoadServiceAccount(const OrthancPlugins::OrthancConfiguration& account) | |
54 { | |
55 std::string path; | |
56 | |
57 if (!account.LookupStringValue(path, "ServiceAccountFile")) | |
58 { | |
59 return false; | |
60 } | |
61 | |
62 OrthancPlugins::MemoryBuffer f; | |
63 f.ReadFile(path); | |
64 | |
65 std::string s; | |
66 f.ToString(s); | |
67 | |
68 google::cloud::StatusOr<google::cloud::storage::oauth2::ServiceAccountCredentialsInfo> info = | |
69 google::cloud::storage::oauth2::ParseServiceAccountCredentials(s, "memory"); | |
70 | |
71 if (!info) | |
72 { | |
73 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
74 "Cannot parse service account configuration at: " + path); | |
75 } | |
76 | |
77 type_ = Type_ServiceAccount; | |
78 serviceAccount_.reset(new google::cloud::storage::oauth2::ServiceAccountCredentialsInfo(*info)); | |
79 return true; | |
80 } | |
81 | |
82 | |
83 bool GoogleAccount::LoadAuthorizedUserFile(const OrthancPlugins::OrthancConfiguration& account) | |
84 { | |
85 std::string path; | |
86 | |
87 if (account.LookupStringValue(path, "AuthorizedUserFile")) | |
88 { | |
89 OrthancPlugins::MemoryBuffer f; | |
90 f.ReadFile(path); | |
91 | |
92 std::string s; | |
93 f.ToString(s); | |
94 | |
95 LoadAuthorizedUser(s); | |
96 return true; | |
97 } | |
98 else | |
99 { | |
100 return false; | |
101 } | |
102 } | |
103 | |
104 | |
105 bool GoogleAccount::LoadAuthorizedUserStrings(const OrthancPlugins::OrthancConfiguration& account) | |
106 { | |
107 std::string clientId, clientSecret, refreshToken; | |
108 | |
109 if (account.LookupStringValue(clientId, "AuthorizedUserClientId") && | |
110 account.LookupStringValue(clientSecret, "AuthorizedUserClientSecret") && | |
111 account.LookupStringValue(refreshToken, "AuthorizedUserRefreshToken")) | |
112 { | |
113 Json::Value json = Json::objectValue; | |
114 json["client_id"] = clientId; | |
115 json["client_secret"] = clientSecret; | |
116 json["refresh_token"] = refreshToken; | |
117 | |
118 LoadAuthorizedUser(json.toStyledString()); | |
119 return true; | |
120 } | |
121 else | |
122 { | |
123 return false; | |
124 } | |
125 } | |
126 | |
127 | |
128 GoogleAccount::GoogleAccount(const OrthancPlugins::OrthancConfiguration& account, | |
129 const std::string& name) : | |
130 name_(name) | |
131 { | |
132 if (!account.LookupStringValue(project_, "Project")) | |
133 { | |
134 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
135 "Missing \"Project\" option for account \"" + name + "\""); | |
136 } | |
137 | |
138 if (!account.LookupStringValue(location_, "Location")) | |
139 { | |
140 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
141 "Missing \"Location\" option for account \"" + name + "\""); | |
142 } | |
143 | |
144 if (!account.LookupStringValue(dataset_, "Dataset")) | |
145 { | |
146 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
147 "Missing \"Dataset\" option for account \"" + name + "\""); | |
148 } | |
149 | |
150 if (!account.LookupStringValue(dicomStore_, "DicomStore")) | |
151 { | |
152 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, | |
153 "Missing \"DicomStore\" option for account \"" + name + "\""); | |
154 } | |
155 | |
156 if (!LoadServiceAccount(account) && | |
157 !LoadAuthorizedUserFile(account) && | |
158 !LoadAuthorizedUserStrings(account)) | |
159 { | |
160 throw Orthanc::OrthancException( | |
161 Orthanc::ErrorCode_BadFileFormat, | |
162 "Missing \"ServiceAccount\" or \"AuthorizedUserXXX\" option for account \"" + name + "\""); | |
163 } | |
164 } | |
165 | |
166 | |
167 const google::cloud::storage::oauth2::AuthorizedUserCredentialsInfo& GoogleAccount::GetAuthorizedUser() const | |
168 { | |
169 if (authorizedUser_.get() == NULL) | |
170 { | |
171 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
172 } | |
173 else | |
174 { | |
175 return *authorizedUser_; | |
176 } | |
177 } | |
178 | |
179 | |
180 google::cloud::storage::oauth2::ServiceAccountCredentialsInfo& GoogleAccount::GetServiceAccount() const | |
181 { | |
182 if (serviceAccount_.get() == NULL) | |
183 { | |
184 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
185 } | |
186 else | |
187 { | |
188 return *serviceAccount_; | |
189 } | |
190 } | |
191 | |
192 | |
193 static std::string AddTrailingSlash(const std::string& url) | |
194 { | |
195 // Add a trailing slash if needed | |
196 if (url.empty() || | |
197 url[url.size() - 1] != '/') | |
198 { | |
199 return url + '/'; | |
200 } | |
201 else | |
202 { | |
203 return url; | |
204 } | |
205 } | |
206 | |
207 | |
208 bool GoogleAccount::UpdateServerDefinition(const std::string& dicomWebPluginRoot, | |
209 const std::string& baseGoogleUrl, | |
210 const std::string& token) const | |
211 { | |
212 std::string url = (AddTrailingSlash(baseGoogleUrl) + | |
213 "projects/" + project_ + | |
214 "/locations/" + location_ + | |
215 "/datasets/" + dataset_ + | |
216 "/dicomStores/" + dicomStore_ + | |
217 "/dicomWeb/"); | |
218 | |
219 Json::Value headers = Json::objectValue; | |
220 headers["Authorization"] = "Bearer " + token; | |
221 | |
222 Json::Value server = Json::objectValue; | |
223 server["Url"] = url; | |
224 server["HasDelete"] = "1"; // Google Cloud Platform allows "-X DELETE" | |
225 server["HttpHeaders"] = headers; | |
226 | |
227 Json::Value answer; | |
228 if (OrthancPlugins::RestApiPut(answer, AddTrailingSlash(dicomWebPluginRoot) + "servers/" + name_, | |
229 server, true)) | |
230 { | |
231 return true; | |
232 } | |
233 else | |
234 { | |
235 LOG(ERROR) << "Cannot update DICOMweb access to Google Cloud Platform: " << name_; | |
236 return false; | |
237 } | |
238 } |