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