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