]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_user.h
35738ce7d284b2a90ad8b4b9748832b16298f625
[ceph.git] / ceph / src / rgw / rgw_user.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_RGW_USER_H
5 #define CEPH_RGW_USER_H
6
7 #include <string>
8 #include <boost/algorithm/string.hpp>
9 #include "include/assert.h"
10
11 #include "include/types.h"
12 #include "rgw_common.h"
13 #include "rgw_tools.h"
14
15 #include "rgw_rados.h"
16
17 #include "rgw_string.h"
18
19 #include "common/Formatter.h"
20 #include "rgw_formats.h"
21
22 #define RGW_USER_ANON_ID "anonymous"
23
24 #define SECRET_KEY_LEN 40
25 #define PUBLIC_ID_LEN 20
26 #define RAND_SUBUSER_LEN 5
27
28 #define XMLNS_AWS_S3 "http://s3.amazonaws.com/doc/2006-03-01/"
29
30 /**
31 * A string wrapper that includes encode/decode functions
32 * for easily accessing a UID in all forms
33 */
34 struct RGWUID
35 {
36 rgw_user user_id;
37 void encode(bufferlist& bl) const {
38 string s;
39 user_id.to_str(s);
40 ::encode(s, bl);
41 }
42 void decode(bufferlist::iterator& bl) {
43 string s;
44 ::decode(s, bl);
45 user_id.from_str(s);
46 }
47 };
48 WRITE_CLASS_ENCODER(RGWUID)
49
50 extern int rgw_user_sync_all_stats(RGWRados *store, const rgw_user& user_id);
51 extern int rgw_user_get_all_buckets_stats(RGWRados *store, const rgw_user& user_id, map<string, cls_user_bucket_entry>&buckets_usage_map);
52
53 /**
54 * Get the anonymous (ie, unauthenticated) user info.
55 */
56 extern void rgw_get_anon_user(RGWUserInfo& info);
57
58 /**
59 * Save the given user information to storage.
60 * Returns: 0 on success, -ERR# on failure.
61 */
62 extern int rgw_store_user_info(RGWRados *store,
63 RGWUserInfo& info,
64 RGWUserInfo *old_info,
65 RGWObjVersionTracker *objv_tracker,
66 real_time mtime,
67 bool exclusive,
68 map<string, bufferlist> *pattrs = NULL);
69
70 /**
71 * Given an user_id, finds the user info associated with it.
72 * returns: 0 on success, -ERR# on failure (including nonexistence)
73 */
74 extern int rgw_get_user_info_by_uid(RGWRados *store,
75 const rgw_user& user_id,
76 RGWUserInfo& info,
77 RGWObjVersionTracker *objv_tracker = NULL,
78 real_time *pmtime = NULL,
79 rgw_cache_entry_info *cache_info = NULL,
80 map<string, bufferlist> *pattrs = NULL);
81 /**
82 * Given an email, finds the user info associated with it.
83 * returns: 0 on success, -ERR# on failure (including nonexistence)
84 */
85 extern int rgw_get_user_info_by_email(RGWRados *store, string& email, RGWUserInfo& info,
86 RGWObjVersionTracker *objv_tracker = NULL, real_time *pmtime = NULL);
87 /**
88 * Given an swift username, finds the user info associated with it.
89 * returns: 0 on success, -ERR# on failure (including nonexistence)
90 */
91 extern int rgw_get_user_info_by_swift(RGWRados *store,
92 const string& swift_name,
93 RGWUserInfo& info, /* out */
94 RGWObjVersionTracker *objv_tracker = nullptr,
95 real_time *pmtime = nullptr);
96 /**
97 * Given an access key, finds the user info associated with it.
98 * returns: 0 on success, -ERR# on failure (including nonexistence)
99 */
100 extern int rgw_get_user_info_by_access_key(RGWRados* store,
101 const std::string& access_key,
102 RGWUserInfo& info,
103 RGWObjVersionTracker* objv_tracker = nullptr,
104 real_time* pmtime = nullptr);
105 /**
106 * Get all the custom metadata stored for user specified in @user_id
107 * and put it into @attrs.
108 * Returns: 0 on success, -ERR# on failure.
109 */
110 extern int rgw_get_user_attrs_by_uid(RGWRados *store,
111 const rgw_user& user_id,
112 map<string, bufferlist>& attrs,
113 RGWObjVersionTracker *objv_tracker = NULL);
114 /**
115 * Given an RGWUserInfo, deletes the user and its bucket ACLs.
116 */
117 extern int rgw_delete_user(RGWRados *store, RGWUserInfo& user, RGWObjVersionTracker& objv_tracker);
118 /**
119 * Store a list of the user's buckets, with associated functinos.
120 */
121
122 /*
123 * remove the different indexes
124 */
125 extern int rgw_remove_key_index(RGWRados *store, RGWAccessKey& access_key);
126 extern int rgw_remove_uid_index(RGWRados *store, rgw_user& uid);
127 extern int rgw_remove_email_index(RGWRados *store, string& email);
128 extern int rgw_remove_swift_name_index(RGWRados *store, string& swift_name);
129
130 /*
131 * An RGWUser class along with supporting classes created
132 * to support the creation of an RESTful administrative API
133 */
134
135 extern void rgw_perm_to_str(uint32_t mask, char *buf, int len);
136 extern uint32_t rgw_str_to_perm(const char *str);
137
138 enum ObjectKeyType {
139 KEY_TYPE_SWIFT,
140 KEY_TYPE_S3,
141 KEY_TYPE_UNDEFINED
142 };
143
144 enum RGWKeyPoolOp {
145 GENERATE_KEY,
146 MODIFY_KEY
147 };
148
149 enum RGWUserId {
150 RGW_USER_ID,
151 RGW_SWIFT_USERNAME,
152 RGW_USER_EMAIL,
153 RGW_ACCESS_KEY,
154 };
155
156 struct RGWUserAdminOpState {
157 // user attributes
158 RGWUserInfo info;
159 rgw_user user_id;
160 std::string user_email;
161 std::string display_name;
162 int32_t max_buckets;
163 __u8 suspended;
164 __u8 admin;
165 __u8 system;
166 __u8 exclusive;
167 __u8 fetch_stats;
168 std::string caps;
169 RGWObjVersionTracker objv;
170 uint32_t op_mask;
171 map<int, string> temp_url_keys;
172
173 // subuser attributes
174 std::string subuser;
175 uint32_t perm_mask;
176
177 // key_attributes
178 std::string id; // access key
179 std::string key; // secret key
180 int32_t key_type;
181
182 // operation attributes
183 bool existing_user;
184 bool existing_key;
185 bool existing_subuser;
186 bool existing_email;
187 bool subuser_specified;
188 bool gen_secret;
189 bool gen_access;
190 bool gen_subuser;
191 bool id_specified;
192 bool key_specified;
193 bool type_specified;
194 bool key_type_setbycontext; // key type set by user or subuser context
195 bool purge_data;
196 bool purge_keys;
197 bool display_name_specified;
198 bool user_email_specified;
199 bool max_buckets_specified;
200 bool perm_specified;
201 bool op_mask_specified;
202 bool caps_specified;
203 bool suspension_op;
204 bool admin_specified;
205 bool system_specified;
206 bool key_op;
207 bool temp_url_key_specified;
208 bool found_by_uid;
209 bool found_by_email;
210 bool found_by_key;
211
212 // req parameters
213 bool populated;
214 bool initialized;
215 bool key_params_checked;
216 bool subuser_params_checked;
217 bool user_params_checked;
218
219 bool bucket_quota_specified;
220 bool user_quota_specified;
221
222 RGWQuotaInfo bucket_quota;
223 RGWQuotaInfo user_quota;
224
225 void set_access_key(std::string& access_key) {
226 if (access_key.empty())
227 return;
228
229 id = access_key;
230 id_specified = true;
231 gen_access = false;
232 key_op = true;
233 }
234
235 void set_secret_key(std::string& secret_key) {
236 if (secret_key.empty())
237 return;
238
239 key = secret_key;
240 key_specified = true;
241 gen_secret = false;
242 key_op = true;
243 }
244
245 void set_user_id(rgw_user& id) {
246 if (id.empty())
247 return;
248
249 user_id = id;
250 }
251
252 void set_user_email(std::string& email) {
253 /* always lowercase email address */
254 boost::algorithm::to_lower(email);
255 user_email = email;
256 user_email_specified = true;
257 }
258
259 void set_display_name(std::string& name) {
260 if (name.empty())
261 return;
262
263 display_name = name;
264 display_name_specified = true;
265 }
266
267 void set_subuser(std::string& _subuser) {
268 if (_subuser.empty())
269 return;
270
271 size_t pos = _subuser.find(":");
272 if (pos != string::npos) {
273 rgw_user tmp_id;
274 tmp_id.from_str(_subuser.substr(0, pos));
275 if (tmp_id.tenant.empty()) {
276 user_id.id = tmp_id.id;
277 } else {
278 user_id = tmp_id;
279 }
280 subuser = _subuser.substr(pos+1);
281 } else {
282 subuser = _subuser;
283 }
284
285 subuser_specified = true;
286 }
287
288 void set_caps(std::string& _caps) {
289 if (_caps.empty())
290 return;
291
292 caps = _caps;
293 caps_specified = true;
294 }
295
296 void set_perm(uint32_t perm) {
297 perm_mask = perm;
298 perm_specified = true;
299 }
300
301 void set_op_mask(uint32_t mask) {
302 op_mask = mask;
303 op_mask_specified = true;
304 }
305
306 void set_temp_url_key(const string& key, int index) {
307 temp_url_keys[index] = key;
308 temp_url_key_specified = true;
309 }
310
311 void set_key_type(int32_t type) {
312 key_type = type;
313 type_specified = true;
314 }
315
316 void set_suspension(__u8 is_suspended) {
317 suspended = is_suspended;
318 suspension_op = true;
319 }
320
321 void set_admin(__u8 is_admin) {
322 admin = is_admin;
323 admin_specified = true;
324 }
325
326 void set_system(__u8 is_system) {
327 system = is_system;
328 system_specified = true;
329 }
330
331 void set_exclusive(__u8 is_exclusive) {
332 exclusive = is_exclusive;
333 }
334
335 void set_fetch_stats(__u8 is_fetch_stats) {
336 fetch_stats = is_fetch_stats;
337 }
338
339 void set_user_info(RGWUserInfo& user_info) {
340 user_id = user_info.user_id;
341 info = user_info;
342 }
343
344 void set_max_buckets(int32_t mb) {
345 max_buckets = mb;
346 max_buckets_specified = true;
347 }
348
349 void set_gen_access() {
350 gen_access = true;
351 key_op = true;
352 }
353
354 void set_gen_secret() {
355 gen_secret = true;
356 key_op = true;
357 }
358
359 void set_generate_key() {
360 if (id.empty())
361 gen_access = true;
362 if (key.empty())
363 gen_secret = true;
364 key_op = true;
365 }
366
367 void clear_generate_key() {
368 gen_access = false;
369 gen_secret = false;
370 }
371
372 void set_purge_keys() {
373 purge_keys = true;
374 key_op = true;
375 }
376
377 void set_bucket_quota(RGWQuotaInfo& quota) {
378 bucket_quota = quota;
379 bucket_quota_specified = true;
380 }
381
382 void set_user_quota(RGWQuotaInfo& quota) {
383 user_quota = quota;
384 user_quota_specified = true;
385 }
386
387 bool is_populated() { return populated; }
388 bool is_initialized() { return initialized; }
389 bool has_existing_user() { return existing_user; }
390 bool has_existing_key() { return existing_key; }
391 bool has_existing_subuser() { return existing_subuser; }
392 bool has_existing_email() { return existing_email; }
393 bool has_subuser() { return subuser_specified; }
394 bool has_key_op() { return key_op; }
395 bool has_caps_op() { return caps_specified; }
396 bool has_suspension_op() { return suspension_op; }
397 bool has_subuser_perm() { return perm_specified; }
398 bool has_op_mask() { return op_mask_specified; }
399 bool will_gen_access() { return gen_access; }
400 bool will_gen_secret() { return gen_secret; }
401 bool will_gen_subuser() { return gen_subuser; }
402 bool will_purge_keys() { return purge_keys; }
403 bool will_purge_data() { return purge_data; }
404 bool will_generate_subuser() { return gen_subuser; }
405 bool has_bucket_quota() { return bucket_quota_specified; }
406 bool has_user_quota() { return user_quota_specified; }
407 void set_populated() { populated = true; }
408 void clear_populated() { populated = false; }
409 void set_initialized() { initialized = true; }
410 void set_existing_user(bool flag) { existing_user = flag; }
411 void set_existing_key(bool flag) { existing_key = flag; }
412 void set_existing_subuser(bool flag) { existing_subuser = flag; }
413 void set_existing_email(bool flag) { existing_email = flag; }
414 void set_purge_data(bool flag) { purge_data = flag; }
415 void set_generate_subuser(bool flag) { gen_subuser = flag; }
416 __u8 get_suspension_status() { return suspended; }
417 int32_t get_key_type() {return key_type; }
418 uint32_t get_subuser_perm() { return perm_mask; }
419 int32_t get_max_buckets() { return max_buckets; }
420 uint32_t get_op_mask() { return op_mask; }
421 RGWQuotaInfo& get_bucket_quota() { return bucket_quota; }
422 RGWQuotaInfo& get_user_quota() { return user_quota; }
423
424 rgw_user& get_user_id() { return user_id; }
425 std::string get_subuser() { return subuser; }
426 std::string get_access_key() { return id; }
427 std::string get_secret_key() { return key; }
428 std::string get_caps() { return caps; }
429 std::string get_user_email() { return user_email; }
430 std::string get_display_name() { return display_name; }
431 map<int, std::string>& get_temp_url_keys() { return temp_url_keys; }
432
433 RGWUserInfo& get_user_info() { return info; }
434
435 map<std::string, RGWAccessKey> *get_swift_keys() { return &info.swift_keys; }
436 map<std::string, RGWAccessKey> *get_access_keys() { return &info.access_keys; }
437 map<std::string, RGWSubUser> *get_subusers() { return &info.subusers; }
438
439 RGWUserCaps *get_caps_obj() { return &info.caps; }
440
441 std::string build_default_swift_kid() {
442 if (user_id.empty() || subuser.empty())
443 return "";
444
445 std::string kid;
446 user_id.to_str(kid);
447 kid.append(":");
448 kid.append(subuser);
449
450 return kid;
451 }
452
453 std::string generate_subuser() {
454 if (user_id.empty())
455 return "";
456
457 std::string generated_subuser;
458 user_id.to_str(generated_subuser);
459 std::string rand_suffix;
460
461 int sub_buf_size = RAND_SUBUSER_LEN + 1;
462 char sub_buf[RAND_SUBUSER_LEN + 1];
463
464 if (gen_rand_alphanumeric_upper(g_ceph_context, sub_buf, sub_buf_size) < 0)
465 return "";
466
467 rand_suffix = sub_buf;
468 if (rand_suffix.empty())
469 return "";
470
471 generated_subuser.append(rand_suffix);
472 subuser = generated_subuser;
473
474 return generated_subuser;
475 }
476
477 RGWUserAdminOpState() : user_id(RGW_USER_ANON_ID)
478 {
479 max_buckets = RGW_DEFAULT_MAX_BUCKETS;
480 key_type = -1;
481 perm_mask = RGW_PERM_NONE;
482 suspended = 0;
483 admin = 0;
484 system = 0;
485 exclusive = 0;
486 fetch_stats = 0;
487 op_mask = 0;
488
489 existing_user = false;
490 existing_key = false;
491 existing_subuser = false;
492 existing_email = false;
493 subuser_specified = false;
494 caps_specified = false;
495 purge_keys = false;
496 gen_secret = false;
497 gen_access = false;
498 gen_subuser = false;
499 id_specified = false;
500 key_specified = false;
501 type_specified = false;
502 key_type_setbycontext = false;
503 purge_data = false;
504 display_name_specified = false;
505 user_email_specified = false;
506 max_buckets_specified = false;
507 perm_specified = false;
508 op_mask_specified = false;
509 suspension_op = false;
510 system_specified = false;
511 key_op = false;
512 populated = false;
513 initialized = false;
514 key_params_checked = false;
515 subuser_params_checked = false;
516 user_params_checked = false;
517 bucket_quota_specified = false;
518 temp_url_key_specified = false;
519 user_quota_specified = false;
520 found_by_uid = false;
521 found_by_email = false;
522 found_by_key = false;
523 }
524 };
525
526 class RGWUser;
527
528 class RGWAccessKeyPool
529 {
530 RGWUser *user;
531
532 std::map<std::string, int, ltstr_nocase> key_type_map;
533 rgw_user user_id;
534 RGWRados *store;
535
536 map<std::string, RGWAccessKey> *swift_keys;
537 map<std::string, RGWAccessKey> *access_keys;
538
539 // we don't want to allow keys for the anonymous user or a null user
540 bool keys_allowed;
541
542 private:
543 int create_key(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
544 int generate_key(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
545 int modify_key(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
546
547 int check_key_owner(RGWUserAdminOpState& op_state);
548 bool check_existing_key(RGWUserAdminOpState& op_state);
549 int check_op(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
550
551 /* API Contract Fulfilment */
552 int execute_add(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
553 int execute_remove(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
554 int remove_subuser_keys(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
555
556 int add(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
557 int remove(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
558 public:
559 explicit RGWAccessKeyPool(RGWUser* usr);
560 ~RGWAccessKeyPool();
561
562 int init(RGWUserAdminOpState& op_state);
563
564 /* API Contracted Methods */
565 int add(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
566 int remove(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
567
568 friend class RGWUser;
569 friend class RGWSubUserPool;
570 };
571
572 class RGWSubUserPool
573 {
574 RGWUser *user;
575
576 rgw_user user_id;
577 RGWRados *store;
578 bool subusers_allowed;
579
580 map<string, RGWSubUser> *subuser_map;
581
582 private:
583 int check_op(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
584
585 /* API Contract Fulfillment */
586 int execute_add(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
587 int execute_remove(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
588 int execute_modify(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
589
590 int add(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
591 int remove(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
592 int modify(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
593 public:
594 explicit RGWSubUserPool(RGWUser *user);
595 ~RGWSubUserPool();
596
597 bool exists(std::string subuser);
598 int init(RGWUserAdminOpState& op_state);
599
600 /* API contracted methods */
601 int add(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
602 int remove(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
603 int modify(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
604
605 friend class RGWUser;
606 };
607
608 class RGWUserCapPool
609 {
610 RGWUserCaps *caps;
611 bool caps_allowed;
612 RGWUser *user;
613
614 private:
615 int add(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
616 int remove(RGWUserAdminOpState& op_state, std::string *err_msg, bool defer_save);
617
618 public:
619 explicit RGWUserCapPool(RGWUser *user);
620 ~RGWUserCapPool();
621
622 int init(RGWUserAdminOpState& op_state);
623
624 /* API contracted methods */
625 int add(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
626 int remove(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
627
628 friend class RGWUser;
629 };
630
631 class RGWUser
632 {
633
634 private:
635 RGWUserInfo old_info;
636 RGWRados *store;
637
638 rgw_user user_id;
639 bool info_stored;
640
641 void set_populated() { info_stored = true; }
642 void clear_populated() { info_stored = false; }
643 bool is_populated() { return info_stored; }
644
645 int check_op(RGWUserAdminOpState& req, std::string *err_msg);
646 int update(RGWUserAdminOpState& op_state, std::string *err_msg);
647
648 void clear_members();
649 void init_default();
650
651 /* API Contract Fulfillment */
652 int execute_add(RGWUserAdminOpState& op_state, std::string *err_msg);
653 int execute_remove(RGWUserAdminOpState& op_state, std::string *err_msg);
654 int execute_modify(RGWUserAdminOpState& op_state, std::string *err_msg);
655
656 public:
657 RGWUser();
658 ~RGWUser();
659
660 int init(RGWRados *storage, RGWUserAdminOpState& op_state);
661
662 int init_storage(RGWRados *storage);
663 int init(RGWUserAdminOpState& op_state);
664 int init_members(RGWUserAdminOpState& op_state);
665
666 RGWRados *get_store() { return store; }
667
668 /* API Contracted Members */
669 RGWUserCapPool caps;
670 RGWAccessKeyPool keys;
671 RGWSubUserPool subusers;
672
673 /* API Contracted Methods */
674 int add(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
675 int remove(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
676
677 /* remove an already populated RGWUser */
678 int remove(std::string *err_msg = NULL);
679
680 int modify(RGWUserAdminOpState& op_state, std::string *err_msg = NULL);
681
682 /* retrieve info from an existing user in the RGW system */
683 int info(RGWUserAdminOpState& op_state, RGWUserInfo& fetched_info, std::string *err_msg = NULL);
684
685 /* info from an already populated RGWUser */
686 int info (RGWUserInfo& fetched_info, std::string *err_msg = NULL);
687
688 friend class RGWAccessKeyPool;
689 friend class RGWSubUserPool;
690 friend class RGWUserCapPool;
691 };
692
693 /* Wrapers for admin API functionality */
694
695 class RGWUserAdminOp_User
696 {
697 public:
698 static int info(RGWRados *store,
699 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
700
701 static int create(RGWRados *store,
702 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
703
704 static int modify(RGWRados *store,
705 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
706
707 static int remove(RGWRados *store,
708 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
709 };
710
711 class RGWUserAdminOp_Subuser
712 {
713 public:
714 static int create(RGWRados *store,
715 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
716
717 static int modify(RGWRados *store,
718 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
719
720 static int remove(RGWRados *store,
721 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
722 };
723
724 class RGWUserAdminOp_Key
725 {
726 public:
727 static int create(RGWRados *store,
728 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
729
730 static int remove(RGWRados *store,
731 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
732 };
733
734 class RGWUserAdminOp_Caps
735 {
736 public:
737 static int add(RGWRados *store,
738 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
739
740 static int remove(RGWRados *store,
741 RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher);
742 };
743
744 class RGWMetadataManager;
745
746 extern void rgw_user_init(RGWRados *store);
747
748 #endif