]>
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; | |
3efd9988 | 35 | bool sync_stats; |
7c673cae FG |
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 | ||
3efd9988 FG |
51 | RESTArgs::get_bool(s, "sync", false, &sync_stats); |
52 | ||
7c673cae FG |
53 | op_state.set_user_id(uid); |
54 | op_state.set_fetch_stats(fetch_stats); | |
3efd9988 | 55 | op_state.set_sync_stats(sync_stats); |
7c673cae FG |
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; | |
d2e6a577 | 83 | std::string tenant_name; |
7c673cae FG |
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); | |
d2e6a577 | 104 | RESTArgs::get_string(s, "tenant", tenant_name, &tenant_name); |
7c673cae FG |
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 | ||
d2e6a577 FG |
117 | if (!tenant_name.empty()) { |
118 | uid.tenant = tenant_name; | |
119 | } | |
120 | ||
7c673cae FG |
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); | |
b32b8144 FG |
421 | |
422 | if (!secret_key.empty()) | |
423 | op_state.set_secret_key(secret_key); | |
424 | ||
425 | if (gen_secret) | |
426 | op_state.set_gen_secret(); | |
7c673cae FG |
427 | |
428 | if (!key_type_str.empty()) { | |
429 | if (key_type_str.compare("swift") == 0) | |
430 | key_type = KEY_TYPE_SWIFT; | |
431 | else if (key_type_str.compare("s3") == 0) | |
432 | key_type = KEY_TYPE_S3; | |
433 | } | |
434 | op_state.set_key_type(key_type); | |
435 | ||
436 | http_ret = RGWUserAdminOp_Subuser::modify(store, op_state, flusher); | |
437 | } | |
438 | ||
439 | class RGWOp_Subuser_Remove : public RGWRESTOp { | |
440 | ||
441 | public: | |
442 | RGWOp_Subuser_Remove() {} | |
443 | ||
444 | int check_caps(RGWUserCaps& caps) override { | |
445 | return caps.check_cap("users", RGW_CAP_WRITE); | |
446 | } | |
447 | ||
448 | void execute() override; | |
449 | ||
450 | const string name() override { return "remove_subuser"; } | |
451 | }; | |
452 | ||
453 | void RGWOp_Subuser_Remove::execute() | |
454 | { | |
455 | std::string uid_str; | |
456 | std::string subuser; | |
457 | bool purge_keys; | |
458 | ||
459 | RGWUserAdminOpState op_state; | |
460 | ||
461 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
462 | rgw_user uid(uid_str); | |
463 | ||
464 | RESTArgs::get_string(s, "subuser", subuser, &subuser); | |
465 | RESTArgs::get_bool(s, "purge-keys", true, &purge_keys); | |
466 | ||
467 | op_state.set_user_id(uid); | |
468 | op_state.set_subuser(subuser); | |
469 | ||
470 | if (purge_keys) | |
471 | op_state.set_purge_keys(); | |
472 | ||
473 | http_ret = RGWUserAdminOp_Subuser::remove(store, op_state, flusher); | |
474 | } | |
475 | ||
476 | class RGWOp_Key_Create : public RGWRESTOp { | |
477 | ||
478 | public: | |
479 | RGWOp_Key_Create() {} | |
480 | ||
481 | int check_caps(RGWUserCaps& caps) override { | |
482 | return caps.check_cap("users", RGW_CAP_WRITE); | |
483 | } | |
484 | ||
485 | void execute() override; | |
486 | ||
487 | const string name() override { return "create_access_key"; } | |
488 | }; | |
489 | ||
490 | void RGWOp_Key_Create::execute() | |
491 | { | |
492 | std::string uid_str; | |
493 | std::string subuser; | |
494 | std::string access_key; | |
495 | std::string secret_key; | |
496 | std::string key_type_str; | |
497 | ||
498 | bool gen_key; | |
499 | ||
500 | RGWUserAdminOpState op_state; | |
501 | ||
502 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
503 | rgw_user uid(uid_str); | |
504 | ||
505 | RESTArgs::get_string(s, "subuser", subuser, &subuser); | |
506 | RESTArgs::get_string(s, "access-key", access_key, &access_key); | |
507 | RESTArgs::get_string(s, "secret-key", secret_key, &secret_key); | |
508 | RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str); | |
509 | RESTArgs::get_bool(s, "generate-key", true, &gen_key); | |
510 | ||
511 | op_state.set_user_id(uid); | |
512 | op_state.set_subuser(subuser); | |
513 | op_state.set_access_key(access_key); | |
514 | op_state.set_secret_key(secret_key); | |
515 | ||
516 | if (gen_key) | |
517 | op_state.set_generate_key(); | |
518 | ||
519 | if (!key_type_str.empty()) { | |
520 | int32_t key_type = KEY_TYPE_UNDEFINED; | |
521 | if (key_type_str.compare("swift") == 0) | |
522 | key_type = KEY_TYPE_SWIFT; | |
523 | else if (key_type_str.compare("s3") == 0) | |
524 | key_type = KEY_TYPE_S3; | |
525 | ||
526 | op_state.set_key_type(key_type); | |
527 | } | |
528 | ||
529 | http_ret = RGWUserAdminOp_Key::create(store, op_state, flusher); | |
530 | } | |
531 | ||
532 | class RGWOp_Key_Remove : public RGWRESTOp { | |
533 | ||
534 | public: | |
535 | RGWOp_Key_Remove() {} | |
536 | ||
537 | int check_caps(RGWUserCaps& caps) override { | |
538 | return caps.check_cap("users", RGW_CAP_WRITE); | |
539 | } | |
540 | ||
541 | void execute() override; | |
542 | ||
543 | const string name() override { return "remove_access_key"; } | |
544 | }; | |
545 | ||
546 | void RGWOp_Key_Remove::execute() | |
547 | { | |
548 | std::string uid_str; | |
549 | std::string subuser; | |
550 | std::string access_key; | |
551 | std::string key_type_str; | |
552 | ||
553 | RGWUserAdminOpState op_state; | |
554 | ||
555 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
556 | rgw_user uid(uid_str); | |
557 | ||
558 | RESTArgs::get_string(s, "subuser", subuser, &subuser); | |
559 | RESTArgs::get_string(s, "access-key", access_key, &access_key); | |
560 | RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str); | |
561 | ||
562 | op_state.set_user_id(uid); | |
563 | op_state.set_subuser(subuser); | |
564 | op_state.set_access_key(access_key); | |
565 | ||
566 | if (!key_type_str.empty()) { | |
567 | int32_t key_type = KEY_TYPE_UNDEFINED; | |
568 | if (key_type_str.compare("swift") == 0) | |
569 | key_type = KEY_TYPE_SWIFT; | |
570 | else if (key_type_str.compare("s3") == 0) | |
571 | key_type = KEY_TYPE_S3; | |
572 | ||
573 | op_state.set_key_type(key_type); | |
574 | } | |
575 | ||
576 | http_ret = RGWUserAdminOp_Key::remove(store, op_state, flusher); | |
577 | } | |
578 | ||
579 | class RGWOp_Caps_Add : public RGWRESTOp { | |
580 | ||
581 | public: | |
582 | RGWOp_Caps_Add() {} | |
583 | ||
584 | int check_caps(RGWUserCaps& caps) override { | |
585 | return caps.check_cap("users", RGW_CAP_WRITE); | |
586 | } | |
587 | ||
588 | void execute() override; | |
589 | ||
590 | const string name() override { return "add_user_caps"; } | |
591 | }; | |
592 | ||
593 | void RGWOp_Caps_Add::execute() | |
594 | { | |
595 | std::string uid_str; | |
596 | std::string caps; | |
597 | ||
598 | RGWUserAdminOpState op_state; | |
599 | ||
600 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
601 | rgw_user uid(uid_str); | |
602 | ||
603 | RESTArgs::get_string(s, "user-caps", caps, &caps); | |
604 | ||
605 | op_state.set_user_id(uid); | |
606 | op_state.set_caps(caps); | |
607 | ||
608 | http_ret = RGWUserAdminOp_Caps::add(store, op_state, flusher); | |
609 | } | |
610 | ||
611 | class RGWOp_Caps_Remove : public RGWRESTOp { | |
612 | ||
613 | public: | |
614 | RGWOp_Caps_Remove() {} | |
615 | ||
616 | int check_caps(RGWUserCaps& caps) override { | |
617 | return caps.check_cap("users", RGW_CAP_WRITE); | |
618 | } | |
619 | ||
620 | void execute() override; | |
621 | ||
622 | const string name() override { return "remove_user_caps"; } | |
623 | }; | |
624 | ||
625 | void RGWOp_Caps_Remove::execute() | |
626 | { | |
627 | std::string uid_str; | |
628 | std::string caps; | |
629 | ||
630 | RGWUserAdminOpState op_state; | |
631 | ||
632 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
633 | rgw_user uid(uid_str); | |
634 | ||
635 | RESTArgs::get_string(s, "user-caps", caps, &caps); | |
636 | ||
637 | op_state.set_user_id(uid); | |
638 | op_state.set_caps(caps); | |
639 | ||
640 | http_ret = RGWUserAdminOp_Caps::remove(store, op_state, flusher); | |
641 | } | |
642 | ||
643 | struct UserQuotas { | |
644 | RGWQuotaInfo bucket_quota; | |
645 | RGWQuotaInfo user_quota; | |
646 | ||
647 | UserQuotas() {} | |
648 | ||
649 | explicit UserQuotas(RGWUserInfo& info) : bucket_quota(info.bucket_quota), | |
650 | user_quota(info.user_quota) {} | |
651 | ||
652 | void dump(Formatter *f) const { | |
653 | encode_json("bucket_quota", bucket_quota, f); | |
654 | encode_json("user_quota", user_quota, f); | |
655 | } | |
656 | void decode_json(JSONObj *obj) { | |
657 | JSONDecoder::decode_json("bucket_quota", bucket_quota, obj); | |
658 | JSONDecoder::decode_json("user_quota", user_quota, obj); | |
659 | } | |
660 | }; | |
661 | ||
662 | class RGWOp_Quota_Info : public RGWRESTOp { | |
663 | ||
664 | public: | |
665 | RGWOp_Quota_Info() {} | |
666 | ||
667 | int check_caps(RGWUserCaps& caps) override { | |
668 | return caps.check_cap("users", RGW_CAP_READ); | |
669 | } | |
670 | ||
671 | void execute() override; | |
672 | ||
673 | const string name() override { return "get_quota_info"; } | |
674 | }; | |
675 | ||
676 | ||
677 | void RGWOp_Quota_Info::execute() | |
678 | { | |
679 | RGWUserAdminOpState op_state; | |
680 | ||
681 | std::string uid_str; | |
682 | std::string quota_type; | |
683 | ||
684 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
685 | RESTArgs::get_string(s, "quota-type", quota_type, "a_type); | |
686 | ||
687 | if (uid_str.empty()) { | |
688 | http_ret = -EINVAL; | |
689 | return; | |
690 | } | |
691 | ||
692 | rgw_user uid(uid_str); | |
693 | ||
694 | bool show_all = quota_type.empty(); | |
695 | bool show_bucket = show_all || (quota_type == "bucket"); | |
696 | bool show_user = show_all || (quota_type == "user"); | |
697 | ||
698 | if (!(show_all || show_bucket || show_user)) { | |
699 | http_ret = -EINVAL; | |
700 | return; | |
701 | } | |
702 | ||
703 | op_state.set_user_id(uid); | |
704 | ||
705 | RGWUser user; | |
706 | http_ret = user.init(store, op_state); | |
707 | if (http_ret < 0) | |
708 | return; | |
709 | ||
224ce89b WB |
710 | if (!op_state.has_existing_user()) { |
711 | http_ret = -ERR_NO_SUCH_USER; | |
712 | return; | |
713 | } | |
714 | ||
7c673cae FG |
715 | RGWUserInfo info; |
716 | string err_msg; | |
717 | http_ret = user.info(info, &err_msg); | |
718 | if (http_ret < 0) | |
719 | return; | |
720 | ||
721 | flusher.start(0); | |
722 | if (show_all) { | |
723 | UserQuotas quotas(info); | |
724 | encode_json("quota", quotas, s->formatter); | |
725 | } else if (show_user) { | |
726 | encode_json("user_quota", info.user_quota, s->formatter); | |
727 | } else { | |
728 | encode_json("bucket_quota", info.bucket_quota, s->formatter); | |
729 | } | |
730 | ||
731 | flusher.flush(); | |
732 | } | |
733 | ||
734 | class RGWOp_Quota_Set : public RGWRESTOp { | |
735 | ||
736 | public: | |
737 | RGWOp_Quota_Set() {} | |
738 | ||
739 | int check_caps(RGWUserCaps& caps) override { | |
740 | return caps.check_cap("users", RGW_CAP_WRITE); | |
741 | } | |
742 | ||
743 | void execute() override; | |
744 | ||
745 | const string name() override { return "set_quota_info"; } | |
746 | }; | |
747 | ||
748 | /** | |
749 | * set quota | |
750 | * | |
751 | * two different ways to set the quota info: as json struct in the message body or via http params. | |
752 | * | |
753 | * as json: | |
754 | * | |
755 | * PUT /admin/user?uid=<uid>["a-type=<type>] | |
756 | * | |
757 | * whereas quota-type is optional and is either user, or bucket | |
758 | * | |
759 | * if quota-type is not specified then we expect to get a structure that contains both quotas, | |
760 | * otherwise we'll only get the relevant configuration. | |
761 | * | |
762 | * E.g., if quota type not specified: | |
763 | * { | |
764 | * "user_quota" : { | |
765 | * "max_size_kb" : 4096, | |
766 | * "max_objects" : -1, | |
767 | * "enabled" : false | |
768 | * }, | |
769 | * "bucket_quota" : { | |
770 | * "max_size_kb" : 1024, | |
771 | * "max_objects" : -1, | |
772 | * "enabled" : true | |
773 | * } | |
774 | * } | |
775 | * | |
776 | * | |
777 | * or if quota type is specified: | |
778 | * { | |
779 | * "max_size_kb" : 4096, | |
780 | * "max_objects" : -1, | |
781 | * "enabled" : false | |
782 | * } | |
783 | * | |
784 | * Another option is not to pass any body and set the following http params: | |
785 | * | |
786 | * | |
787 | * max-size-kb=<size> | |
788 | * max-objects=<max objects> | |
789 | * enabled[={true,false}] | |
790 | * | |
791 | * all params are optionals and default to the current settings. With this type of configuration the | |
792 | * quota-type param is mandatory. | |
793 | * | |
794 | */ | |
795 | ||
796 | void RGWOp_Quota_Set::execute() | |
797 | { | |
798 | RGWUserAdminOpState op_state; | |
799 | ||
800 | std::string uid_str; | |
801 | std::string quota_type; | |
802 | ||
803 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
804 | RESTArgs::get_string(s, "quota-type", quota_type, "a_type); | |
805 | ||
806 | if (uid_str.empty()) { | |
807 | http_ret = -EINVAL; | |
808 | return; | |
809 | } | |
810 | ||
811 | rgw_user uid(uid_str); | |
812 | ||
813 | bool set_all = quota_type.empty(); | |
814 | bool set_bucket = set_all || (quota_type == "bucket"); | |
815 | bool set_user = set_all || (quota_type == "user"); | |
816 | ||
817 | if (!(set_all || set_bucket || set_user)) { | |
818 | ldout(store->ctx(), 20) << "invalid quota type" << dendl; | |
819 | http_ret = -EINVAL; | |
820 | return; | |
821 | } | |
822 | ||
823 | bool use_http_params; | |
824 | ||
825 | if (s->content_length > 0) { | |
826 | use_http_params = false; | |
827 | } else { | |
828 | const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING"); | |
829 | use_http_params = (!encoding || strcmp(encoding, "chunked") != 0); | |
830 | } | |
831 | ||
832 | if (use_http_params && set_all) { | |
833 | ldout(store->ctx(), 20) << "quota type was not specified, can't set all quotas via http headers" << dendl; | |
834 | http_ret = -EINVAL; | |
835 | return; | |
836 | } | |
837 | ||
838 | op_state.set_user_id(uid); | |
839 | ||
840 | RGWUser user; | |
841 | http_ret = user.init(store, op_state); | |
842 | if (http_ret < 0) { | |
843 | ldout(store->ctx(), 20) << "failed initializing user info: " << http_ret << dendl; | |
844 | return; | |
845 | } | |
846 | ||
224ce89b WB |
847 | if (!op_state.has_existing_user()) { |
848 | http_ret = -ERR_NO_SUCH_USER; | |
849 | return; | |
850 | } | |
851 | ||
7c673cae FG |
852 | #define QUOTA_INPUT_MAX_LEN 1024 |
853 | if (set_all) { | |
854 | UserQuotas quotas; | |
855 | ||
856 | if ((http_ret = rgw_rest_get_json_input(store->ctx(), s, quotas, QUOTA_INPUT_MAX_LEN, NULL)) < 0) { | |
857 | ldout(store->ctx(), 20) << "failed to retrieve input" << dendl; | |
858 | return; | |
859 | } | |
860 | ||
861 | op_state.set_user_quota(quotas.user_quota); | |
862 | op_state.set_bucket_quota(quotas.bucket_quota); | |
863 | } else { | |
864 | RGWQuotaInfo quota; | |
865 | ||
866 | if (!use_http_params) { | |
867 | bool empty; | |
868 | http_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty); | |
869 | if (http_ret < 0) { | |
870 | ldout(store->ctx(), 20) << "failed to retrieve input" << dendl; | |
871 | if (!empty) | |
872 | return; | |
873 | ||
874 | /* was probably chunked input, but no content provided, configure via http params */ | |
875 | use_http_params = true; | |
876 | } | |
877 | } | |
878 | ||
879 | if (use_http_params) { | |
880 | RGWUserInfo info; | |
881 | string err_msg; | |
882 | http_ret = user.info(info, &err_msg); | |
883 | if (http_ret < 0) { | |
884 | ldout(store->ctx(), 20) << "failed to get user info: " << http_ret << dendl; | |
885 | return; | |
886 | } | |
887 | RGWQuotaInfo *old_quota; | |
888 | if (set_user) { | |
889 | old_quota = &info.user_quota; | |
890 | } else { | |
891 | old_quota = &info.bucket_quota; | |
892 | } | |
893 | ||
894 | int64_t old_max_size_kb = rgw_rounded_kb(old_quota->max_size); | |
895 | int64_t max_size_kb; | |
896 | RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, "a.max_objects); | |
897 | RESTArgs::get_int64(s, "max-size-kb", old_max_size_kb, &max_size_kb); | |
898 | quota.max_size = max_size_kb * 1024; | |
899 | RESTArgs::get_bool(s, "enabled", old_quota->enabled, "a.enabled); | |
900 | } | |
901 | ||
902 | if (set_user) { | |
903 | op_state.set_user_quota(quota); | |
904 | } else { | |
905 | op_state.set_bucket_quota(quota); | |
906 | } | |
907 | } | |
908 | ||
909 | string err; | |
910 | http_ret = user.modify(op_state, &err); | |
911 | if (http_ret < 0) { | |
912 | ldout(store->ctx(), 20) << "failed updating user info: " << http_ret << ": " << err << dendl; | |
913 | return; | |
914 | } | |
915 | } | |
916 | ||
917 | RGWOp *RGWHandler_User::op_get() | |
918 | { | |
919 | if (s->info.args.sub_resource_exists("quota")) | |
920 | return new RGWOp_Quota_Info; | |
921 | ||
922 | return new RGWOp_User_Info; | |
923 | } | |
924 | ||
925 | RGWOp *RGWHandler_User::op_put() | |
926 | { | |
927 | if (s->info.args.sub_resource_exists("subuser")) | |
928 | return new RGWOp_Subuser_Create; | |
929 | ||
930 | if (s->info.args.sub_resource_exists("key")) | |
931 | return new RGWOp_Key_Create; | |
932 | ||
933 | if (s->info.args.sub_resource_exists("caps")) | |
934 | return new RGWOp_Caps_Add; | |
935 | ||
936 | if (s->info.args.sub_resource_exists("quota")) | |
937 | return new RGWOp_Quota_Set; | |
938 | ||
939 | return new RGWOp_User_Create; | |
940 | } | |
941 | ||
942 | RGWOp *RGWHandler_User::op_post() | |
943 | { | |
944 | if (s->info.args.sub_resource_exists("subuser")) | |
945 | return new RGWOp_Subuser_Modify; | |
946 | ||
947 | return new RGWOp_User_Modify; | |
948 | } | |
949 | ||
950 | RGWOp *RGWHandler_User::op_delete() | |
951 | { | |
952 | if (s->info.args.sub_resource_exists("subuser")) | |
953 | return new RGWOp_Subuser_Remove; | |
954 | ||
955 | if (s->info.args.sub_resource_exists("key")) | |
956 | return new RGWOp_Key_Remove; | |
957 | ||
958 | if (s->info.args.sub_resource_exists("caps")) | |
959 | return new RGWOp_Caps_Remove; | |
960 | ||
961 | return new RGWOp_User_Remove; | |
962 | } | |
963 |