1#include <Access/IAccessStorage.h>
2#include <Common/Exception.h>
3#include <Common/quoteString.h>
4#include <IO/WriteHelpers.h>
5#include <Poco/UUIDGenerator.h>
6#include <Poco/Logger.h>
7
8
9namespace DB
10{
11namespace ErrorCodes
12{
13 extern const int BAD_CAST;
14 extern const int ACCESS_ENTITY_NOT_FOUND;
15 extern const int ACCESS_ENTITY_ALREADY_EXISTS;
16 extern const int ACCESS_ENTITY_FOUND_DUPLICATES;
17 extern const int ACCESS_ENTITY_STORAGE_READONLY;
18}
19
20
21std::vector<UUID> IAccessStorage::findAll(std::type_index type) const
22{
23 return findAllImpl(type);
24}
25
26
27std::optional<UUID> IAccessStorage::find(std::type_index type, const String & name) const
28{
29 return findImpl(type, name);
30}
31
32
33std::vector<UUID> IAccessStorage::find(std::type_index type, const Strings & names) const
34{
35 std::vector<UUID> ids;
36 ids.reserve(names.size());
37 for (const String & name : names)
38 {
39 auto id = findImpl(type, name);
40 if (id)
41 ids.push_back(*id);
42 }
43 return ids;
44}
45
46
47UUID IAccessStorage::getID(std::type_index type, const String & name) const
48{
49 auto id = findImpl(type, name);
50 if (id)
51 return *id;
52 throwNotFound(type, name);
53}
54
55
56std::vector<UUID> IAccessStorage::getIDs(std::type_index type, const Strings & names) const
57{
58 std::vector<UUID> ids;
59 ids.reserve(names.size());
60 for (const String & name : names)
61 ids.push_back(getID(type, name));
62 return ids;
63}
64
65
66bool IAccessStorage::exists(const UUID & id) const
67{
68 return existsImpl(id);
69}
70
71
72
73AccessEntityPtr IAccessStorage::tryReadBase(const UUID & id) const
74{
75 try
76 {
77 return readImpl(id);
78 }
79 catch (Exception &)
80 {
81 return nullptr;
82 }
83}
84
85
86String IAccessStorage::readName(const UUID & id) const
87{
88 return readNameImpl(id);
89}
90
91
92std::optional<String> IAccessStorage::tryReadName(const UUID & id) const
93{
94 try
95 {
96 return readNameImpl(id);
97 }
98 catch (Exception &)
99 {
100 return {};
101 }
102}
103
104
105UUID IAccessStorage::insert(const AccessEntityPtr & entity)
106{
107 return insertImpl(entity, false);
108}
109
110
111std::vector<UUID> IAccessStorage::insert(const std::vector<AccessEntityPtr> & multiple_entities)
112{
113 std::vector<UUID> ids;
114 ids.reserve(multiple_entities.size());
115 String error_message;
116 for (const auto & entity : multiple_entities)
117 {
118 try
119 {
120 ids.push_back(insertImpl(entity, false));
121 }
122 catch (Exception & e)
123 {
124 if (e.code() != ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS)
125 throw;
126 error_message += (error_message.empty() ? "" : ". ") + e.message();
127 }
128 }
129 if (!error_message.empty())
130 throw Exception(error_message, ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS);
131 return ids;
132}
133
134
135std::optional<UUID> IAccessStorage::tryInsert(const AccessEntityPtr & entity)
136{
137 try
138 {
139 return insertImpl(entity, false);
140 }
141 catch (Exception &)
142 {
143 return {};
144 }
145}
146
147
148std::vector<UUID> IAccessStorage::tryInsert(const std::vector<AccessEntityPtr> & multiple_entities)
149{
150 std::vector<UUID> ids;
151 ids.reserve(multiple_entities.size());
152 for (const auto & entity : multiple_entities)
153 {
154 try
155 {
156 ids.push_back(insertImpl(entity, false));
157 }
158 catch (Exception &)
159 {
160 }
161 }
162 return ids;
163}
164
165
166UUID IAccessStorage::insertOrReplace(const AccessEntityPtr & entity)
167{
168 return insertImpl(entity, true);
169}
170
171
172std::vector<UUID> IAccessStorage::insertOrReplace(const std::vector<AccessEntityPtr> & multiple_entities)
173{
174 std::vector<UUID> ids;
175 ids.reserve(multiple_entities.size());
176 for (const auto & entity : multiple_entities)
177 ids.push_back(insertImpl(entity, true));
178 return ids;
179}
180
181
182void IAccessStorage::remove(const UUID & id)
183{
184 removeImpl(id);
185}
186
187
188void IAccessStorage::remove(const std::vector<UUID> & ids)
189{
190 String error_message;
191 for (const auto & id : ids)
192 {
193 try
194 {
195 removeImpl(id);
196 }
197 catch (Exception & e)
198 {
199 if (e.code() != ErrorCodes::ACCESS_ENTITY_NOT_FOUND)
200 throw;
201 error_message += (error_message.empty() ? "" : ". ") + e.message();
202 }
203 }
204 if (!error_message.empty())
205 throw Exception(error_message, ErrorCodes::ACCESS_ENTITY_NOT_FOUND);
206}
207
208
209bool IAccessStorage::tryRemove(const UUID & id)
210{
211 try
212 {
213 removeImpl(id);
214 return true;
215 }
216 catch (Exception &)
217 {
218 return false;
219 }
220}
221
222
223std::vector<UUID> IAccessStorage::tryRemove(const std::vector<UUID> & ids)
224{
225 std::vector<UUID> removed;
226 removed.reserve(ids.size());
227 for (const auto & id : ids)
228 {
229 try
230 {
231 removeImpl(id);
232 removed.push_back(id);
233 }
234 catch (Exception &)
235 {
236 }
237 }
238 return removed;
239}
240
241
242void IAccessStorage::update(const UUID & id, const UpdateFunc & update_func)
243{
244 updateImpl(id, update_func);
245}
246
247
248void IAccessStorage::update(const std::vector<UUID> & ids, const UpdateFunc & update_func)
249{
250 String error_message;
251 for (const auto & id : ids)
252 {
253 try
254 {
255 updateImpl(id, update_func);
256 }
257 catch (Exception & e)
258 {
259 if (e.code() != ErrorCodes::ACCESS_ENTITY_NOT_FOUND)
260 throw;
261 error_message += (error_message.empty() ? "" : ". ") + e.message();
262 }
263 }
264 if (!error_message.empty())
265 throw Exception(error_message, ErrorCodes::ACCESS_ENTITY_NOT_FOUND);
266}
267
268
269bool IAccessStorage::tryUpdate(const UUID & id, const UpdateFunc & update_func)
270{
271 try
272 {
273 updateImpl(id, update_func);
274 return true;
275 }
276 catch (Exception &)
277 {
278 return false;
279 }
280}
281
282
283std::vector<UUID> IAccessStorage::tryUpdate(const std::vector<UUID> & ids, const UpdateFunc & update_func)
284{
285 std::vector<UUID> updated;
286 updated.reserve(ids.size());
287 for (const auto & id : ids)
288 {
289 try
290 {
291 updateImpl(id, update_func);
292 updated.push_back(id);
293 }
294 catch (Exception &)
295 {
296 }
297 }
298 return updated;
299}
300
301
302IAccessStorage::SubscriptionPtr IAccessStorage::subscribeForChanges(std::type_index type, const OnChangedHandler & handler) const
303{
304 return subscribeForChangesImpl(type, handler);
305}
306
307
308IAccessStorage::SubscriptionPtr IAccessStorage::subscribeForChanges(const UUID & id, const OnChangedHandler & handler) const
309{
310 return subscribeForChangesImpl(id, handler);
311}
312
313
314IAccessStorage::SubscriptionPtr IAccessStorage::subscribeForChanges(const std::vector<UUID> & ids, const OnChangedHandler & handler) const
315{
316 if (ids.empty())
317 return nullptr;
318 if (ids.size() == 1)
319 return subscribeForChangesImpl(ids[0], handler);
320
321 std::vector<SubscriptionPtr> subscriptions;
322 subscriptions.reserve(ids.size());
323 for (const auto & id : ids)
324 {
325 auto subscription = subscribeForChangesImpl(id, handler);
326 if (subscription)
327 subscriptions.push_back(std::move(subscription));
328 }
329
330 class SubscriptionImpl : public Subscription
331 {
332 public:
333 SubscriptionImpl(std::vector<SubscriptionPtr> subscriptions_)
334 : subscriptions(std::move(subscriptions_)) {}
335 private:
336 std::vector<SubscriptionPtr> subscriptions;
337 };
338
339 return std::make_unique<SubscriptionImpl>(std::move(subscriptions));
340}
341
342
343bool IAccessStorage::hasSubscription(std::type_index type) const
344{
345 return hasSubscriptionImpl(type);
346}
347
348
349bool IAccessStorage::hasSubscription(const UUID & id) const
350{
351 return hasSubscriptionImpl(id);
352}
353
354
355void IAccessStorage::notify(const Notifications & notifications)
356{
357 for (const auto & [fn, id, new_entity] : notifications)
358 fn(id, new_entity);
359}
360
361
362UUID IAccessStorage::generateRandomID()
363{
364 static Poco::UUIDGenerator generator;
365 UUID id;
366 generator.createRandom().copyTo(reinterpret_cast<char *>(&id));
367 return id;
368}
369
370
371Poco::Logger * IAccessStorage::getLogger() const
372{
373 Poco::Logger * ptr = log.load();
374 if (!ptr)
375 log.store(ptr = &Poco::Logger::get("Access(" + storage_name + ")"), std::memory_order_relaxed);
376 return ptr;
377}
378
379
380void IAccessStorage::throwNotFound(const UUID & id) const
381{
382 throw Exception("ID {" + toString(id) + "} not found in " + getStorageName(), ErrorCodes::ACCESS_ENTITY_NOT_FOUND);
383}
384
385
386void IAccessStorage::throwNotFound(std::type_index type, const String & name) const
387{
388 throw Exception(
389 getTypeName(type) + " " + backQuote(name) + " not found in " + getStorageName(), ErrorCodes::ACCESS_ENTITY_NOT_FOUND);
390}
391
392
393void IAccessStorage::throwBadCast(const UUID & id, std::type_index type, const String & name, std::type_index required_type) const
394{
395 throw Exception(
396 "ID {" + toString(id) + "}: " + getTypeName(type) + backQuote(name) + " expected to be of type " + getTypeName(required_type),
397 ErrorCodes::BAD_CAST);
398}
399
400
401void IAccessStorage::throwIDCollisionCannotInsert(const UUID & id, std::type_index type, const String & name, std::type_index existing_type, const String & existing_name) const
402{
403 throw Exception(
404 getTypeName(type) + " " + backQuote(name) + ": cannot insert because the ID {" + toString(id) + "} is already used by "
405 + getTypeName(existing_type) + " " + backQuote(existing_name) + " in " + getStorageName(),
406 ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS);
407}
408
409
410void IAccessStorage::throwNameCollisionCannotInsert(std::type_index type, const String & name) const
411{
412 throw Exception(
413 getTypeName(type) + " " + backQuote(name) + ": cannot insert because " + getTypeName(type) + " " + backQuote(name)
414 + " already exists in " + getStorageName(),
415 ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS);
416}
417
418
419void IAccessStorage::throwNameCollisionCannotRename(std::type_index type, const String & old_name, const String & new_name) const
420{
421 throw Exception(
422 getTypeName(type) + " " + backQuote(old_name) + ": cannot rename to " + backQuote(new_name) + " because " + getTypeName(type) + " "
423 + backQuote(new_name) + " already exists in " + getStorageName(),
424 ErrorCodes::ACCESS_ENTITY_ALREADY_EXISTS);
425}
426
427
428void IAccessStorage::throwReadonlyCannotInsert(std::type_index type, const String & name) const
429{
430 throw Exception(
431 "Cannot insert " + getTypeName(type) + " " + backQuote(name) + " to " + getStorageName() + " because this storage is readonly",
432 ErrorCodes::ACCESS_ENTITY_STORAGE_READONLY);
433}
434
435
436void IAccessStorage::throwReadonlyCannotUpdate(std::type_index type, const String & name) const
437{
438 throw Exception(
439 "Cannot update " + getTypeName(type) + " " + backQuote(name) + " in " + getStorageName() + " because this storage is readonly",
440 ErrorCodes::ACCESS_ENTITY_STORAGE_READONLY);
441}
442
443
444void IAccessStorage::throwReadonlyCannotRemove(std::type_index type, const String & name) const
445{
446 throw Exception(
447 "Cannot remove " + getTypeName(type) + " " + backQuote(name) + " from " + getStorageName() + " because this storage is readonly",
448 ErrorCodes::ACCESS_ENTITY_STORAGE_READONLY);
449}
450}
451