Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / rgw / rgw_rest_user.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "common/ceph_json.h"
5
6 #include "rgw_op.h"
7 #include "rgw_user.h"
8 #include "rgw_rest_user.h"
9
10 #include "include/str_list.h"
11 #include "include/assert.h"
12
13 #define dout_subsys ceph_subsys_rgw
14
15 class RGWOp_User_Info : public RGWRESTOp {
16
17 public:
18   RGWOp_User_Info() {}
19
20   int check_caps(RGWUserCaps& caps) override {
21     return caps.check_cap("users", RGW_CAP_READ);
22   }
23
24   void execute() override;
25
26   const string name() override { return "get_user_info"; }
27 };
28
29 void RGWOp_User_Info::execute()
30 {
31   RGWUserAdminOpState op_state;
32
33   std::string uid_str;
34   bool fetch_stats;
35   bool sync_stats;
36
37   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
38
39   // if uid was not supplied in rest argument, error out now, otherwise we'll
40   // end up initializing anonymous user, for which keys.init will eventually
41   // return -EACESS
42   if (uid_str.empty()){
43     http_ret=-EINVAL;
44     return;
45   }
46
47   rgw_user uid(uid_str);
48
49   RESTArgs::get_bool(s, "stats", false, &fetch_stats);
50
51   RESTArgs::get_bool(s, "sync", false, &sync_stats);
52
53   op_state.set_user_id(uid);
54   op_state.set_fetch_stats(fetch_stats);
55   op_state.set_sync_stats(sync_stats);
56
57   http_ret = RGWUserAdminOp_User::info(store, op_state, flusher);
58 }
59
60 class RGWOp_User_Create : public RGWRESTOp {
61
62 public:
63   RGWOp_User_Create() {}
64
65   int check_caps(RGWUserCaps& caps) override {
66     return caps.check_cap("users", RGW_CAP_WRITE);
67   }
68
69   void execute() override;
70
71   const string name() override { return "create_user"; }
72 };
73
74 void RGWOp_User_Create::execute()
75 {
76   std::string uid_str;
77   std::string display_name;
78   std::string email;
79   std::string access_key;
80   std::string secret_key;
81   std::string key_type_str;
82   std::string caps;
83   std::string tenant_name;
84
85   bool gen_key;
86   bool suspended;
87   bool system;
88   bool exclusive;
89
90   int32_t max_buckets;
91   int32_t default_max_buckets = s->cct->_conf->rgw_user_max_buckets;
92
93   RGWUserAdminOpState op_state;
94
95   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
96   rgw_user uid(uid_str);
97
98   RESTArgs::get_string(s, "display-name", display_name, &display_name);
99   RESTArgs::get_string(s, "email", email, &email);
100   RESTArgs::get_string(s, "access-key", access_key, &access_key);
101   RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
102   RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
103   RESTArgs::get_string(s, "user-caps", caps, &caps);
104   RESTArgs::get_string(s, "tenant", tenant_name, &tenant_name);
105   RESTArgs::get_bool(s, "generate-key", true, &gen_key);
106   RESTArgs::get_bool(s, "suspended", false, &suspended);
107   RESTArgs::get_int32(s, "max-buckets", default_max_buckets, &max_buckets);
108   RESTArgs::get_bool(s, "system", false, &system);
109   RESTArgs::get_bool(s, "exclusive", false, &exclusive);
110
111   if (!s->user->system && system) {
112     ldout(s->cct, 0) << "cannot set system flag by non-system user" << dendl;
113     http_ret = -EINVAL;
114     return;
115   }
116
117   if (!tenant_name.empty()) {
118     uid.tenant = tenant_name;
119   }
120
121   // TODO: validate required args are passed in. (for eg. uid and display_name here)
122   op_state.set_user_id(uid);
123   op_state.set_display_name(display_name);
124   op_state.set_user_email(email);
125   op_state.set_caps(caps);
126   op_state.set_access_key(access_key);
127   op_state.set_secret_key(secret_key);
128
129   if (!key_type_str.empty()) {
130     int32_t key_type = KEY_TYPE_UNDEFINED;
131     if (key_type_str.compare("swift") == 0)
132       key_type = KEY_TYPE_SWIFT;
133     else if (key_type_str.compare("s3") == 0)
134       key_type = KEY_TYPE_S3;
135
136     op_state.set_key_type(key_type);
137   }
138
139   if (max_buckets != default_max_buckets)
140     op_state.set_max_buckets(max_buckets);
141
142   if (s->info.args.exists("suspended"))
143     op_state.set_suspension(suspended);
144
145   if (s->info.args.exists("system"))
146     op_state.set_system(system);
147
148   if (s->info.args.exists("exclusive"))
149     op_state.set_exclusive(exclusive);
150
151   if (gen_key)
152     op_state.set_generate_key();
153
154   RGWQuotaInfo bucket_quota;
155   RGWQuotaInfo user_quota;
156
157   if (s->cct->_conf->rgw_bucket_default_quota_max_objects >= 0) {
158     bucket_quota.max_objects = s->cct->_conf->rgw_bucket_default_quota_max_objects;
159     bucket_quota.enabled = true;
160   }
161
162   if (s->cct->_conf->rgw_bucket_default_quota_max_size >= 0) {
163     bucket_quota.max_size = s->cct->_conf->rgw_bucket_default_quota_max_size;
164     bucket_quota.enabled = true;
165   }
166
167   if (s->cct->_conf->rgw_user_default_quota_max_objects >= 0) {
168     user_quota.max_objects = s->cct->_conf->rgw_user_default_quota_max_objects;
169     user_quota.enabled = true;
170   }
171
172   if (s->cct->_conf->rgw_user_default_quota_max_size >= 0) {
173     user_quota.max_size = s->cct->_conf->rgw_user_default_quota_max_size;
174     user_quota.enabled = true;
175   }
176
177   if (bucket_quota.enabled) {
178     op_state.set_bucket_quota(bucket_quota);
179   }
180
181   if (user_quota.enabled) {
182     op_state.set_user_quota(user_quota);
183   }
184
185   http_ret = RGWUserAdminOp_User::create(store, op_state, flusher);
186 }
187
188 class RGWOp_User_Modify : public RGWRESTOp {
189
190 public:
191   RGWOp_User_Modify() {}
192
193   int check_caps(RGWUserCaps& caps) override {
194     return caps.check_cap("users", RGW_CAP_WRITE);
195   }
196
197   void execute() override;
198
199   const string name() override { return "modify_user"; }
200 };
201
202 void RGWOp_User_Modify::execute()
203 {
204   std::string uid_str;
205   std::string display_name;
206   std::string email;
207   std::string access_key;
208   std::string secret_key;
209   std::string key_type_str;
210   std::string caps;
211
212   bool gen_key;
213   bool suspended;
214   bool system;
215
216   int32_t max_buckets;
217
218   RGWUserAdminOpState op_state;
219
220   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
221   rgw_user uid(uid_str);
222
223   RESTArgs::get_string(s, "display-name", display_name, &display_name);
224   RESTArgs::get_string(s, "email", email, &email);
225   RESTArgs::get_string(s, "access-key", access_key, &access_key);
226   RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
227   RESTArgs::get_string(s, "user-caps", caps, &caps);
228   RESTArgs::get_bool(s, "generate-key", false, &gen_key);
229   RESTArgs::get_bool(s, "suspended", false, &suspended);
230   RESTArgs::get_int32(s, "max-buckets", RGW_DEFAULT_MAX_BUCKETS, &max_buckets);
231   RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
232
233   RESTArgs::get_bool(s, "system", false, &system);
234
235   if (!s->user->system && system) {
236     ldout(s->cct, 0) << "cannot set system flag by non-system user" << dendl;
237     http_ret = -EINVAL;
238     return;
239   }
240
241   op_state.set_user_id(uid);
242   op_state.set_display_name(display_name);
243   op_state.set_user_email(email);
244   op_state.set_caps(caps);
245   op_state.set_access_key(access_key);
246   op_state.set_secret_key(secret_key);
247
248   if (max_buckets != RGW_DEFAULT_MAX_BUCKETS)
249     op_state.set_max_buckets(max_buckets);
250
251   if (gen_key)
252     op_state.set_generate_key();
253
254   if (!key_type_str.empty()) {
255     int32_t key_type = KEY_TYPE_UNDEFINED;
256     if (key_type_str.compare("swift") == 0)
257       key_type = KEY_TYPE_SWIFT;
258     else if (key_type_str.compare("s3") == 0)
259       key_type = KEY_TYPE_S3;
260
261     op_state.set_key_type(key_type);
262   }
263
264   if (s->info.args.exists("suspended"))
265     op_state.set_suspension(suspended);
266
267   if (s->info.args.exists("system"))
268     op_state.set_system(system);
269
270   http_ret = RGWUserAdminOp_User::modify(store, op_state, flusher);
271 }
272
273 class RGWOp_User_Remove : public RGWRESTOp {
274
275 public:
276   RGWOp_User_Remove() {}
277
278   int check_caps(RGWUserCaps& caps) override {
279     return caps.check_cap("users", RGW_CAP_WRITE);
280   }
281
282   void execute() override;
283
284   const string name() override { return "remove_user"; }
285 };
286
287 void RGWOp_User_Remove::execute()
288 {
289   std::string uid_str;
290   bool purge_data;
291
292   RGWUserAdminOpState op_state;
293
294   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
295   rgw_user uid(uid_str);
296
297   RESTArgs::get_bool(s, "purge-data", false, &purge_data);
298
299   // FIXME: no double checking
300   if (!uid.empty())
301     op_state.set_user_id(uid);
302
303   op_state.set_purge_data(purge_data);
304
305   http_ret = RGWUserAdminOp_User::remove(store, op_state, flusher);
306 }
307
308 class RGWOp_Subuser_Create : public RGWRESTOp {
309
310 public:
311   RGWOp_Subuser_Create() {}
312
313   int check_caps(RGWUserCaps& caps) override {
314     return caps.check_cap("users", RGW_CAP_WRITE);
315   }
316
317   void execute() override;
318
319   const string name() override { return "create_subuser"; }
320 };
321
322 void RGWOp_Subuser_Create::execute()
323 {
324   std::string uid_str;
325   std::string subuser;
326   std::string secret_key;
327   std::string access_key;
328   std::string perm_str;
329   std::string key_type_str;
330
331   bool gen_subuser = false; // FIXME placeholder
332   bool gen_secret;
333   bool gen_access;
334
335   uint32_t perm_mask = 0;
336   int32_t key_type = KEY_TYPE_SWIFT;
337
338   RGWUserAdminOpState op_state;
339
340   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
341   rgw_user uid(uid_str);
342
343   RESTArgs::get_string(s, "subuser", subuser, &subuser);
344   RESTArgs::get_string(s, "access-key", access_key, &access_key);
345   RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
346   RESTArgs::get_string(s, "access", perm_str, &perm_str);
347   RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
348   //RESTArgs::get_bool(s, "generate-subuser", false, &gen_subuser);
349   RESTArgs::get_bool(s, "generate-secret", false, &gen_secret);
350   RESTArgs::get_bool(s, "gen-access-key", false, &gen_access);
351   
352   perm_mask = rgw_str_to_perm(perm_str.c_str());
353   op_state.set_perm(perm_mask);
354
355   op_state.set_user_id(uid);
356   op_state.set_subuser(subuser);
357   op_state.set_access_key(access_key);
358   op_state.set_secret_key(secret_key);
359   op_state.set_generate_subuser(gen_subuser);
360
361   if (gen_access)
362     op_state.set_gen_access();
363
364   if (gen_secret)
365     op_state.set_gen_secret();
366
367   if (!key_type_str.empty()) {
368     if (key_type_str.compare("swift") == 0)
369       key_type = KEY_TYPE_SWIFT;
370     else if (key_type_str.compare("s3") == 0)
371       key_type = KEY_TYPE_S3;
372   }
373   op_state.set_key_type(key_type);
374
375   http_ret = RGWUserAdminOp_Subuser::create(store, op_state, flusher);
376 }
377
378 class RGWOp_Subuser_Modify : public RGWRESTOp {
379
380 public:
381   RGWOp_Subuser_Modify() {}
382
383   int check_caps(RGWUserCaps& caps) override {
384     return caps.check_cap("users", RGW_CAP_WRITE);
385   }
386
387   void execute() override;
388
389   const string name() override { return "modify_subuser"; }
390 };
391
392 void RGWOp_Subuser_Modify::execute()
393 {
394   std::string uid_str;
395   std::string subuser;
396   std::string secret_key;
397   std::string key_type_str;
398   std::string perm_str;
399
400   RGWUserAdminOpState op_state;
401
402   uint32_t perm_mask;
403   int32_t key_type = KEY_TYPE_SWIFT;
404
405   bool gen_secret;
406
407   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
408   rgw_user uid(uid_str);
409
410   RESTArgs::get_string(s, "subuser", subuser, &subuser);
411   RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
412   RESTArgs::get_string(s, "access", perm_str, &perm_str);
413   RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
414   RESTArgs::get_bool(s, "generate-secret", false, &gen_secret);
415
416   perm_mask = rgw_str_to_perm(perm_str.c_str());
417   op_state.set_perm(perm_mask);
418
419   op_state.set_user_id(uid);
420   op_state.set_subuser(subuser);
421   op_state.set_secret_key(secret_key);
422   op_state.set_gen_secret();
423
424   if (!key_type_str.empty()) {
425     if (key_type_str.compare("swift") == 0)
426       key_type = KEY_TYPE_SWIFT;
427     else if (key_type_str.compare("s3") == 0)
428       key_type = KEY_TYPE_S3;
429   }
430   op_state.set_key_type(key_type);
431
432   http_ret = RGWUserAdminOp_Subuser::modify(store, op_state, flusher);
433 }
434
435 class RGWOp_Subuser_Remove : public RGWRESTOp {
436
437 public:
438   RGWOp_Subuser_Remove() {}
439
440   int check_caps(RGWUserCaps& caps) override {
441     return caps.check_cap("users", RGW_CAP_WRITE);
442   }
443
444   void execute() override;
445
446   const string name() override { return "remove_subuser"; }
447 };
448
449 void RGWOp_Subuser_Remove::execute()
450 {
451   std::string uid_str;
452   std::string subuser;
453   bool purge_keys;
454
455   RGWUserAdminOpState op_state;
456
457   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
458   rgw_user uid(uid_str);
459
460   RESTArgs::get_string(s, "subuser", subuser, &subuser);
461   RESTArgs::get_bool(s, "purge-keys", true, &purge_keys);
462
463   op_state.set_user_id(uid);
464   op_state.set_subuser(subuser);
465
466   if (purge_keys)
467     op_state.set_purge_keys();
468
469   http_ret = RGWUserAdminOp_Subuser::remove(store, op_state, flusher);
470 }
471
472 class RGWOp_Key_Create : public RGWRESTOp {
473
474 public:
475   RGWOp_Key_Create() {}
476
477   int check_caps(RGWUserCaps& caps) override {
478     return caps.check_cap("users", RGW_CAP_WRITE);
479   }
480
481   void execute() override;
482
483   const string name() override { return "create_access_key"; }
484 };
485
486 void RGWOp_Key_Create::execute()
487 {
488   std::string uid_str;
489   std::string subuser;
490   std::string access_key;
491   std::string secret_key;
492   std::string key_type_str;
493
494   bool gen_key;
495
496   RGWUserAdminOpState op_state;
497
498   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
499   rgw_user uid(uid_str);
500
501   RESTArgs::get_string(s, "subuser", subuser, &subuser);
502   RESTArgs::get_string(s, "access-key", access_key, &access_key);
503   RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
504   RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
505   RESTArgs::get_bool(s, "generate-key", true, &gen_key);
506
507   op_state.set_user_id(uid);
508   op_state.set_subuser(subuser);
509   op_state.set_access_key(access_key);
510   op_state.set_secret_key(secret_key);
511
512   if (gen_key)
513     op_state.set_generate_key();
514
515   if (!key_type_str.empty()) {
516     int32_t key_type = KEY_TYPE_UNDEFINED;
517     if (key_type_str.compare("swift") == 0)
518       key_type = KEY_TYPE_SWIFT;
519     else if (key_type_str.compare("s3") == 0)
520       key_type = KEY_TYPE_S3;
521
522     op_state.set_key_type(key_type);
523   }
524
525   http_ret = RGWUserAdminOp_Key::create(store, op_state, flusher);
526 }
527
528 class RGWOp_Key_Remove : public RGWRESTOp {
529
530 public:
531   RGWOp_Key_Remove() {}
532
533   int check_caps(RGWUserCaps& caps) override {
534     return caps.check_cap("users", RGW_CAP_WRITE);
535   }
536
537   void execute() override;
538
539   const string name() override { return "remove_access_key"; }
540 };
541
542 void RGWOp_Key_Remove::execute()
543 {
544   std::string uid_str;
545   std::string subuser;
546   std::string access_key;
547   std::string key_type_str;
548
549   RGWUserAdminOpState op_state;
550
551   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
552   rgw_user uid(uid_str);
553
554   RESTArgs::get_string(s, "subuser", subuser, &subuser);
555   RESTArgs::get_string(s, "access-key", access_key, &access_key);
556   RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
557
558   op_state.set_user_id(uid);
559   op_state.set_subuser(subuser);
560   op_state.set_access_key(access_key);
561
562   if (!key_type_str.empty()) {
563     int32_t key_type = KEY_TYPE_UNDEFINED;
564     if (key_type_str.compare("swift") == 0)
565       key_type = KEY_TYPE_SWIFT;
566     else if (key_type_str.compare("s3") == 0)
567       key_type = KEY_TYPE_S3;
568
569     op_state.set_key_type(key_type);
570   }
571
572   http_ret = RGWUserAdminOp_Key::remove(store, op_state, flusher);
573 }
574
575 class RGWOp_Caps_Add : public RGWRESTOp {
576
577 public:
578   RGWOp_Caps_Add() {}
579
580   int check_caps(RGWUserCaps& caps) override {
581     return caps.check_cap("users", RGW_CAP_WRITE);
582   }
583
584   void execute() override;
585
586   const string name() override { return "add_user_caps"; }
587 };
588
589 void RGWOp_Caps_Add::execute()
590 {
591   std::string uid_str;
592   std::string caps;
593
594   RGWUserAdminOpState op_state;
595
596   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
597   rgw_user uid(uid_str);
598
599   RESTArgs::get_string(s, "user-caps", caps, &caps);
600
601   op_state.set_user_id(uid);
602   op_state.set_caps(caps);
603
604   http_ret = RGWUserAdminOp_Caps::add(store, op_state, flusher);
605 }
606
607 class RGWOp_Caps_Remove : public RGWRESTOp {
608
609 public:
610   RGWOp_Caps_Remove() {}
611
612   int check_caps(RGWUserCaps& caps) override {
613     return caps.check_cap("users", RGW_CAP_WRITE);
614   }
615
616   void execute() override;
617
618   const string name() override { return "remove_user_caps"; }
619 };
620
621 void RGWOp_Caps_Remove::execute()
622 {
623   std::string uid_str;
624   std::string caps;
625
626   RGWUserAdminOpState op_state;
627
628   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
629   rgw_user uid(uid_str);
630
631   RESTArgs::get_string(s, "user-caps", caps, &caps);
632
633   op_state.set_user_id(uid);
634   op_state.set_caps(caps);
635
636   http_ret = RGWUserAdminOp_Caps::remove(store, op_state, flusher);
637 }
638
639 struct UserQuotas {
640   RGWQuotaInfo bucket_quota;
641   RGWQuotaInfo user_quota;
642
643   UserQuotas() {}
644
645   explicit UserQuotas(RGWUserInfo& info) : bucket_quota(info.bucket_quota), 
646                                   user_quota(info.user_quota) {}
647
648   void dump(Formatter *f) const {
649     encode_json("bucket_quota", bucket_quota, f);
650     encode_json("user_quota", user_quota, f);
651   }
652   void decode_json(JSONObj *obj) {
653     JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
654     JSONDecoder::decode_json("user_quota", user_quota, obj);
655   }
656 };
657
658 class RGWOp_Quota_Info : public RGWRESTOp {
659
660 public:
661   RGWOp_Quota_Info() {}
662
663   int check_caps(RGWUserCaps& caps) override {
664     return caps.check_cap("users", RGW_CAP_READ);
665   }
666
667   void execute() override;
668
669   const string name() override { return "get_quota_info"; }
670 };
671
672
673 void RGWOp_Quota_Info::execute()
674 {
675   RGWUserAdminOpState op_state;
676
677   std::string uid_str;
678   std::string quota_type;
679
680   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
681   RESTArgs::get_string(s, "quota-type", quota_type, &quota_type);
682
683   if (uid_str.empty()) {
684     http_ret = -EINVAL;
685     return;
686   }
687
688   rgw_user uid(uid_str);
689
690   bool show_all = quota_type.empty();
691   bool show_bucket = show_all || (quota_type == "bucket");
692   bool show_user = show_all || (quota_type == "user");
693
694   if (!(show_all || show_bucket || show_user)) {
695     http_ret = -EINVAL;
696     return;
697   }
698
699   op_state.set_user_id(uid);
700
701   RGWUser user;
702   http_ret = user.init(store, op_state);
703   if (http_ret < 0)
704     return;
705
706   if (!op_state.has_existing_user()) {
707     http_ret = -ERR_NO_SUCH_USER;
708     return;
709   }
710
711   RGWUserInfo info;
712   string err_msg;
713   http_ret = user.info(info, &err_msg);
714   if (http_ret < 0)
715     return;
716
717   flusher.start(0);
718   if (show_all) {
719     UserQuotas quotas(info);
720     encode_json("quota", quotas, s->formatter);
721   } else if (show_user) {
722     encode_json("user_quota", info.user_quota, s->formatter);
723   } else {
724     encode_json("bucket_quota", info.bucket_quota, s->formatter);
725   }
726
727   flusher.flush();
728 }
729
730 class RGWOp_Quota_Set : public RGWRESTOp {
731
732 public:
733   RGWOp_Quota_Set() {}
734
735   int check_caps(RGWUserCaps& caps) override {
736     return caps.check_cap("users", RGW_CAP_WRITE);
737   }
738
739   void execute() override;
740
741   const string name() override { return "set_quota_info"; }
742 };
743
744 /**
745  * set quota
746  *
747  * two different ways to set the quota info: as json struct in the message body or via http params.
748  *
749  * as json:
750  *
751  * PUT /admin/user?uid=<uid>[&quota-type=<type>]
752  *
753  * whereas quota-type is optional and is either user, or bucket
754  *
755  * if quota-type is not specified then we expect to get a structure that contains both quotas,
756  * otherwise we'll only get the relevant configuration.
757  *
758  * E.g., if quota type not specified:
759  * {
760  *    "user_quota" : {
761  *      "max_size_kb" : 4096,
762  *      "max_objects" : -1,
763  *      "enabled" : false
764  *    },
765  *    "bucket_quota" : {
766  *      "max_size_kb" : 1024,
767  *      "max_objects" : -1,
768  *      "enabled" : true
769  *    }
770  * }
771  *
772  *
773  * or if quota type is specified:
774  * {
775  *   "max_size_kb" : 4096,
776  *   "max_objects" : -1,
777  *   "enabled" : false
778  * }
779  *
780  * Another option is not to pass any body and set the following http params:
781  *
782  *
783  * max-size-kb=<size>
784  * max-objects=<max objects>
785  * enabled[={true,false}]
786  *
787  * all params are optionals and default to the current settings. With this type of configuration the
788  * quota-type param is mandatory.
789  *
790  */
791
792 void RGWOp_Quota_Set::execute()
793 {
794   RGWUserAdminOpState op_state;
795
796   std::string uid_str;
797   std::string quota_type;
798
799   RESTArgs::get_string(s, "uid", uid_str, &uid_str);
800   RESTArgs::get_string(s, "quota-type", quota_type, &quota_type);
801
802   if (uid_str.empty()) {
803     http_ret = -EINVAL;
804     return;
805   }
806
807   rgw_user uid(uid_str);
808
809   bool set_all = quota_type.empty();
810   bool set_bucket = set_all || (quota_type == "bucket");
811   bool set_user = set_all || (quota_type == "user");
812
813   if (!(set_all || set_bucket || set_user)) {
814     ldout(store->ctx(), 20) << "invalid quota type" << dendl;
815     http_ret = -EINVAL;
816     return;
817   }
818
819   bool use_http_params;
820
821   if (s->content_length > 0) {
822     use_http_params = false;
823   } else {
824     const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING");
825     use_http_params = (!encoding || strcmp(encoding, "chunked") != 0);
826   }
827
828   if (use_http_params && set_all) {
829     ldout(store->ctx(), 20) << "quota type was not specified, can't set all quotas via http headers" << dendl;
830     http_ret = -EINVAL;
831     return;
832   }
833
834   op_state.set_user_id(uid);
835
836   RGWUser user;
837   http_ret = user.init(store, op_state);
838   if (http_ret < 0) {
839     ldout(store->ctx(), 20) << "failed initializing user info: " << http_ret << dendl;
840     return;
841   }
842
843   if (!op_state.has_existing_user()) {
844     http_ret = -ERR_NO_SUCH_USER;
845     return;
846   }
847
848 #define QUOTA_INPUT_MAX_LEN 1024
849   if (set_all) {
850     UserQuotas quotas;
851
852     if ((http_ret = rgw_rest_get_json_input(store->ctx(), s, quotas, QUOTA_INPUT_MAX_LEN, NULL)) < 0) {
853       ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
854       return;
855     }
856
857     op_state.set_user_quota(quotas.user_quota);
858     op_state.set_bucket_quota(quotas.bucket_quota);
859   } else {
860     RGWQuotaInfo quota;
861
862     if (!use_http_params) {
863       bool empty;
864       http_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
865       if (http_ret < 0) {
866         ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
867         if (!empty)
868           return;
869
870         /* was probably chunked input, but no content provided, configure via http params */
871         use_http_params = true;
872       }
873     }
874
875     if (use_http_params) {
876       RGWUserInfo info;
877       string err_msg;
878       http_ret = user.info(info, &err_msg);
879       if (http_ret < 0) {
880         ldout(store->ctx(), 20) << "failed to get user info: " << http_ret << dendl;
881         return;
882       }
883       RGWQuotaInfo *old_quota;
884       if (set_user) {
885         old_quota = &info.user_quota;
886       } else {
887         old_quota = &info.bucket_quota;
888       }
889
890       int64_t old_max_size_kb = rgw_rounded_kb(old_quota->max_size);
891       int64_t max_size_kb;
892       RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, &quota.max_objects);
893       RESTArgs::get_int64(s, "max-size-kb", old_max_size_kb, &max_size_kb);
894       quota.max_size = max_size_kb * 1024;
895       RESTArgs::get_bool(s, "enabled", old_quota->enabled, &quota.enabled);
896     }
897
898     if (set_user) {
899       op_state.set_user_quota(quota);
900     } else {
901       op_state.set_bucket_quota(quota);
902     }
903   }
904
905   string err;
906   http_ret = user.modify(op_state, &err);
907   if (http_ret < 0) {
908     ldout(store->ctx(), 20) << "failed updating user info: " << http_ret << ": " << err << dendl;
909     return;
910   }
911 }
912
913 RGWOp *RGWHandler_User::op_get()
914 {
915   if (s->info.args.sub_resource_exists("quota"))
916     return new RGWOp_Quota_Info;
917
918   return new RGWOp_User_Info;
919 }
920
921 RGWOp *RGWHandler_User::op_put()
922 {
923   if (s->info.args.sub_resource_exists("subuser"))
924     return new RGWOp_Subuser_Create;
925
926   if (s->info.args.sub_resource_exists("key"))
927     return new RGWOp_Key_Create;
928
929   if (s->info.args.sub_resource_exists("caps"))
930     return new RGWOp_Caps_Add;
931
932   if (s->info.args.sub_resource_exists("quota"))
933     return new RGWOp_Quota_Set;
934
935   return new RGWOp_User_Create;
936 }
937
938 RGWOp *RGWHandler_User::op_post()
939 {
940   if (s->info.args.sub_resource_exists("subuser"))
941     return new RGWOp_Subuser_Modify;
942
943   return new RGWOp_User_Modify;
944 }
945
946 RGWOp *RGWHandler_User::op_delete()
947 {
948   if (s->info.args.sub_resource_exists("subuser"))
949     return new RGWOp_Subuser_Remove;
950
951   if (s->info.args.sub_resource_exists("key"))
952     return new RGWOp_Key_Remove;
953
954   if (s->info.args.sub_resource_exists("caps"))
955     return new RGWOp_Caps_Remove;
956
957   return new RGWOp_User_Remove;
958 }
959