1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
8 #include <boost/algorithm/string.hpp>
10 #include "common/errno.h"
11 #include "common/Formatter.h"
12 #include "common/ceph_json.h"
13 #include "common/RWLock.h"
14 #include "rgw_rados.h"
17 #include "include/types.h"
19 #include "rgw_string.h"
21 // until everything is moved from rgw_common
22 #include "rgw_common.h"
24 #include "rgw_bucket.h"
26 #define dout_subsys ceph_subsys_rgw
31 static RGWMetadataHandler
*user_meta_handler
= NULL
;
35 * Get the anonymous (ie, unauthenticated) user info.
37 void rgw_get_anon_user(RGWUserInfo
& info
)
39 info
.user_id
= RGW_USER_ANON_ID
;
40 info
.display_name
.clear();
41 info
.access_keys
.clear();
44 int rgw_user_sync_all_stats(RGWRados
*store
, const rgw_user
& user_id
)
46 CephContext
*cct
= store
->ctx();
47 size_t max_entries
= cct
->_conf
->rgw_list_buckets_max_chunk
;
48 bool is_truncated
= false;
51 RGWObjectCtx
obj_ctx(store
);
54 RGWUserBuckets user_buckets
;
55 ret
= rgw_read_user_buckets(store
, user_id
, user_buckets
, marker
,
56 string(), max_entries
, false, &is_truncated
);
58 ldout(cct
, 0) << "failed to read user buckets: ret=" << ret
<< dendl
;
61 map
<string
, RGWBucketEnt
>& buckets
= user_buckets
.get_buckets();
62 for (map
<string
, RGWBucketEnt
>::iterator i
= buckets
.begin();
67 RGWBucketEnt
& bucket_ent
= i
->second
;
68 RGWBucketInfo bucket_info
;
70 ret
= store
->get_bucket_instance_info(obj_ctx
, bucket_ent
.bucket
, bucket_info
, NULL
, NULL
);
72 ldout(cct
, 0) << "ERROR: could not read bucket info: bucket=" << bucket_ent
.bucket
<< " ret=" << ret
<< dendl
;
75 ret
= rgw_bucket_sync_user_stats(store
, user_id
, bucket_info
);
77 ldout(cct
, 0) << "ERROR: could not sync bucket stats: ret=" << ret
<< dendl
;
81 } while (is_truncated
);
83 ret
= store
->complete_sync_user_stats(user_id
);
85 cerr
<< "ERROR: failed to complete syncing user stats: ret=" << ret
<< std::endl
;
93 * Save the given user information to storage.
94 * Returns: 0 on success, -ERR# on failure.
96 int rgw_store_user_info(RGWRados
*store
,
98 RGWUserInfo
*old_info
,
99 RGWObjVersionTracker
*objv_tracker
,
102 map
<string
, bufferlist
> *pattrs
)
105 RGWObjVersionTracker ot
;
111 if (ot
.write_version
.tag
.empty()) {
112 if (ot
.read_version
.tag
.empty()) {
113 ot
.generate_new_write_ver(store
->ctx());
115 ot
.write_version
= ot
.read_version
;
116 ot
.write_version
.ver
++;
120 map
<string
, RGWAccessKey
>::iterator iter
;
121 for (iter
= info
.swift_keys
.begin(); iter
!= info
.swift_keys
.end(); ++iter
) {
122 if (old_info
&& old_info
->swift_keys
.count(iter
->first
) != 0)
124 RGWAccessKey
& k
= iter
->second
;
125 /* check if swift mapping exists */
127 int r
= rgw_get_user_info_by_swift(store
, k
.id
, inf
);
128 if (r
>= 0 && inf
.user_id
.compare(info
.user_id
) != 0) {
129 ldout(store
->ctx(), 0) << "WARNING: can't store user info, swift id (" << k
.id
130 << ") already mapped to another user (" << info
.user_id
<< ")" << dendl
;
135 if (!info
.access_keys
.empty()) {
136 /* check if access keys already exist */
138 map
<string
, RGWAccessKey
>::iterator iter
= info
.access_keys
.begin();
139 for (; iter
!= info
.access_keys
.end(); ++iter
) {
140 RGWAccessKey
& k
= iter
->second
;
141 if (old_info
&& old_info
->access_keys
.count(iter
->first
) != 0)
143 int r
= rgw_get_user_info_by_access_key(store
, k
.id
, inf
);
144 if (r
>= 0 && inf
.user_id
.compare(info
.user_id
) != 0) {
145 ldout(store
->ctx(), 0) << "WARNING: can't store user info, access key already mapped to another user" << dendl
;
152 ui
.user_id
= info
.user_id
;
155 ::encode(ui
, link_bl
);
158 ::encode(ui
, data_bl
);
159 ::encode(info
, data_bl
);
162 info
.user_id
.to_str(key
);
164 ret
= store
->meta_mgr
->put_entry(user_meta_handler
, key
, data_bl
, exclusive
, &ot
, mtime
, pattrs
);
168 if (!info
.user_email
.empty()) {
170 old_info
->user_email
.compare(info
.user_email
) != 0) { /* only if new index changed */
171 ret
= rgw_put_system_obj(store
, store
->get_zone_params().user_email_pool
, info
.user_email
,
172 link_bl
.c_str(), link_bl
.length(), exclusive
, NULL
, real_time());
178 if (!info
.access_keys
.empty()) {
179 map
<string
, RGWAccessKey
>::iterator iter
= info
.access_keys
.begin();
180 for (; iter
!= info
.access_keys
.end(); ++iter
) {
181 RGWAccessKey
& k
= iter
->second
;
182 if (old_info
&& old_info
->access_keys
.count(iter
->first
) != 0)
185 ret
= rgw_put_system_obj(store
, store
->get_zone_params().user_keys_pool
, k
.id
,
186 link_bl
.c_str(), link_bl
.length(), exclusive
,
193 map
<string
, RGWAccessKey
>::iterator siter
;
194 for (siter
= info
.swift_keys
.begin(); siter
!= info
.swift_keys
.end(); ++siter
) {
195 RGWAccessKey
& k
= siter
->second
;
196 if (old_info
&& old_info
->swift_keys
.count(siter
->first
) != 0)
199 ret
= rgw_put_system_obj(store
, store
->get_zone_params().user_swift_pool
, k
.id
,
200 link_bl
.c_str(), link_bl
.length(), exclusive
,
209 struct user_info_entry
{
211 RGWObjVersionTracker objv_tracker
;
215 static RGWChainedCacheImpl
<user_info_entry
> uinfo_cache
;
217 int rgw_get_user_info_from_index(RGWRados
* const store
,
221 RGWObjVersionTracker
* const objv_tracker
,
222 real_time
* const pmtime
)
225 if (uinfo_cache
.find(key
, &e
)) {
228 *objv_tracker
= e
.objv_tracker
;
236 RGWObjectCtx
obj_ctx(store
);
238 int ret
= rgw_get_system_obj(store
, obj_ctx
, pool
, key
, bl
, NULL
, &e
.mtime
);
242 rgw_cache_entry_info cache_info
;
244 bufferlist::iterator iter
= bl
.begin();
247 int ret
= rgw_get_user_info_by_uid(store
, uid
.user_id
, e
.info
, &e
.objv_tracker
, NULL
, &cache_info
);
251 } catch (buffer::error
& err
) {
252 ldout(store
->ctx(), 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl
;
256 list
<rgw_cache_entry_info
*> cache_info_entries
;
257 cache_info_entries
.push_back(&cache_info
);
259 uinfo_cache
.put(store
, key
, &e
, cache_info_entries
);
263 *objv_tracker
= e
.objv_tracker
;
271 * Given a uid, finds the user info associated with it.
272 * returns: 0 on success, -ERR# on failure (including nonexistence)
274 int rgw_get_user_info_by_uid(RGWRados
*store
,
277 RGWObjVersionTracker
* const objv_tracker
,
278 real_time
* const pmtime
,
279 rgw_cache_entry_info
* const cache_info
,
280 map
<string
, bufferlist
> * const pattrs
)
285 RGWObjectCtx
obj_ctx(store
);
286 string oid
= uid
.to_str();
287 int ret
= rgw_get_system_obj(store
, obj_ctx
, store
->get_zone_params().user_uid_pool
, oid
, bl
, objv_tracker
, pmtime
, pattrs
, cache_info
);
292 bufferlist::iterator iter
= bl
.begin();
294 ::decode(user_id
, iter
);
295 if (user_id
.user_id
.compare(uid
) != 0) {
296 lderr(store
->ctx()) << "ERROR: rgw_get_user_info_by_uid(): user id mismatch: " << user_id
.user_id
<< " != " << uid
<< dendl
;
300 ::decode(info
, iter
);
302 } catch (buffer::error
& err
) {
303 ldout(store
->ctx(), 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl
;
311 * Given an email, finds the user info associated with it.
312 * returns: 0 on success, -ERR# on failure (including nonexistence)
314 int rgw_get_user_info_by_email(RGWRados
*store
, string
& email
, RGWUserInfo
& info
,
315 RGWObjVersionTracker
*objv_tracker
, real_time
*pmtime
)
317 return rgw_get_user_info_from_index(store
, email
, store
->get_zone_params().user_email_pool
, info
, objv_tracker
, pmtime
);
321 * Given an swift username, finds the user_info associated with it.
322 * returns: 0 on success, -ERR# on failure (including nonexistence)
324 extern int rgw_get_user_info_by_swift(RGWRados
* const store
,
325 const string
& swift_name
,
326 RGWUserInfo
& info
, /* out */
327 RGWObjVersionTracker
* const objv_tracker
,
328 real_time
* const pmtime
)
330 return rgw_get_user_info_from_index(store
, swift_name
,
331 store
->get_zone_params().user_swift_pool
,
332 info
, objv_tracker
, pmtime
);
336 * Given an access key, finds the user info associated with it.
337 * returns: 0 on success, -ERR# on failure (including nonexistence)
339 extern int rgw_get_user_info_by_access_key(RGWRados
* store
,
340 const std::string
& access_key
,
342 RGWObjVersionTracker
* objv_tracker
,
345 return rgw_get_user_info_from_index(store
, access_key
,
346 store
->get_zone_params().user_keys_pool
,
347 info
, objv_tracker
, pmtime
);
350 int rgw_get_user_attrs_by_uid(RGWRados
*store
,
351 const rgw_user
& user_id
,
352 map
<string
, bufferlist
>& attrs
,
353 RGWObjVersionTracker
*objv_tracker
)
355 RGWObjectCtx
obj_ctx(store
);
356 rgw_raw_obj
obj(store
->get_zone_params().user_uid_pool
, user_id
.to_str());
357 RGWRados::SystemObject
src(store
, obj_ctx
, obj
);
358 RGWRados::SystemObject::Read
rop(&src
);
360 rop
.stat_params
.attrs
= &attrs
;
361 return rop
.stat(objv_tracker
);
364 int rgw_remove_key_index(RGWRados
*store
, RGWAccessKey
& access_key
)
366 rgw_raw_obj
obj(store
->get_zone_params().user_keys_pool
, access_key
.id
);
367 int ret
= store
->delete_system_obj(obj
);
371 int rgw_remove_uid_index(RGWRados
*store
, rgw_user
& uid
)
373 RGWObjVersionTracker objv_tracker
;
375 int ret
= rgw_get_user_info_by_uid(store
, uid
, info
, &objv_tracker
, NULL
);
379 string oid
= uid
.to_str();
380 ret
= store
->meta_mgr
->remove_entry(user_meta_handler
, oid
, &objv_tracker
);
387 int rgw_remove_email_index(RGWRados
*store
, string
& email
)
392 rgw_raw_obj
obj(store
->get_zone_params().user_email_pool
, email
);
393 return store
->delete_system_obj(obj
);
396 int rgw_remove_swift_name_index(RGWRados
*store
, string
& swift_name
)
398 rgw_raw_obj
obj(store
->get_zone_params().user_swift_pool
, swift_name
);
399 int ret
= store
->delete_system_obj(obj
);
404 * delete a user's presence from the RGW system.
405 * First remove their bucket ACLs, then delete them
406 * from the user and user email pools. This leaves the pools
407 * themselves alone, as well as any ACLs embedded in object xattrs.
409 int rgw_delete_user(RGWRados
*store
, RGWUserInfo
& info
, RGWObjVersionTracker
& objv_tracker
) {
412 map
<string
, RGWAccessKey
>::iterator kiter
= info
.access_keys
.begin();
413 for (; kiter
!= info
.access_keys
.end(); ++kiter
) {
414 ldout(store
->ctx(), 10) << "removing key index: " << kiter
->first
<< dendl
;
415 ret
= rgw_remove_key_index(store
, kiter
->second
);
416 if (ret
< 0 && ret
!= -ENOENT
) {
417 ldout(store
->ctx(), 0) << "ERROR: could not remove " << kiter
->first
<< " (access key object), should be fixed (err=" << ret
<< ")" << dendl
;
422 map
<string
, RGWAccessKey
>::iterator siter
= info
.swift_keys
.begin();
423 for (; siter
!= info
.swift_keys
.end(); ++siter
) {
424 RGWAccessKey
& k
= siter
->second
;
425 ldout(store
->ctx(), 10) << "removing swift subuser index: " << k
.id
<< dendl
;
426 /* check if swift mapping exists */
427 ret
= rgw_remove_swift_name_index(store
, k
.id
);
428 if (ret
< 0 && ret
!= -ENOENT
) {
429 ldout(store
->ctx(), 0) << "ERROR: could not remove " << k
.id
<< " (swift name object), should be fixed (err=" << ret
<< ")" << dendl
;
434 ldout(store
->ctx(), 10) << "removing email index: " << info
.user_email
<< dendl
;
435 ret
= rgw_remove_email_index(store
, info
.user_email
);
436 if (ret
< 0 && ret
!= -ENOENT
) {
437 ldout(store
->ctx(), 0) << "ERROR: could not remove email index object for "
438 << info
.user_email
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
442 string buckets_obj_id
;
443 rgw_get_buckets_obj(info
.user_id
, buckets_obj_id
);
444 rgw_raw_obj
uid_bucks(store
->get_zone_params().user_uid_pool
, buckets_obj_id
);
445 ldout(store
->ctx(), 10) << "removing user buckets index" << dendl
;
446 ret
= store
->delete_system_obj(uid_bucks
);
447 if (ret
< 0 && ret
!= -ENOENT
) {
448 ldout(store
->ctx(), 0) << "ERROR: could not remove " << info
.user_id
<< ":" << uid_bucks
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
453 info
.user_id
.to_str(key
);
455 rgw_raw_obj
uid_obj(store
->get_zone_params().user_uid_pool
, key
);
456 ldout(store
->ctx(), 10) << "removing user index: " << info
.user_id
<< dendl
;
457 ret
= store
->meta_mgr
->remove_entry(user_meta_handler
, key
, &objv_tracker
);
458 if (ret
< 0 && ret
!= -ENOENT
&& ret
!= -ECANCELED
) {
459 ldout(store
->ctx(), 0) << "ERROR: could not remove " << info
.user_id
<< ":" << uid_obj
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
466 static bool char_is_unreserved_url(char c
)
482 struct rgw_flags_desc
{
487 static struct rgw_flags_desc rgw_perms
[] = {
488 { RGW_PERM_FULL_CONTROL
, "full-control" },
489 { RGW_PERM_READ
| RGW_PERM_WRITE
, "read-write" },
490 { RGW_PERM_READ
, "read" },
491 { RGW_PERM_WRITE
, "write" },
492 { RGW_PERM_READ_ACP
, "read-acp" },
493 { RGW_PERM_WRITE_ACP
, "read-acp" },
497 void rgw_perm_to_str(uint32_t mask
, char *buf
, int len
)
499 const char *sep
= "";
502 snprintf(buf
, len
, "<none>");
506 uint32_t orig_mask
= mask
;
507 for (int i
= 0; rgw_perms
[i
].mask
; i
++) {
508 struct rgw_flags_desc
*desc
= &rgw_perms
[i
];
509 if ((mask
& desc
->mask
) == desc
->mask
) {
510 pos
+= snprintf(buf
+ pos
, len
- pos
, "%s%s", sep
, desc
->str
);
519 if (mask
== orig_mask
) // no change
524 uint32_t rgw_str_to_perm(const char *str
)
526 if (strcasecmp(str
, "") == 0)
527 return RGW_PERM_NONE
;
528 else if (strcasecmp(str
, "read") == 0)
529 return RGW_PERM_READ
;
530 else if (strcasecmp(str
, "write") == 0)
531 return RGW_PERM_WRITE
;
532 else if (strcasecmp(str
, "readwrite") == 0)
533 return RGW_PERM_READ
| RGW_PERM_WRITE
;
534 else if (strcasecmp(str
, "full") == 0)
535 return RGW_PERM_FULL_CONTROL
;
537 return RGW_PERM_INVALID
;
540 static bool validate_access_key(string
& key
)
542 const char *p
= key
.c_str();
544 if (!char_is_unreserved_url(*p
))
551 static void set_err_msg(std::string
*sink
, std::string msg
)
553 if (sink
&& !msg
.empty())
557 static bool remove_old_indexes(RGWRados
*store
,
558 RGWUserInfo
& old_info
, RGWUserInfo
& new_info
, std::string
*err_msg
)
563 if (!old_info
.user_id
.empty() &&
564 old_info
.user_id
.compare(new_info
.user_id
) != 0) {
565 if (old_info
.user_id
.tenant
!= new_info
.user_id
.tenant
) {
566 ldout(store
->ctx(), 0) << "ERROR: tenant mismatch: " << old_info
.user_id
.tenant
<< " != " << new_info
.user_id
.tenant
<< dendl
;
569 ret
= rgw_remove_uid_index(store
, old_info
.user_id
);
570 if (ret
< 0 && ret
!= -ENOENT
) {
571 set_err_msg(err_msg
, "ERROR: could not remove index for uid " + old_info
.user_id
.to_str());
576 if (!old_info
.user_email
.empty() &&
577 old_info
.user_email
.compare(new_info
.user_email
) != 0) {
578 ret
= rgw_remove_email_index(store
, old_info
.user_email
);
579 if (ret
< 0 && ret
!= -ENOENT
) {
580 set_err_msg(err_msg
, "ERROR: could not remove index for email " + old_info
.user_email
);
585 map
<string
, RGWAccessKey
>::iterator old_iter
;
586 for (old_iter
= old_info
.swift_keys
.begin(); old_iter
!= old_info
.swift_keys
.end(); ++old_iter
) {
587 RGWAccessKey
& swift_key
= old_iter
->second
;
588 map
<string
, RGWAccessKey
>::iterator new_iter
= new_info
.swift_keys
.find(swift_key
.id
);
589 if (new_iter
== new_info
.swift_keys
.end()) {
590 ret
= rgw_remove_swift_name_index(store
, swift_key
.id
);
591 if (ret
< 0 && ret
!= -ENOENT
) {
592 set_err_msg(err_msg
, "ERROR: could not remove index for swift_name " + swift_key
.id
);
602 * Dump either the full user info or a subset to a formatter.
604 * NOTE: It is the caller's respnsibility to ensure that the
605 * formatter is flushed at the correct time.
608 static void dump_subusers_info(Formatter
*f
, RGWUserInfo
&info
)
610 map
<string
, RGWSubUser
>::iterator uiter
;
612 f
->open_array_section("subusers");
613 for (uiter
= info
.subusers
.begin(); uiter
!= info
.subusers
.end(); ++uiter
) {
614 RGWSubUser
& u
= uiter
->second
;
615 f
->open_object_section("user");
617 info
.user_id
.to_str(s
);
618 f
->dump_format("id", "%s:%s", s
.c_str(), u
.name
.c_str());
620 rgw_perm_to_str(u
.perm_mask
, buf
, sizeof(buf
));
621 f
->dump_string("permissions", buf
);
627 static void dump_access_keys_info(Formatter
*f
, RGWUserInfo
&info
)
629 map
<string
, RGWAccessKey
>::iterator kiter
;
630 f
->open_array_section("keys");
631 for (kiter
= info
.access_keys
.begin(); kiter
!= info
.access_keys
.end(); ++kiter
) {
632 RGWAccessKey
& k
= kiter
->second
;
633 const char *sep
= (k
.subuser
.empty() ? "" : ":");
634 const char *subuser
= (k
.subuser
.empty() ? "" : k
.subuser
.c_str());
635 f
->open_object_section("key");
637 info
.user_id
.to_str(s
);
638 f
->dump_format("user", "%s%s%s", s
.c_str(), sep
, subuser
);
639 f
->dump_string("access_key", k
.id
);
640 f
->dump_string("secret_key", k
.key
);
646 static void dump_swift_keys_info(Formatter
*f
, RGWUserInfo
&info
)
648 map
<string
, RGWAccessKey
>::iterator kiter
;
649 f
->open_array_section("swift_keys");
650 for (kiter
= info
.swift_keys
.begin(); kiter
!= info
.swift_keys
.end(); ++kiter
) {
651 RGWAccessKey
& k
= kiter
->second
;
652 const char *sep
= (k
.subuser
.empty() ? "" : ":");
653 const char *subuser
= (k
.subuser
.empty() ? "" : k
.subuser
.c_str());
654 f
->open_object_section("key");
656 info
.user_id
.to_str(s
);
657 f
->dump_format("user", "%s%s%s", s
.c_str(), sep
, subuser
);
658 f
->dump_string("secret_key", k
.key
);
664 static void dump_user_info(Formatter
*f
, RGWUserInfo
&info
,
665 RGWStorageStats
*stats
= NULL
)
667 f
->open_object_section("user_info");
669 f
->dump_string("tenant", info
.user_id
.tenant
);
670 f
->dump_string("user_id", info
.user_id
.id
);
671 f
->dump_string("display_name", info
.display_name
);
672 f
->dump_string("email", info
.user_email
);
673 f
->dump_int("suspended", (int)info
.suspended
);
674 f
->dump_int("max_buckets", (int)info
.max_buckets
);
676 dump_subusers_info(f
, info
);
677 dump_access_keys_info(f
, info
);
678 dump_swift_keys_info(f
, info
);
681 encode_json("stats", *stats
, f
);
688 RGWAccessKeyPool::RGWAccessKeyPool(RGWUser
* usr
)
695 keys_allowed
= false;
702 store
= user
->get_store();
705 RGWAccessKeyPool::~RGWAccessKeyPool()
710 int RGWAccessKeyPool::init(RGWUserAdminOpState
& op_state
)
712 if (!op_state
.is_initialized()) {
713 keys_allowed
= false;
717 rgw_user
& uid
= op_state
.get_user_id();
718 if (uid
.compare(RGW_USER_ANON_ID
) == 0) {
719 keys_allowed
= false;
723 swift_keys
= op_state
.get_swift_keys();
724 access_keys
= op_state
.get_access_keys();
732 * Do a fairly exhaustive search for an existing key matching the parameters
733 * given. Also handles the case where no key type was specified and updates
734 * the operation state if needed.
737 bool RGWAccessKeyPool::check_existing_key(RGWUserAdminOpState
& op_state
)
739 bool existing_key
= false;
741 int key_type
= op_state
.get_key_type();
742 std::string kid
= op_state
.get_access_key();
743 std::map
<std::string
, RGWAccessKey
>::iterator kiter
;
744 std::string swift_kid
= op_state
.build_default_swift_kid();
746 RGWUserInfo dup_info
;
748 if (kid
.empty() && swift_kid
.empty())
753 kiter
= swift_keys
->find(swift_kid
);
755 existing_key
= (kiter
!= swift_keys
->end());
757 op_state
.set_access_key(swift_kid
);
761 kiter
= access_keys
->find(kid
);
762 existing_key
= (kiter
!= access_keys
->end());
766 kiter
= access_keys
->find(kid
);
768 existing_key
= (kiter
!= access_keys
->end());
770 op_state
.set_key_type(KEY_TYPE_S3
);
774 kiter
= swift_keys
->find(kid
);
776 existing_key
= (kiter
!= swift_keys
->end());
778 op_state
.set_key_type(KEY_TYPE_SWIFT
);
782 // handle the case where the access key was not provided in user:key format
783 if (swift_kid
.empty())
786 kiter
= swift_keys
->find(swift_kid
);
788 existing_key
= (kiter
!= swift_keys
->end());
790 op_state
.set_access_key(swift_kid
);
791 op_state
.set_key_type(KEY_TYPE_SWIFT
);
795 op_state
.set_existing_key(existing_key
);
800 int RGWAccessKeyPool::check_op(RGWUserAdminOpState
& op_state
,
801 std::string
*err_msg
)
803 RGWUserInfo dup_info
;
805 if (!op_state
.is_populated()) {
806 set_err_msg(err_msg
, "user info was not populated");
811 set_err_msg(err_msg
, "keys not allowed for this user");
815 int32_t key_type
= op_state
.get_key_type();
817 // if a key type wasn't specified
819 if (op_state
.has_subuser()) {
820 key_type
= KEY_TYPE_SWIFT
;
822 key_type
= KEY_TYPE_S3
;
826 op_state
.set_key_type(key_type
);
828 /* see if the access key was specified */
829 if (key_type
== KEY_TYPE_S3
&& !op_state
.will_gen_access() &&
830 op_state
.get_access_key().empty()) {
831 set_err_msg(err_msg
, "empty access key");
832 return -ERR_INVALID_ACCESS_KEY
;
835 // don't check for secret key because we may be doing a removal
837 check_existing_key(op_state
);
842 // Generate a new random key
843 int RGWAccessKeyPool::generate_key(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
848 std::pair
<std::string
, RGWAccessKey
> key_pair
;
849 RGWAccessKey new_key
;
850 RGWUserInfo duplicate_check
;
853 int key_type
= op_state
.get_key_type();
854 bool gen_access
= op_state
.will_gen_access();
855 bool gen_secret
= op_state
.will_gen_secret();
858 set_err_msg(err_msg
, "access keys not allowed for this user");
862 if (op_state
.has_existing_key()) {
863 set_err_msg(err_msg
, "cannot create existing key");
864 return -ERR_KEY_EXIST
;
868 id
= op_state
.get_access_key();
874 if (rgw_get_user_info_by_swift(store
, id
, duplicate_check
) >= 0) {
875 set_err_msg(err_msg
, "existing swift key in RGW system:" + id
);
876 return -ERR_KEY_EXIST
;
880 if (rgw_get_user_info_by_access_key(store
, id
, duplicate_check
) >= 0) {
881 set_err_msg(err_msg
, "existing S3 key in RGW system:" + id
);
882 return -ERR_KEY_EXIST
;
888 if (op_state
.has_subuser()) {
889 //create user and subuser at the same time, user's s3 key should not be set this
890 if (!op_state
.key_type_setbycontext
|| (key_type
== KEY_TYPE_SWIFT
)) {
891 new_key
.subuser
= op_state
.get_subuser();
897 if (op_state
.get_secret_key().empty()) {
898 set_err_msg(err_msg
, "empty secret key");
899 return -ERR_INVALID_SECRET_KEY
;
902 key
= op_state
.get_secret_key();
904 char secret_key_buf
[SECRET_KEY_LEN
+ 1];
906 ret
= gen_rand_alphanumeric_plain(g_ceph_context
, secret_key_buf
, sizeof(secret_key_buf
));
908 set_err_msg(err_msg
, "unable to generate secret key");
912 key
= secret_key_buf
;
915 // Generate the access key
916 if (key_type
== KEY_TYPE_S3
&& gen_access
) {
917 char public_id_buf
[PUBLIC_ID_LEN
+ 1];
920 int id_buf_size
= sizeof(public_id_buf
);
921 ret
= gen_rand_alphanumeric_upper(g_ceph_context
,
922 public_id_buf
, id_buf_size
);
925 set_err_msg(err_msg
, "unable to generate access key");
930 if (!validate_access_key(id
))
933 } while (!rgw_get_user_info_by_access_key(store
, id
, duplicate_check
));
936 if (key_type
== KEY_TYPE_SWIFT
) {
937 id
= op_state
.build_default_swift_kid();
939 set_err_msg(err_msg
, "empty swift access key");
940 return -ERR_INVALID_ACCESS_KEY
;
943 // check that the access key doesn't exist
944 if (rgw_get_user_info_by_swift(store
, id
, duplicate_check
) >= 0) {
945 set_err_msg(err_msg
, "cannot create existing swift key");
946 return -ERR_KEY_EXIST
;
950 // finally create the new key
955 key_pair
.second
= new_key
;
957 if (key_type
== KEY_TYPE_S3
) {
958 access_keys
->insert(key_pair
);
959 } else if (key_type
== KEY_TYPE_SWIFT
) {
960 swift_keys
->insert(key_pair
);
966 // modify an existing key
967 int RGWAccessKeyPool::modify_key(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
970 std::string key
= op_state
.get_secret_key();
971 int key_type
= op_state
.get_key_type();
973 RGWAccessKey modify_key
;
975 pair
<string
, RGWAccessKey
> key_pair
;
976 map
<std::string
, RGWAccessKey
>::iterator kiter
;
980 id
= op_state
.get_access_key();
982 set_err_msg(err_msg
, "no access key specified");
983 return -ERR_INVALID_ACCESS_KEY
;
987 id
= op_state
.build_default_swift_kid();
989 set_err_msg(err_msg
, "no subuser specified");
994 set_err_msg(err_msg
, "invalid key type");
995 return -ERR_INVALID_KEY_TYPE
;
998 if (!op_state
.has_existing_key()) {
999 set_err_msg(err_msg
, "key does not exist");
1000 return -ERR_INVALID_ACCESS_KEY
;
1003 key_pair
.first
= id
;
1005 if (key_type
== KEY_TYPE_SWIFT
) {
1007 modify_key
.subuser
= op_state
.get_subuser();
1008 } else if (key_type
== KEY_TYPE_S3
) {
1009 kiter
= access_keys
->find(id
);
1010 if (kiter
!= access_keys
->end()) {
1011 modify_key
= kiter
->second
;
1015 if (op_state
.will_gen_secret()) {
1016 char secret_key_buf
[SECRET_KEY_LEN
+ 1];
1019 int key_buf_size
= sizeof(secret_key_buf
);
1020 ret
= gen_rand_alphanumeric_plain(g_ceph_context
, secret_key_buf
, key_buf_size
);
1022 set_err_msg(err_msg
, "unable to generate secret key");
1026 key
= secret_key_buf
;
1030 set_err_msg(err_msg
, "empty secret key");
1031 return -ERR_INVALID_SECRET_KEY
;
1034 // update the access key with the new secret key
1035 modify_key
.key
= key
;
1037 key_pair
.second
= modify_key
;
1040 if (key_type
== KEY_TYPE_S3
) {
1041 (*access_keys
)[id
] = modify_key
;
1042 } else if (key_type
== KEY_TYPE_SWIFT
) {
1043 (*swift_keys
)[id
] = modify_key
;
1049 int RGWAccessKeyPool::execute_add(RGWUserAdminOpState
& op_state
,
1050 std::string
*err_msg
, bool defer_user_update
)
1054 std::string subprocess_msg
;
1055 int key_op
= GENERATE_KEY
;
1058 if (op_state
.has_existing_key())
1059 key_op
= MODIFY_KEY
;
1063 ret
= generate_key(op_state
, &subprocess_msg
);
1066 ret
= modify_key(op_state
, &subprocess_msg
);
1071 set_err_msg(err_msg
, subprocess_msg
);
1075 // store the updated info
1076 if (!defer_user_update
)
1077 ret
= user
->update(op_state
, err_msg
);
1085 int RGWAccessKeyPool::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1087 return add(op_state
, err_msg
, false);
1090 int RGWAccessKeyPool::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1093 std::string subprocess_msg
;
1095 ret
= check_op(op_state
, &subprocess_msg
);
1097 set_err_msg(err_msg
, "unable to parse request, " + subprocess_msg
);
1101 ret
= execute_add(op_state
, &subprocess_msg
, defer_user_update
);
1103 set_err_msg(err_msg
, "unable to add access key, " + subprocess_msg
);
1110 int RGWAccessKeyPool::execute_remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1114 int key_type
= op_state
.get_key_type();
1115 std::string id
= op_state
.get_access_key();
1116 map
<std::string
, RGWAccessKey
>::iterator kiter
;
1117 map
<std::string
, RGWAccessKey
> *keys_map
;
1119 if (!op_state
.has_existing_key()) {
1120 set_err_msg(err_msg
, "unable to find access key");
1121 return -ERR_INVALID_ACCESS_KEY
;
1124 if (key_type
== KEY_TYPE_S3
) {
1125 keys_map
= access_keys
;
1126 } else if (key_type
== KEY_TYPE_SWIFT
) {
1127 keys_map
= swift_keys
;
1130 set_err_msg(err_msg
, "invalid access key");
1131 return -ERR_INVALID_ACCESS_KEY
;
1134 kiter
= keys_map
->find(id
);
1135 if (kiter
== keys_map
->end()) {
1136 set_err_msg(err_msg
, "key not found");
1137 return -ERR_INVALID_ACCESS_KEY
;
1140 rgw_remove_key_index(store
, kiter
->second
);
1141 keys_map
->erase(kiter
);
1143 if (!defer_user_update
)
1144 ret
= user
->update(op_state
, err_msg
);
1152 int RGWAccessKeyPool::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1154 return remove(op_state
, err_msg
, false);
1157 int RGWAccessKeyPool::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1161 std::string subprocess_msg
;
1163 ret
= check_op(op_state
, &subprocess_msg
);
1165 set_err_msg(err_msg
, "unable to parse request, " + subprocess_msg
);
1169 ret
= execute_remove(op_state
, &subprocess_msg
, defer_user_update
);
1171 set_err_msg(err_msg
, "unable to remove access key, " + subprocess_msg
);
1178 // remove all keys associated with a subuser
1179 int RGWAccessKeyPool::remove_subuser_keys(RGWUserAdminOpState
& op_state
,
1180 std::string
*err_msg
, bool defer_user_update
)
1184 if (!op_state
.is_populated()) {
1185 set_err_msg(err_msg
, "user info was not populated");
1189 if (!op_state
.has_subuser()) {
1190 set_err_msg(err_msg
, "no subuser specified");
1194 std::string swift_kid
= op_state
.build_default_swift_kid();
1195 if (swift_kid
.empty()) {
1196 set_err_msg(err_msg
, "empty swift access key");
1200 map
<std::string
, RGWAccessKey
>::iterator kiter
;
1201 map
<std::string
, RGWAccessKey
> *keys_map
;
1203 // a subuser can have at most one swift key
1204 keys_map
= swift_keys
;
1205 kiter
= keys_map
->find(swift_kid
);
1206 if (kiter
!= keys_map
->end()) {
1207 rgw_remove_key_index(store
, kiter
->second
);
1208 keys_map
->erase(kiter
);
1211 // a subuser may have multiple s3 key pairs
1212 std::string subuser_str
= op_state
.get_subuser();
1213 keys_map
= access_keys
;
1214 RGWUserInfo user_info
= op_state
.get_user_info();
1215 map
<std::string
, RGWAccessKey
>::iterator user_kiter
= user_info
.access_keys
.begin();
1216 for (; user_kiter
!= user_info
.access_keys
.end(); ++user_kiter
) {
1217 if (user_kiter
->second
.subuser
== subuser_str
) {
1218 kiter
= keys_map
->find(user_kiter
->first
);
1219 if (kiter
!= keys_map
->end()) {
1220 rgw_remove_key_index(store
, kiter
->second
);
1221 keys_map
->erase(kiter
);
1226 if (!defer_user_update
)
1227 ret
= user
->update(op_state
, err_msg
);
1235 RGWSubUserPool::RGWSubUserPool(RGWUser
*usr
)
1237 subusers_allowed
= (usr
!= NULL
);
1239 store
= usr
->get_store();
1246 RGWSubUserPool::~RGWSubUserPool()
1251 int RGWSubUserPool::init(RGWUserAdminOpState
& op_state
)
1253 if (!op_state
.is_initialized()) {
1254 subusers_allowed
= false;
1258 rgw_user
& uid
= op_state
.get_user_id();
1259 if (uid
.compare(RGW_USER_ANON_ID
) == 0) {
1260 subusers_allowed
= false;
1264 subuser_map
= op_state
.get_subusers();
1265 if (subuser_map
== NULL
) {
1266 subusers_allowed
= false;
1270 subusers_allowed
= true;
1275 bool RGWSubUserPool::exists(std::string subuser
)
1277 if (subuser
.empty())
1283 if (subuser_map
->count(subuser
))
1289 int RGWSubUserPool::check_op(RGWUserAdminOpState
& op_state
,
1290 std::string
*err_msg
)
1292 bool existing
= false;
1293 std::string subuser
= op_state
.get_subuser();
1295 if (!op_state
.is_populated()) {
1296 set_err_msg(err_msg
, "user info was not populated");
1300 if (!subusers_allowed
) {
1301 set_err_msg(err_msg
, "subusers not allowed for this user");
1305 if (subuser
.empty() && !op_state
.will_gen_subuser()) {
1306 set_err_msg(err_msg
, "empty subuser name");
1310 if (op_state
.get_subuser_perm() == RGW_PERM_INVALID
) {
1311 set_err_msg(err_msg
, "invaild subuser access");
1315 //set key type when it not set or set by context
1316 if ((op_state
.get_key_type() < 0) || op_state
.key_type_setbycontext
) {
1317 op_state
.set_key_type(KEY_TYPE_SWIFT
);
1318 op_state
.key_type_setbycontext
= true;
1321 // check if the subuser exists
1322 if (!subuser
.empty())
1323 existing
= exists(subuser
);
1325 op_state
.set_existing_subuser(existing
);
1330 int RGWSubUserPool::execute_add(RGWUserAdminOpState
& op_state
,
1331 std::string
*err_msg
, bool defer_user_update
)
1334 std::string subprocess_msg
;
1337 std::pair
<std::string
, RGWSubUser
> subuser_pair
;
1338 std::string subuser_str
= op_state
.get_subuser();
1340 subuser_pair
.first
= subuser_str
;
1342 // assumes key should be created
1343 if (op_state
.has_key_op()) {
1344 ret
= user
->keys
.add(op_state
, &subprocess_msg
, true);
1346 set_err_msg(err_msg
, "unable to create subuser key, " + subprocess_msg
);
1351 // create the subuser
1352 subuser
.name
= subuser_str
;
1354 if (op_state
.has_subuser_perm())
1355 subuser
.perm_mask
= op_state
.get_subuser_perm();
1357 // insert the subuser into user info
1358 subuser_pair
.second
= subuser
;
1359 subuser_map
->insert(subuser_pair
);
1361 // attempt to save the subuser
1362 if (!defer_user_update
)
1363 ret
= user
->update(op_state
, err_msg
);
1371 int RGWSubUserPool::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1373 return add(op_state
, err_msg
, false);
1376 int RGWSubUserPool::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1378 std::string subprocess_msg
;
1380 int32_t key_type
= op_state
.get_key_type();
1382 ret
= check_op(op_state
, &subprocess_msg
);
1384 set_err_msg(err_msg
, "unable to parse request, " + subprocess_msg
);
1388 if (key_type
== KEY_TYPE_S3
&& op_state
.get_access_key().empty()) {
1389 op_state
.set_gen_access();
1392 if (op_state
.get_secret_key().empty()) {
1393 op_state
.set_gen_secret();
1396 ret
= execute_add(op_state
, &subprocess_msg
, defer_user_update
);
1398 set_err_msg(err_msg
, "unable to create subuser, " + subprocess_msg
);
1405 int RGWSubUserPool::execute_remove(RGWUserAdminOpState
& op_state
,
1406 std::string
*err_msg
, bool defer_user_update
)
1409 std::string subprocess_msg
;
1411 std::string subuser_str
= op_state
.get_subuser();
1413 map
<std::string
, RGWSubUser
>::iterator siter
;
1414 siter
= subuser_map
->find(subuser_str
);
1415 if (siter
== subuser_map
->end()){
1416 set_err_msg(err_msg
, "subuser not found: " + subuser_str
);
1419 if (!op_state
.has_existing_subuser()) {
1420 set_err_msg(err_msg
, "subuser not found: " + subuser_str
);
1424 // always purge all associate keys
1425 user
->keys
.remove_subuser_keys(op_state
, &subprocess_msg
, true);
1427 // remove the subuser from the user info
1428 subuser_map
->erase(siter
);
1430 // attempt to save the subuser
1431 if (!defer_user_update
)
1432 ret
= user
->update(op_state
, err_msg
);
1440 int RGWSubUserPool::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1442 return remove(op_state
, err_msg
, false);
1445 int RGWSubUserPool::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1447 std::string subprocess_msg
;
1450 ret
= check_op(op_state
, &subprocess_msg
);
1452 set_err_msg(err_msg
, "unable to parse request, " + subprocess_msg
);
1456 ret
= execute_remove(op_state
, &subprocess_msg
, defer_user_update
);
1458 set_err_msg(err_msg
, "unable to remove subuser, " + subprocess_msg
);
1465 int RGWSubUserPool::execute_modify(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1468 std::string subprocess_msg
;
1469 std::map
<std::string
, RGWSubUser
>::iterator siter
;
1470 std::pair
<std::string
, RGWSubUser
> subuser_pair
;
1472 std::string subuser_str
= op_state
.get_subuser();
1475 if (!op_state
.has_existing_subuser()) {
1476 set_err_msg(err_msg
, "subuser does not exist");
1480 subuser_pair
.first
= subuser_str
;
1482 siter
= subuser_map
->find(subuser_str
);
1483 subuser
= siter
->second
;
1485 if (op_state
.has_key_op()) {
1486 ret
= user
->keys
.add(op_state
, &subprocess_msg
, true);
1488 set_err_msg(err_msg
, "unable to create subuser keys, " + subprocess_msg
);
1493 if (op_state
.has_subuser_perm())
1494 subuser
.perm_mask
= op_state
.get_subuser_perm();
1496 subuser_pair
.second
= subuser
;
1498 subuser_map
->erase(siter
);
1499 subuser_map
->insert(subuser_pair
);
1501 // attempt to save the subuser
1502 if (!defer_user_update
)
1503 ret
= user
->update(op_state
, err_msg
);
1511 int RGWSubUserPool::modify(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1513 return RGWSubUserPool::modify(op_state
, err_msg
, false);
1516 int RGWSubUserPool::modify(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_user_update
)
1518 std::string subprocess_msg
;
1523 ret
= check_op(op_state
, &subprocess_msg
);
1525 set_err_msg(err_msg
, "unable to parse request, " + subprocess_msg
);
1529 ret
= execute_modify(op_state
, &subprocess_msg
, defer_user_update
);
1531 set_err_msg(err_msg
, "unable to modify subuser, " + subprocess_msg
);
1538 RGWUserCapPool::RGWUserCapPool(RGWUser
*usr
)
1542 caps_allowed
= (user
!= NULL
);
1545 RGWUserCapPool::~RGWUserCapPool()
1550 int RGWUserCapPool::init(RGWUserAdminOpState
& op_state
)
1552 if (!op_state
.is_initialized()) {
1553 caps_allowed
= false;
1557 rgw_user
& uid
= op_state
.get_user_id();
1558 if (uid
.compare(RGW_USER_ANON_ID
) == 0) {
1559 caps_allowed
= false;
1563 caps
= op_state
.get_caps_obj();
1565 caps_allowed
= false;
1566 return -ERR_INVALID_CAP
;
1569 caps_allowed
= true;
1574 int RGWUserCapPool::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1576 return add(op_state
, err_msg
, false);
1579 int RGWUserCapPool::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_save
)
1582 std::string caps_str
= op_state
.get_caps();
1584 if (!op_state
.is_populated()) {
1585 set_err_msg(err_msg
, "user info was not populated");
1589 if (!caps_allowed
) {
1590 set_err_msg(err_msg
, "caps not allowed for this user");
1594 if (caps_str
.empty()) {
1595 set_err_msg(err_msg
, "empty user caps");
1596 return -ERR_INVALID_CAP
;
1599 int r
= caps
->add_from_string(caps_str
);
1601 set_err_msg(err_msg
, "unable to add caps: " + caps_str
);
1606 ret
= user
->update(op_state
, err_msg
);
1614 int RGWUserCapPool::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1616 return remove(op_state
, err_msg
, false);
1619 int RGWUserCapPool::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
, bool defer_save
)
1623 std::string caps_str
= op_state
.get_caps();
1625 if (!op_state
.is_populated()) {
1626 set_err_msg(err_msg
, "user info was not populated");
1630 if (!caps_allowed
) {
1631 set_err_msg(err_msg
, "caps not allowed for this user");
1635 if (caps_str
.empty()) {
1636 set_err_msg(err_msg
, "empty user caps");
1637 return -ERR_INVALID_CAP
;
1640 int r
= caps
->remove_from_string(caps_str
);
1642 set_err_msg(err_msg
, "unable to remove caps: " + caps_str
);
1647 ret
= user
->update(op_state
, err_msg
);
1655 RGWUser::RGWUser() : store(NULL
), info_stored(false), caps(this), keys(this), subusers(this)
1660 int RGWUser::init(RGWRados
*storage
, RGWUserAdminOpState
& op_state
)
1663 int ret
= init_storage(storage
);
1667 ret
= init(op_state
);
1678 void RGWUser::init_default()
1680 // use anonymous user info as a placeholder
1681 rgw_get_anon_user(old_info
);
1682 user_id
= RGW_USER_ANON_ID
;
1687 int RGWUser::init_storage(RGWRados
*storage
)
1698 keys
= RGWAccessKeyPool(this);
1699 caps
= RGWUserCapPool(this);
1700 subusers
= RGWSubUserPool(this);
1705 int RGWUser::init(RGWUserAdminOpState
& op_state
)
1708 std::string swift_user
;
1709 rgw_user
& uid
= op_state
.get_user_id();
1710 std::string user_email
= op_state
.get_user_email();
1711 std::string access_key
= op_state
.get_access_key();
1712 std::string subuser
= op_state
.get_subuser();
1714 int key_type
= op_state
.get_key_type();
1715 if (key_type
== KEY_TYPE_SWIFT
) {
1716 swift_user
= op_state
.get_access_key();
1720 RGWUserInfo user_info
;
1724 if (uid
.empty() && !subuser
.empty()) {
1725 size_t pos
= subuser
.find(':');
1726 if (pos
!= string::npos
) {
1727 uid
= subuser
.substr(0, pos
);
1728 op_state
.set_user_id(uid
);
1732 if (!uid
.empty() && (uid
.compare(RGW_USER_ANON_ID
) != 0)) {
1733 found
= (rgw_get_user_info_by_uid(store
, uid
, user_info
, &op_state
.objv
) >= 0);
1734 op_state
.found_by_uid
= found
;
1736 if (!user_email
.empty() && !found
) {
1737 found
= (rgw_get_user_info_by_email(store
, user_email
, user_info
, &op_state
.objv
) >= 0);
1738 op_state
.found_by_email
= found
;
1740 if (!swift_user
.empty() && !found
) {
1741 found
= (rgw_get_user_info_by_swift(store
, swift_user
, user_info
, &op_state
.objv
) >= 0);
1742 op_state
.found_by_key
= found
;
1744 if (!access_key
.empty() && !found
) {
1745 found
= (rgw_get_user_info_by_access_key(store
, access_key
, user_info
, &op_state
.objv
) >= 0);
1746 op_state
.found_by_key
= found
;
1749 op_state
.set_existing_user(found
);
1751 op_state
.set_user_info(user_info
);
1752 op_state
.set_populated();
1754 old_info
= user_info
;
1758 user_id
= user_info
.user_id
;
1759 op_state
.set_initialized();
1761 // this may have been called by a helper object
1762 int ret
= init_members(op_state
);
1769 int RGWUser::init_members(RGWUserAdminOpState
& op_state
)
1773 ret
= keys
.init(op_state
);
1777 ret
= subusers
.init(op_state
);
1781 ret
= caps
.init(op_state
);
1788 int RGWUser::update(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1791 std::string subprocess_msg
;
1792 RGWUserInfo user_info
= op_state
.get_user_info();
1795 set_err_msg(err_msg
, "couldn't initialize storage");
1799 if (is_populated()) {
1800 ret
= rgw_store_user_info(store
, user_info
, &old_info
, &op_state
.objv
, real_time(), false);
1802 set_err_msg(err_msg
, "unable to store user info");
1806 ret
= remove_old_indexes(store
, old_info
, user_info
, &subprocess_msg
);
1808 set_err_msg(err_msg
, "unable to remove old user info, " + subprocess_msg
);
1812 ret
= rgw_store_user_info(store
, user_info
, NULL
, &op_state
.objv
, real_time(), false);
1814 set_err_msg(err_msg
, "unable to store user info");
1819 old_info
= user_info
;
1825 int RGWUser::check_op(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1829 rgw_user
& op_id
= op_state
.get_user_id();
1831 RGWUserInfo user_info
;
1833 same_id
= (user_id
.compare(op_id
) == 0);
1834 populated
= is_populated();
1836 if (op_id
.compare(RGW_USER_ANON_ID
) == 0) {
1837 set_err_msg(err_msg
, "unable to perform operations on the anonymous user");
1841 if (populated
&& !same_id
) {
1842 set_err_msg(err_msg
, "user id mismatch, operation id: " + op_id
.to_str()
1843 + " does not match: " + user_id
.to_str());
1848 //set key type when it not set or set by context
1849 if ((op_state
.get_key_type() < 0) || op_state
.key_type_setbycontext
) {
1850 op_state
.set_key_type(KEY_TYPE_S3
);
1851 op_state
.key_type_setbycontext
= true;
1857 int RGWUser::execute_add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
1859 std::string subprocess_msg
;
1861 bool defer_user_update
= true;
1863 RGWUserInfo user_info
;
1865 rgw_user
& uid
= op_state
.get_user_id();
1866 std::string user_email
= op_state
.get_user_email();
1867 std::string display_name
= op_state
.get_display_name();
1869 // fail if the user exists already
1870 if (op_state
.has_existing_user()) {
1871 if (!op_state
.exclusive
&&
1872 (user_email
.empty() ||
1873 boost::iequals(user_email
, old_info
.user_email
)) &&
1874 old_info
.display_name
== display_name
) {
1875 return execute_modify(op_state
, err_msg
);
1878 if (op_state
.found_by_email
) {
1879 set_err_msg(err_msg
, "email: " + user_email
+
1880 " is the email address an existing user");
1881 ret
= -ERR_EMAIL_EXIST
;
1882 } else if (op_state
.found_by_key
) {
1883 set_err_msg(err_msg
, "duplicate key provided");
1884 ret
= -ERR_KEY_EXIST
;
1886 set_err_msg(err_msg
, "user: " + op_state
.user_id
.to_str() + " exists");
1892 // fail if the user_info has already been populated
1893 if (op_state
.is_populated()) {
1894 set_err_msg(err_msg
, "cannot overwrite already populated user");
1898 // fail if the display name was not included
1899 if (display_name
.empty()) {
1900 set_err_msg(err_msg
, "no display name specified");
1905 // set the user info
1907 user_info
.user_id
= user_id
;
1908 user_info
.display_name
= display_name
;
1909 user_info
.type
= TYPE_RGW
;
1911 if (!user_email
.empty())
1912 user_info
.user_email
= user_email
;
1914 CephContext
*cct
= store
->ctx();
1915 if (op_state
.max_buckets_specified
) {
1916 user_info
.max_buckets
= op_state
.get_max_buckets();
1918 user_info
.max_buckets
= cct
->_conf
->rgw_user_max_buckets
;
1921 user_info
.suspended
= op_state
.get_suspension_status();
1922 user_info
.admin
= op_state
.admin
;
1923 user_info
.system
= op_state
.system
;
1925 if (op_state
.op_mask_specified
)
1926 user_info
.op_mask
= op_state
.get_op_mask();
1928 if (op_state
.has_bucket_quota()) {
1929 user_info
.bucket_quota
= op_state
.get_bucket_quota();
1931 if (cct
->_conf
->rgw_bucket_default_quota_max_objects
>= 0) {
1932 user_info
.bucket_quota
.max_objects
= cct
->_conf
->rgw_bucket_default_quota_max_objects
;
1933 user_info
.bucket_quota
.enabled
= true;
1935 if (cct
->_conf
->rgw_bucket_default_quota_max_size
>= 0) {
1936 user_info
.bucket_quota
.max_size
= cct
->_conf
->rgw_bucket_default_quota_max_size
;
1937 user_info
.bucket_quota
.enabled
= true;
1941 if (op_state
.temp_url_key_specified
) {
1942 map
<int, string
>::iterator iter
;
1943 for (iter
= op_state
.temp_url_keys
.begin();
1944 iter
!= op_state
.temp_url_keys
.end(); ++iter
) {
1945 user_info
.temp_url_keys
[iter
->first
] = iter
->second
;
1949 if (op_state
.has_user_quota()) {
1950 user_info
.user_quota
= op_state
.get_user_quota();
1952 if (cct
->_conf
->rgw_user_default_quota_max_objects
>= 0) {
1953 user_info
.user_quota
.max_objects
= cct
->_conf
->rgw_user_default_quota_max_objects
;
1954 user_info
.user_quota
.enabled
= true;
1956 if (cct
->_conf
->rgw_user_default_quota_max_size
>= 0) {
1957 user_info
.user_quota
.max_size
= cct
->_conf
->rgw_user_default_quota_max_size
;
1958 user_info
.user_quota
.enabled
= true;
1962 // update the request
1963 op_state
.set_user_info(user_info
);
1964 op_state
.set_populated();
1966 // update the helper objects
1967 ret
= init_members(op_state
);
1969 set_err_msg(err_msg
, "unable to initialize user");
1973 // see if we need to add an access key
1974 if (op_state
.has_key_op()) {
1975 ret
= keys
.add(op_state
, &subprocess_msg
, defer_user_update
);
1977 set_err_msg(err_msg
, "unable to create access key, " + subprocess_msg
);
1982 // see if we need to add some caps
1983 if (op_state
.has_caps_op()) {
1984 ret
= caps
.add(op_state
, &subprocess_msg
, defer_user_update
);
1986 set_err_msg(err_msg
, "unable to add user capabilities, " + subprocess_msg
);
1991 ret
= update(op_state
, err_msg
);
1998 int RGWUser::add(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
2000 std::string subprocess_msg
;
2003 ret
= check_op(op_state
, &subprocess_msg
);
2005 set_err_msg(err_msg
, "unable to parse parameters, " + subprocess_msg
);
2009 ret
= execute_add(op_state
, &subprocess_msg
);
2011 set_err_msg(err_msg
, "unable to create user, " + subprocess_msg
);
2018 int RGWUser::execute_remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
2022 bool purge_data
= op_state
.will_purge_data();
2023 rgw_user
& uid
= op_state
.get_user_id();
2024 RGWUserInfo user_info
= op_state
.get_user_info();
2026 if (!op_state
.has_existing_user()) {
2027 set_err_msg(err_msg
, "user does not exist");
2031 bool is_truncated
= false;
2033 CephContext
*cct
= store
->ctx();
2034 size_t max_buckets
= cct
->_conf
->rgw_list_buckets_max_chunk
;
2036 RGWUserBuckets buckets
;
2037 ret
= rgw_read_user_buckets(store
, uid
, buckets
, marker
, string(),
2038 max_buckets
, false, &is_truncated
);
2040 set_err_msg(err_msg
, "unable to read user bucket info");
2044 map
<std::string
, RGWBucketEnt
>& m
= buckets
.get_buckets();
2045 if (!m
.empty() && !purge_data
) {
2046 set_err_msg(err_msg
, "must specify purge data to remove user with buckets");
2047 return -EEXIST
; // change to code that maps to 409: conflict
2050 std::map
<std::string
, RGWBucketEnt
>::iterator it
;
2051 for (it
= m
.begin(); it
!= m
.end(); ++it
) {
2052 ret
= rgw_remove_bucket(store
, ((*it
).second
).bucket
, true);
2054 set_err_msg(err_msg
, "unable to delete user data");
2061 } while (is_truncated
);
2063 ret
= rgw_delete_user(store
, user_info
, op_state
.objv
);
2065 set_err_msg(err_msg
, "unable to remove user from RADOS");
2069 op_state
.clear_populated();
2075 int RGWUser::remove(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
2077 std::string subprocess_msg
;
2080 ret
= check_op(op_state
, &subprocess_msg
);
2082 set_err_msg(err_msg
, "unable to parse parameters, " + subprocess_msg
);
2086 ret
= execute_remove(op_state
, &subprocess_msg
);
2088 set_err_msg(err_msg
, "unable to remove user, " + subprocess_msg
);
2095 int RGWUser::execute_modify(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
2097 bool populated
= op_state
.is_populated();
2099 std::string subprocess_msg
;
2100 std::string op_email
= op_state
.get_user_email();
2101 std::string display_name
= op_state
.get_display_name();
2103 RGWUserInfo user_info
;
2104 RGWUserInfo duplicate_check
;
2106 // ensure that the user info has been populated or is populate-able
2107 if (!op_state
.has_existing_user() && !populated
) {
2108 set_err_msg(err_msg
, "user not found");
2112 // if the user hasn't already been populated...attempt to
2114 ret
= init(op_state
);
2116 set_err_msg(err_msg
, "unable to retrieve user info");
2121 // ensure that we can modify the user's attributes
2122 if (user_id
.compare(RGW_USER_ANON_ID
) == 0) {
2123 set_err_msg(err_msg
, "unable to modify anonymous user's info");
2127 user_info
= old_info
;
2129 std::string old_email
= old_info
.user_email
;
2130 if (!op_email
.empty()) {
2131 // make sure we are not adding a duplicate email
2132 if (old_email
.compare(op_email
) != 0) {
2133 ret
= rgw_get_user_info_by_email(store
, op_email
, duplicate_check
);
2134 if (ret
>= 0 && duplicate_check
.user_id
.compare(user_id
) != 0) {
2135 set_err_msg(err_msg
, "cannot add duplicate email");
2136 return -ERR_EMAIL_EXIST
;
2139 user_info
.user_email
= op_email
;
2140 } else if (op_email
.empty() && op_state
.user_email_specified
) {
2142 ldout(store
->ctx(), 10) << "removing email index: " << user_info
.user_email
<< dendl
;
2143 ret
= rgw_remove_email_index(store
, user_info
.user_email
);
2144 if (ret
< 0 && ret
!= -ENOENT
) {
2145 ldout(store
->ctx(), 0) << "ERROR: could not remove " << user_info
.user_id
<< " index (err=" << ret
<< ")" << dendl
;
2148 user_info
.user_email
= "";
2151 // update the remaining user info
2152 if (!display_name
.empty())
2153 user_info
.display_name
= display_name
;
2155 if (op_state
.max_buckets_specified
)
2156 user_info
.max_buckets
= op_state
.get_max_buckets();
2158 if (op_state
.admin_specified
)
2159 user_info
.admin
= op_state
.admin
;
2161 if (op_state
.system_specified
)
2162 user_info
.system
= op_state
.system
;
2164 if (op_state
.temp_url_key_specified
) {
2165 map
<int, string
>::iterator iter
;
2166 for (iter
= op_state
.temp_url_keys
.begin();
2167 iter
!= op_state
.temp_url_keys
.end(); ++iter
) {
2168 user_info
.temp_url_keys
[iter
->first
] = iter
->second
;
2172 if (op_state
.op_mask_specified
)
2173 user_info
.op_mask
= op_state
.get_op_mask();
2175 if (op_state
.has_bucket_quota())
2176 user_info
.bucket_quota
= op_state
.get_bucket_quota();
2178 if (op_state
.has_user_quota())
2179 user_info
.user_quota
= op_state
.get_user_quota();
2181 if (op_state
.has_suspension_op()) {
2182 __u8 suspended
= op_state
.get_suspension_status();
2183 user_info
.suspended
= suspended
;
2185 RGWUserBuckets buckets
;
2187 if (user_id
.empty()) {
2188 set_err_msg(err_msg
, "empty user id passed...aborting");
2192 bool is_truncated
= false;
2194 CephContext
*cct
= store
->ctx();
2195 size_t max_buckets
= cct
->_conf
->rgw_list_buckets_max_chunk
;
2197 ret
= rgw_read_user_buckets(store
, user_id
, buckets
, marker
, string(),
2198 max_buckets
, false, &is_truncated
);
2200 set_err_msg(err_msg
, "could not get buckets for uid: " + user_id
.to_str());
2204 map
<string
, RGWBucketEnt
>& m
= buckets
.get_buckets();
2205 map
<string
, RGWBucketEnt
>::iterator iter
;
2207 vector
<rgw_bucket
> bucket_names
;
2208 for (iter
= m
.begin(); iter
!= m
.end(); ++iter
) {
2209 RGWBucketEnt obj
= iter
->second
;
2210 bucket_names
.push_back(obj
.bucket
);
2212 marker
= iter
->first
;
2215 ret
= store
->set_buckets_enabled(bucket_names
, !suspended
);
2217 set_err_msg(err_msg
, "failed to modify bucket");
2221 } while (is_truncated
);
2223 op_state
.set_user_info(user_info
);
2225 // if we're supposed to modify keys, do so
2226 if (op_state
.has_key_op()) {
2227 ret
= keys
.add(op_state
, &subprocess_msg
, true);
2229 set_err_msg(err_msg
, "unable to create or modify keys, " + subprocess_msg
);
2234 ret
= update(op_state
, err_msg
);
2241 int RGWUser::modify(RGWUserAdminOpState
& op_state
, std::string
*err_msg
)
2243 std::string subprocess_msg
;
2246 ret
= check_op(op_state
, &subprocess_msg
);
2248 set_err_msg(err_msg
, "unable to parse parameters, " + subprocess_msg
);
2252 ret
= execute_modify(op_state
, &subprocess_msg
);
2254 set_err_msg(err_msg
, "unable to modify user, " + subprocess_msg
);
2261 int RGWUser::info(RGWUserAdminOpState
& op_state
, RGWUserInfo
& fetched_info
, std::string
*err_msg
)
2263 int ret
= init(op_state
);
2265 set_err_msg(err_msg
, "unable to fetch user info");
2269 fetched_info
= op_state
.get_user_info();
2274 int RGWUser::info(RGWUserInfo
& fetched_info
, std::string
*err_msg
)
2276 if (!is_populated()) {
2277 set_err_msg(err_msg
, "no user info saved");
2281 fetched_info
= old_info
;
2286 int RGWUserAdminOp_User::info(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2287 RGWFormatterFlusher
& flusher
)
2292 int ret
= user
.init(store
, op_state
);
2296 if (!op_state
.has_existing_user())
2299 Formatter
*formatter
= flusher
.get_formatter();
2301 ret
= user
.info(info
, NULL
);
2305 RGWStorageStats stats
;
2306 RGWStorageStats
*arg_stats
= NULL
;
2307 if (op_state
.fetch_stats
) {
2308 int ret
= store
->get_user_stats(info
.user_id
, stats
);
2318 dump_user_info(formatter
, info
, arg_stats
);
2324 int RGWUserAdminOp_User::create(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2325 RGWFormatterFlusher
& flusher
)
2329 int ret
= user
.init(store
, op_state
);
2333 Formatter
*formatter
= flusher
.get_formatter();
2335 ret
= user
.add(op_state
, NULL
);
2338 ret
= -ERR_USER_EXIST
;
2342 ret
= user
.info(info
, NULL
);
2348 dump_user_info(formatter
, info
);
2354 int RGWUserAdminOp_User::modify(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2355 RGWFormatterFlusher
& flusher
)
2359 int ret
= user
.init(store
, op_state
);
2362 Formatter
*formatter
= flusher
.get_formatter();
2364 ret
= user
.modify(op_state
, NULL
);
2368 ret
= user
.info(info
, NULL
);
2374 dump_user_info(formatter
, info
);
2380 int RGWUserAdminOp_User::remove(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2381 RGWFormatterFlusher
& flusher
)
2385 int ret
= user
.init(store
, op_state
);
2390 ret
= user
.remove(op_state
, NULL
);
2395 int RGWUserAdminOp_Subuser::create(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2396 RGWFormatterFlusher
& flusher
)
2400 int ret
= user
.init(store
, op_state
);
2404 Formatter
*formatter
= flusher
.get_formatter();
2406 ret
= user
.subusers
.add(op_state
, NULL
);
2410 ret
= user
.info(info
, NULL
);
2416 dump_subusers_info(formatter
, info
);
2422 int RGWUserAdminOp_Subuser::modify(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2423 RGWFormatterFlusher
& flusher
)
2427 int ret
= user
.init(store
, op_state
);
2431 Formatter
*formatter
= flusher
.get_formatter();
2433 ret
= user
.subusers
.modify(op_state
, NULL
);
2437 ret
= user
.info(info
, NULL
);
2443 dump_subusers_info(formatter
, info
);
2449 int RGWUserAdminOp_Subuser::remove(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2450 RGWFormatterFlusher
& flusher
)
2454 int ret
= user
.init(store
, op_state
);
2459 ret
= user
.subusers
.remove(op_state
, NULL
);
2466 int RGWUserAdminOp_Key::create(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2467 RGWFormatterFlusher
& flusher
)
2471 int ret
= user
.init(store
, op_state
);
2475 Formatter
*formatter
= flusher
.get_formatter();
2477 ret
= user
.keys
.add(op_state
, NULL
);
2481 ret
= user
.info(info
, NULL
);
2487 int key_type
= op_state
.get_key_type();
2489 if (key_type
== KEY_TYPE_SWIFT
)
2490 dump_swift_keys_info(formatter
, info
);
2492 else if (key_type
== KEY_TYPE_S3
)
2493 dump_access_keys_info(formatter
, info
);
2500 int RGWUserAdminOp_Key::remove(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2501 RGWFormatterFlusher
& flusher
)
2505 int ret
= user
.init(store
, op_state
);
2510 ret
= user
.keys
.remove(op_state
, NULL
);
2517 int RGWUserAdminOp_Caps::add(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2518 RGWFormatterFlusher
& flusher
)
2522 int ret
= user
.init(store
, op_state
);
2526 Formatter
*formatter
= flusher
.get_formatter();
2528 ret
= user
.caps
.add(op_state
, NULL
);
2532 ret
= user
.info(info
, NULL
);
2538 info
.caps
.dump(formatter
);
2545 int RGWUserAdminOp_Caps::remove(RGWRados
*store
, RGWUserAdminOpState
& op_state
,
2546 RGWFormatterFlusher
& flusher
)
2550 int ret
= user
.init(store
, op_state
);
2554 Formatter
*formatter
= flusher
.get_formatter();
2556 ret
= user
.caps
.remove(op_state
, NULL
);
2560 ret
= user
.info(info
, NULL
);
2566 info
.caps
.dump(formatter
);
2572 struct RGWUserCompleteInfo
{
2574 map
<string
, bufferlist
> attrs
;
2577 RGWUserCompleteInfo()
2581 void dump(Formatter
* const f
) const {
2583 encode_json("attrs", attrs
, f
);
2586 void decode_json(JSONObj
*obj
) {
2587 decode_json_obj(info
, obj
);
2588 has_attrs
= JSONDecoder::decode_json("attrs", attrs
, obj
);
2592 class RGWUserMetadataObject
: public RGWMetadataObject
{
2593 RGWUserCompleteInfo uci
;
2595 RGWUserMetadataObject(const RGWUserCompleteInfo
& _uci
, obj_version
& v
, real_time m
)
2601 void dump(Formatter
*f
) const override
{
2606 class RGWUserMetadataHandler
: public RGWMetadataHandler
{
2608 string
get_type() override
{ return "user"; }
2610 int get(RGWRados
*store
, string
& entry
, RGWMetadataObject
**obj
) override
{
2611 RGWUserCompleteInfo uci
;
2612 RGWObjVersionTracker objv_tracker
;
2615 rgw_user
uid(entry
);
2617 int ret
= rgw_get_user_info_by_uid(store
, uid
, uci
.info
, &objv_tracker
,
2618 &mtime
, NULL
, &uci
.attrs
);
2623 RGWUserMetadataObject
*mdo
= new RGWUserMetadataObject(uci
, objv_tracker
.read_version
, mtime
);
2629 int put(RGWRados
*store
, string
& entry
, RGWObjVersionTracker
& objv_tracker
,
2630 real_time mtime
, JSONObj
*obj
, sync_type_t sync_mode
) override
{
2631 RGWUserCompleteInfo uci
;
2634 decode_json_obj(uci
, obj
);
2635 } catch (JSONDecoder::err
& e
) {
2639 map
<string
, bufferlist
> *pattrs
= NULL
;
2640 if (uci
.has_attrs
) {
2641 pattrs
= &uci
.attrs
;
2644 rgw_user
uid(entry
);
2646 RGWUserInfo old_info
;
2647 real_time orig_mtime
;
2648 int ret
= rgw_get_user_info_by_uid(store
, uid
, old_info
, &objv_tracker
, &orig_mtime
);
2649 if (ret
< 0 && ret
!= -ENOENT
)
2652 // are we actually going to perform this put, or is it too old?
2653 if (ret
!= -ENOENT
&&
2654 !check_versions(objv_tracker
.read_version
, orig_mtime
,
2655 objv_tracker
.write_version
, mtime
, sync_mode
)) {
2656 return STATUS_NO_APPLY
;
2659 ret
= rgw_store_user_info(store
, uci
.info
, &old_info
, &objv_tracker
, mtime
, false, pattrs
);
2664 return STATUS_APPLIED
;
2667 struct list_keys_info
{
2669 RGWListRawObjsCtx ctx
;
2672 int remove(RGWRados
*store
, string
& entry
, RGWObjVersionTracker
& objv_tracker
) override
{
2675 rgw_user
uid(entry
);
2677 int ret
= rgw_get_user_info_by_uid(store
, uid
, info
, &objv_tracker
);
2681 return rgw_delete_user(store
, info
, objv_tracker
);
2684 void get_pool_and_oid(RGWRados
*store
, const string
& key
, rgw_pool
& pool
, string
& oid
) override
{
2686 pool
= store
->get_zone_params().user_uid_pool
;
2689 int list_keys_init(RGWRados
*store
, void **phandle
) override
2691 list_keys_info
*info
= new list_keys_info
;
2693 info
->store
= store
;
2695 *phandle
= (void *)info
;
2700 int list_keys_next(void *handle
, int max
, list
<string
>& keys
, bool *truncated
) override
{
2701 list_keys_info
*info
= static_cast<list_keys_info
*>(handle
);
2707 RGWRados
*store
= info
->store
;
2709 list
<string
> unfiltered_keys
;
2711 int ret
= store
->list_raw_objects(store
->get_zone_params().user_uid_pool
, no_filter
,
2712 max
, info
->ctx
, unfiltered_keys
, truncated
);
2713 if (ret
< 0 && ret
!= -ENOENT
)
2715 if (ret
== -ENOENT
) {
2721 // now filter out the buckets entries
2722 list
<string
>::iterator iter
;
2723 for (iter
= unfiltered_keys
.begin(); iter
!= unfiltered_keys
.end(); ++iter
) {
2726 if (k
.find(".buckets") == string::npos
) {
2734 void list_keys_complete(void *handle
) override
{
2735 list_keys_info
*info
= static_cast<list_keys_info
*>(handle
);
2740 void rgw_user_init(RGWRados
*store
)
2742 uinfo_cache
.init(store
);
2744 user_meta_handler
= new RGWUserMetadataHandler
;
2745 store
->meta_mgr
->register_handler(user_meta_handler
);