Revision 93127325 snf-pithos-app/pithos/api/functions.py
b/snf-pithos-app/pithos/api/functions.py | ||
---|---|---|
164 | 164 |
if not limit: |
165 | 165 |
limit = 10000 |
166 | 166 |
|
167 |
accounts = request.backend.list_accounts(request.user_uniq, marker, limit)
|
|
167 |
accounts = request.backend.list_accounts(request.userid, marker, limit)
|
|
168 | 168 |
|
169 | 169 |
if request.serialization == 'text': |
170 | 170 |
if len(accounts) == 0: |
... | ... | |
177 | 177 |
|
178 | 178 |
account_meta = [] |
179 | 179 |
for x in accounts: |
180 |
if x == request.user_uniq:
|
|
180 |
if x == request.userid:
|
|
181 | 181 |
continue |
182 | 182 |
try: |
183 |
meta = request.backend.get_account_meta(request.user_uniq, x, 'pithos', include_user_defined=False)
|
|
184 |
groups = request.backend.get_account_groups(request.user_uniq, x)
|
|
183 |
meta = request.backend.get_account_meta(request.userid, x, 'pithos', include_user_defined=False)
|
|
184 |
groups = request.backend.get_account_groups(request.userid, x)
|
|
185 | 185 |
except NotAllowedError: |
186 | 186 |
raise Forbidden('Not allowed') |
187 | 187 |
else: |
... | ... | |
207 | 207 |
|
208 | 208 |
until = get_int_parameter(request.GET.get('until')) |
209 | 209 |
try: |
210 |
meta = request.backend.get_account_meta(request.user_uniq, v_account, 'pithos', until)
|
|
211 |
groups = request.backend.get_account_groups(request.user_uniq, v_account)
|
|
212 |
policy = request.backend.get_account_policy(request.user_uniq, v_account)
|
|
210 |
meta = request.backend.get_account_meta(request.userid, v_account, 'pithos', until)
|
|
211 |
groups = request.backend.get_account_groups(request.userid, v_account)
|
|
212 |
policy = request.backend.get_account_policy(request.userid, v_account)
|
|
213 | 213 |
except NotAllowedError: |
214 | 214 |
raise Forbidden('Not allowed') |
215 | 215 |
|
... | ... | |
232 | 232 |
replace = False |
233 | 233 |
if groups: |
234 | 234 |
try: |
235 |
request.backend.update_account_groups(request.user_uniq, v_account,
|
|
235 |
request.backend.update_account_groups(request.userid, v_account,
|
|
236 | 236 |
groups, replace) |
237 | 237 |
except NotAllowedError: |
238 | 238 |
raise Forbidden('Not allowed') |
... | ... | |
240 | 240 |
raise BadRequest('Invalid groups header') |
241 | 241 |
if meta or replace: |
242 | 242 |
try: |
243 |
request.backend.update_account_meta(request.user_uniq, v_account,
|
|
243 |
request.backend.update_account_meta(request.userid, v_account,
|
|
244 | 244 |
'pithos', meta, replace) |
245 | 245 |
except NotAllowedError: |
246 | 246 |
raise Forbidden('Not allowed') |
... | ... | |
256 | 256 |
|
257 | 257 |
until = get_int_parameter(request.GET.get('until')) |
258 | 258 |
try: |
259 |
meta = request.backend.get_account_meta(request.user_uniq, v_account, 'pithos', until)
|
|
260 |
groups = request.backend.get_account_groups(request.user_uniq, v_account)
|
|
261 |
policy = request.backend.get_account_policy(request.user_uniq, v_account)
|
|
259 |
meta = request.backend.get_account_meta(request.userid, v_account, 'pithos', until)
|
|
260 |
groups = request.backend.get_account_groups(request.userid, v_account)
|
|
261 |
policy = request.backend.get_account_policy(request.userid, v_account)
|
|
262 | 262 |
except NotAllowedError: |
263 | 263 |
raise Forbidden('Not allowed') |
264 | 264 |
|
... | ... | |
277 | 277 |
shared = True |
278 | 278 |
|
279 | 279 |
try: |
280 |
containers = request.backend.list_containers(request.user_uniq, v_account,
|
|
280 |
containers = request.backend.list_containers(request.userid, v_account,
|
|
281 | 281 |
marker, limit, shared, until) |
282 | 282 |
except NotAllowedError: |
283 | 283 |
raise Forbidden('Not allowed') |
... | ... | |
296 | 296 |
container_meta = [] |
297 | 297 |
for x in containers: |
298 | 298 |
try: |
299 |
meta = request.backend.get_container_meta(request.user_uniq, v_account,
|
|
299 |
meta = request.backend.get_container_meta(request.userid, v_account,
|
|
300 | 300 |
x, 'pithos', until, include_user_defined=False) |
301 |
policy = request.backend.get_container_policy(request.user_uniq,
|
|
301 |
policy = request.backend.get_container_policy(request.userid,
|
|
302 | 302 |
v_account, x) |
303 | 303 |
except NotAllowedError: |
304 | 304 |
raise Forbidden('Not allowed') |
... | ... | |
328 | 328 |
|
329 | 329 |
until = get_int_parameter(request.GET.get('until')) |
330 | 330 |
try: |
331 |
meta = request.backend.get_container_meta(request.user_uniq, v_account,
|
|
331 |
meta = request.backend.get_container_meta(request.userid, v_account,
|
|
332 | 332 |
v_container, 'pithos', until) |
333 |
meta['object_meta'] = request.backend.list_container_meta(request.user_uniq,
|
|
333 |
meta['object_meta'] = request.backend.list_container_meta(request.userid,
|
|
334 | 334 |
v_account, v_container, 'pithos', until) |
335 |
policy = request.backend.get_container_policy(request.user_uniq, v_account,
|
|
335 |
policy = request.backend.get_container_policy(request.userid, v_account,
|
|
336 | 336 |
v_container) |
337 | 337 |
except NotAllowedError: |
338 | 338 |
raise Forbidden('Not allowed') |
... | ... | |
356 | 356 |
meta, policy = get_container_headers(request) |
357 | 357 |
|
358 | 358 |
try: |
359 |
request.backend.put_container(request.user_uniq, v_account, v_container, policy)
|
|
359 |
request.backend.put_container(request.userid, v_account, v_container, policy)
|
|
360 | 360 |
ret = 201 |
361 | 361 |
except NotAllowedError: |
362 | 362 |
raise Forbidden('Not allowed') |
... | ... | |
367 | 367 |
|
368 | 368 |
if ret == 202 and policy: |
369 | 369 |
try: |
370 |
request.backend.update_container_policy(request.user_uniq, v_account,
|
|
370 |
request.backend.update_container_policy(request.userid, v_account,
|
|
371 | 371 |
v_container, policy, replace=False) |
372 | 372 |
except NotAllowedError: |
373 | 373 |
raise Forbidden('Not allowed') |
... | ... | |
377 | 377 |
raise BadRequest('Invalid policy header') |
378 | 378 |
if meta: |
379 | 379 |
try: |
380 |
request.backend.update_container_meta(request.user_uniq, v_account,
|
|
380 |
request.backend.update_container_meta(request.userid, v_account,
|
|
381 | 381 |
v_container, 'pithos', meta, replace=False) |
382 | 382 |
except NotAllowedError: |
383 | 383 |
raise Forbidden('Not allowed') |
... | ... | |
400 | 400 |
replace = False |
401 | 401 |
if policy: |
402 | 402 |
try: |
403 |
request.backend.update_container_policy(request.user_uniq, v_account,
|
|
403 |
request.backend.update_container_policy(request.userid, v_account,
|
|
404 | 404 |
v_container, policy, replace) |
405 | 405 |
except NotAllowedError: |
406 | 406 |
raise Forbidden('Not allowed') |
... | ... | |
410 | 410 |
raise BadRequest('Invalid policy header') |
411 | 411 |
if meta or replace: |
412 | 412 |
try: |
413 |
request.backend.update_container_meta(request.user_uniq, v_account,
|
|
413 |
request.backend.update_container_meta(request.userid, v_account,
|
|
414 | 414 |
v_container, 'pithos', meta, replace) |
415 | 415 |
except NotAllowedError: |
416 | 416 |
raise Forbidden('Not allowed') |
... | ... | |
445 | 445 |
|
446 | 446 |
until = get_int_parameter(request.GET.get('until')) |
447 | 447 |
try: |
448 |
request.backend.delete_container(request.user_uniq, v_account, v_container,
|
|
448 |
request.backend.delete_container(request.userid, v_account, v_container,
|
|
449 | 449 |
until) |
450 | 450 |
except NotAllowedError: |
451 | 451 |
raise Forbidden('Not allowed') |
... | ... | |
465 | 465 |
|
466 | 466 |
until = get_int_parameter(request.GET.get('until')) |
467 | 467 |
try: |
468 |
meta = request.backend.get_container_meta(request.user_uniq, v_account,
|
|
468 |
meta = request.backend.get_container_meta(request.userid, v_account,
|
|
469 | 469 |
v_container, 'pithos', until) |
470 |
meta['object_meta'] = request.backend.list_container_meta(request.user_uniq,
|
|
470 |
meta['object_meta'] = request.backend.list_container_meta(request.userid,
|
|
471 | 471 |
v_account, v_container, 'pithos', until) |
472 |
policy = request.backend.get_container_policy(request.user_uniq, v_account,
|
|
472 |
policy = request.backend.get_container_policy(request.userid, v_account,
|
|
473 | 473 |
v_container) |
474 | 474 |
except NotAllowedError: |
475 | 475 |
raise Forbidden('Not allowed') |
... | ... | |
521 | 521 |
|
522 | 522 |
if request.serialization == 'text': |
523 | 523 |
try: |
524 |
objects = request.backend.list_objects(request.user_uniq, v_account,
|
|
524 |
objects = request.backend.list_objects(request.userid, v_account,
|
|
525 | 525 |
v_container, prefix, delimiter, marker, |
526 | 526 |
limit, virtual, 'pithos', keys, shared, until) |
527 | 527 |
except NotAllowedError: |
... | ... | |
538 | 538 |
return response |
539 | 539 |
|
540 | 540 |
try: |
541 |
objects = request.backend.list_object_meta(request.user_uniq, v_account,
|
|
541 |
objects = request.backend.list_object_meta(request.userid, v_account,
|
|
542 | 542 |
v_container, prefix, delimiter, marker, |
543 | 543 |
limit, virtual, 'pithos', keys, shared, until) |
544 | 544 |
object_permissions = {} |
545 | 545 |
object_public = {} |
546 | 546 |
if until is None: |
547 | 547 |
name_idx = len('/'.join((v_account, v_container, ''))) |
548 |
for x in request.backend.list_object_permissions(request.user_uniq,
|
|
548 |
for x in request.backend.list_object_permissions(request.userid,
|
|
549 | 549 |
v_account, v_container, prefix): |
550 | 550 |
object = x[name_idx:] |
551 | 551 |
object_permissions[object] = request.backend.get_object_permissions( |
552 |
request.user_uniq, v_account, v_container, object)
|
|
553 |
for k, v in request.backend.list_object_public(request.user_uniq,
|
|
552 |
request.userid, v_account, v_container, object)
|
|
553 |
for k, v in request.backend.list_object_public(request.userid,
|
|
554 | 554 |
v_account, v_container, prefix).iteritems(): |
555 | 555 |
object_public[k[name_idx:]] = v |
556 | 556 |
except NotAllowedError: |
... | ... | |
600 | 600 |
|
601 | 601 |
version = request.GET.get('version') |
602 | 602 |
try: |
603 |
meta = request.backend.get_object_meta(request.user_uniq, v_account,
|
|
603 |
meta = request.backend.get_object_meta(request.userid, v_account,
|
|
604 | 604 |
v_container, v_object, 'pithos', version) |
605 | 605 |
if version is None: |
606 |
permissions = request.backend.get_object_permissions(request.user_uniq,
|
|
606 |
permissions = request.backend.get_object_permissions(request.userid,
|
|
607 | 607 |
v_account, v_container, v_object) |
608 |
public = request.backend.get_object_public(request.user_uniq, v_account,
|
|
608 |
public = request.backend.get_object_public(request.userid, v_account,
|
|
609 | 609 |
v_container, v_object) |
610 | 610 |
else: |
611 | 611 |
permissions = None |
... | ... | |
653 | 653 |
raise BadRequest('No format specified for version list.') |
654 | 654 |
|
655 | 655 |
try: |
656 |
v = request.backend.list_versions(request.user_uniq, v_account,
|
|
656 |
v = request.backend.list_versions(request.userid, v_account,
|
|
657 | 657 |
v_container, v_object) |
658 | 658 |
except NotAllowedError: |
659 | 659 |
raise Forbidden('Not allowed') |
... | ... | |
669 | 669 |
return response |
670 | 670 |
|
671 | 671 |
try: |
672 |
meta = request.backend.get_object_meta(request.user_uniq, v_account,
|
|
672 |
meta = request.backend.get_object_meta(request.userid, v_account,
|
|
673 | 673 |
v_container, v_object, 'pithos', version) |
674 | 674 |
if version is None: |
675 |
permissions = request.backend.get_object_permissions(request.user_uniq,
|
|
675 |
permissions = request.backend.get_object_permissions(request.userid,
|
|
676 | 676 |
v_account, v_container, v_object) |
677 |
public = request.backend.get_object_public(request.user_uniq, v_account,
|
|
677 |
public = request.backend.get_object_public(request.userid, v_account,
|
|
678 | 678 |
v_container, v_object) |
679 | 679 |
else: |
680 | 680 |
permissions = None |
... | ... | |
708 | 708 |
if 'X-Object-Manifest' in meta and not hashmap_reply: |
709 | 709 |
try: |
710 | 710 |
src_container, src_name = split_container_object_string('/' + meta['X-Object-Manifest']) |
711 |
objects = request.backend.list_objects(request.user_uniq, v_account,
|
|
711 |
objects = request.backend.list_objects(request.userid, v_account,
|
|
712 | 712 |
src_container, prefix=src_name, virtual=False) |
713 | 713 |
except NotAllowedError: |
714 | 714 |
raise Forbidden('Not allowed') |
... | ... | |
719 | 719 |
|
720 | 720 |
try: |
721 | 721 |
for x in objects: |
722 |
s, h = request.backend.get_object_hashmap(request.user_uniq,
|
|
722 |
s, h = request.backend.get_object_hashmap(request.userid,
|
|
723 | 723 |
v_account, src_container, x[0], x[1]) |
724 | 724 |
sizes.append(s) |
725 | 725 |
hashmaps.append(h) |
... | ... | |
731 | 731 |
raise ItemNotFound('Version does not exist') |
732 | 732 |
else: |
733 | 733 |
try: |
734 |
s, h = request.backend.get_object_hashmap(request.user_uniq, v_account,
|
|
734 |
s, h = request.backend.get_object_hashmap(request.userid, v_account,
|
|
735 | 735 |
v_container, v_object, version) |
736 | 736 |
sizes.append(s) |
737 | 737 |
hashmaps.append(h) |
... | ... | |
779 | 779 |
# Evaluate conditions. |
780 | 780 |
if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'): |
781 | 781 |
try: |
782 |
meta = request.backend.get_object_meta(request.user_uniq, v_account,
|
|
782 |
meta = request.backend.get_object_meta(request.userid, v_account,
|
|
783 | 783 |
v_container, v_object, 'pithos') |
784 | 784 |
except NotAllowedError: |
785 | 785 |
raise Forbidden('Not allowed') |
... | ... | |
794 | 794 |
|
795 | 795 |
src_account = request.META.get('HTTP_X_SOURCE_ACCOUNT') |
796 | 796 |
if not src_account: |
797 |
src_account = request.user_uniq
|
|
797 |
src_account = request.userid
|
|
798 | 798 |
if move_from: |
799 | 799 |
try: |
800 | 800 |
src_container, src_name = split_container_object_string(move_from) |
... | ... | |
871 | 871 |
raise UnprocessableEntity('Object ETag does not match') |
872 | 872 |
|
873 | 873 |
try: |
874 |
version_id = request.backend.update_object_hashmap(request.user_uniq,
|
|
874 |
version_id = request.backend.update_object_hashmap(request.userid,
|
|
875 | 875 |
v_account, v_container, v_object, size, content_type, |
876 | 876 |
hashmap, checksum, 'pithos', meta, True, permissions) |
877 | 877 |
except NotAllowedError: |
... | ... | |
888 | 888 |
# Update the MD5 after the hashmap, as there may be missing hashes. |
889 | 889 |
checksum = hashmap_md5(request, hashmap, size) |
890 | 890 |
try: |
891 |
version_id = request.backend.update_object_checksum(request.user_uniq,
|
|
891 |
version_id = request.backend.update_object_checksum(request.userid,
|
|
892 | 892 |
v_account, v_container, v_object, version_id, checksum) |
893 | 893 |
except NotAllowedError: |
894 | 894 |
raise Forbidden('Not allowed') |
895 | 895 |
if public is not None: |
896 | 896 |
try: |
897 |
request.backend.update_object_public(request.user_uniq, v_account,
|
|
897 |
request.backend.update_object_public(request.userid, v_account,
|
|
898 | 898 |
v_container, v_object, public) |
899 | 899 |
except NotAllowedError: |
900 | 900 |
raise Forbidden('Not allowed') |
... | ... | |
922 | 922 |
|
923 | 923 |
checksum = file.etag |
924 | 924 |
try: |
925 |
version_id = request.backend.update_object_hashmap(request.user_uniq,
|
|
925 |
version_id = request.backend.update_object_hashmap(request.userid,
|
|
926 | 926 |
v_account, v_container, v_object, file.size, file.content_type, |
927 | 927 |
file.hashmap, checksum, 'pithos', {}, True) |
928 | 928 |
except NotAllowedError: |
... | ... | |
948 | 948 |
|
949 | 949 |
dest_account = request.META.get('HTTP_DESTINATION_ACCOUNT') |
950 | 950 |
if not dest_account: |
951 |
dest_account = request.user_uniq
|
|
951 |
dest_account = request.userid
|
|
952 | 952 |
dest_path = request.META.get('HTTP_DESTINATION') |
953 | 953 |
if not dest_path: |
954 | 954 |
raise BadRequest('Missing Destination header') |
... | ... | |
961 | 961 |
if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'): |
962 | 962 |
src_version = request.META.get('HTTP_X_SOURCE_VERSION') |
963 | 963 |
try: |
964 |
meta = request.backend.get_object_meta(request.user_uniq, v_account,
|
|
964 |
meta = request.backend.get_object_meta(request.userid, v_account,
|
|
965 | 965 |
v_container, v_object, 'pithos', src_version) |
966 | 966 |
except NotAllowedError: |
967 | 967 |
raise Forbidden('Not allowed') |
... | ... | |
985 | 985 |
|
986 | 986 |
dest_account = request.META.get('HTTP_DESTINATION_ACCOUNT') |
987 | 987 |
if not dest_account: |
988 |
dest_account = request.user_uniq
|
|
988 |
dest_account = request.userid
|
|
989 | 989 |
dest_path = request.META.get('HTTP_DESTINATION') |
990 | 990 |
if not dest_path: |
991 | 991 |
raise BadRequest('Missing Destination header') |
... | ... | |
997 | 997 |
# Evaluate conditions. |
998 | 998 |
if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'): |
999 | 999 |
try: |
1000 |
meta = request.backend.get_object_meta(request.user_uniq, v_account,
|
|
1000 |
meta = request.backend.get_object_meta(request.userid, v_account,
|
|
1001 | 1001 |
v_container, v_object, 'pithos') |
1002 | 1002 |
except NotAllowedError: |
1003 | 1003 |
raise Forbidden('Not allowed') |
... | ... | |
1023 | 1023 |
content_type, meta, permissions, public = get_object_headers(request) |
1024 | 1024 |
|
1025 | 1025 |
try: |
1026 |
prev_meta = request.backend.get_object_meta(request.user_uniq, v_account,
|
|
1026 |
prev_meta = request.backend.get_object_meta(request.userid, v_account,
|
|
1027 | 1027 |
v_container, v_object, 'pithos') |
1028 | 1028 |
except NotAllowedError: |
1029 | 1029 |
raise Forbidden('Not allowed') |
... | ... | |
1046 | 1046 |
# Do permissions first, as it may fail easier. |
1047 | 1047 |
if permissions is not None: |
1048 | 1048 |
try: |
1049 |
request.backend.update_object_permissions(request.user_uniq,
|
|
1049 |
request.backend.update_object_permissions(request.userid,
|
|
1050 | 1050 |
v_account, v_container, v_object, permissions) |
1051 | 1051 |
except NotAllowedError: |
1052 | 1052 |
raise Forbidden('Not allowed') |
... | ... | |
1056 | 1056 |
raise BadRequest('Invalid sharing header') |
1057 | 1057 |
if public is not None: |
1058 | 1058 |
try: |
1059 |
request.backend.update_object_public(request.user_uniq, v_account,
|
|
1059 |
request.backend.update_object_public(request.userid, v_account,
|
|
1060 | 1060 |
v_container, v_object, public) |
1061 | 1061 |
except NotAllowedError: |
1062 | 1062 |
raise Forbidden('Not allowed') |
... | ... | |
1064 | 1064 |
raise ItemNotFound('Object does not exist') |
1065 | 1065 |
if meta or replace: |
1066 | 1066 |
try: |
1067 |
version_id = request.backend.update_object_meta(request.user_uniq,
|
|
1067 |
version_id = request.backend.update_object_meta(request.userid,
|
|
1068 | 1068 |
v_account, v_container, v_object, 'pithos', meta, replace) |
1069 | 1069 |
except NotAllowedError: |
1070 | 1070 |
raise Forbidden('Not allowed') |
... | ... | |
1085 | 1085 |
raise RangeNotSatisfiable('Invalid Content-Range header') |
1086 | 1086 |
|
1087 | 1087 |
try: |
1088 |
size, hashmap = request.backend.get_object_hashmap(request.user_uniq,
|
|
1088 |
size, hashmap = request.backend.get_object_hashmap(request.userid,
|
|
1089 | 1089 |
v_account, v_container, v_object) |
1090 | 1090 |
except NotAllowedError: |
1091 | 1091 |
raise Forbidden('Not allowed') |
... | ... | |
1100 | 1100 |
if src_object: |
1101 | 1101 |
src_account = request.META.get('HTTP_X_SOURCE_ACCOUNT') |
1102 | 1102 |
if not src_account: |
1103 |
src_account = request.user_uniq
|
|
1103 |
src_account = request.userid
|
|
1104 | 1104 |
src_container, src_name = split_container_object_string(src_object) |
1105 | 1105 |
src_version = request.META.get('HTTP_X_SOURCE_VERSION') |
1106 | 1106 |
try: |
1107 |
src_size, src_hashmap = request.backend.get_object_hashmap(request.user_uniq,
|
|
1107 |
src_size, src_hashmap = request.backend.get_object_hashmap(request.userid,
|
|
1108 | 1108 |
src_account, src_container, src_name, src_version) |
1109 | 1109 |
except NotAllowedError: |
1110 | 1110 |
raise Forbidden('Not allowed') |
... | ... | |
1189 | 1189 |
hashmap = hashmap[:(int((size - 1) / request.backend.block_size) + 1)] |
1190 | 1190 |
checksum = hashmap_md5(request, hashmap, size) |
1191 | 1191 |
try: |
1192 |
version_id = request.backend.update_object_hashmap(request.user_uniq,
|
|
1192 |
version_id = request.backend.update_object_hashmap(request.userid,
|
|
1193 | 1193 |
v_account, v_container, v_object, size, prev_meta['type'], |
1194 | 1194 |
hashmap, checksum, 'pithos', meta, replace, permissions) |
1195 | 1195 |
except NotAllowedError: |
... | ... | |
1202 | 1202 |
raise RequestEntityTooLarge('Quota exceeded') |
1203 | 1203 |
if public is not None: |
1204 | 1204 |
try: |
1205 |
request.backend.update_object_public(request.user_uniq, v_account,
|
|
1205 |
request.backend.update_object_public(request.userid, v_account,
|
|
1206 | 1206 |
v_container, v_object, public) |
1207 | 1207 |
except NotAllowedError: |
1208 | 1208 |
raise Forbidden('Not allowed') |
... | ... | |
1224 | 1224 |
|
1225 | 1225 |
until = get_int_parameter(request.GET.get('until')) |
1226 | 1226 |
try: |
1227 |
request.backend.delete_object(request.user_uniq, v_account, v_container,
|
|
1227 |
request.backend.delete_object(request.userid, v_account, v_container,
|
|
1228 | 1228 |
v_object, until) |
1229 | 1229 |
except NotAllowedError: |
1230 | 1230 |
raise Forbidden('Not allowed') |
Also available in: Unified diff