Revision f12bcb3d snf-astakos-app/astakos/im/functions.py
b/snf-astakos-app/astakos/im/functions.py | ||
---|---|---|
38 | 38 |
from django.core.mail import send_mail, get_connection |
39 | 39 |
from django.core.urlresolvers import reverse |
40 | 40 |
from django.contrib.auth import login as auth_login, logout as auth_logout |
41 |
from django.core.exceptions import PermissionDenied |
|
42 | 41 |
from django.db.models import Q |
43 | 42 |
|
44 | 43 |
from synnefo_branding.utils import render_to_string |
... | ... | |
244 | 243 |
|
245 | 244 |
### PROJECT FUNCTIONS ### |
246 | 245 |
|
246 |
|
|
247 |
class ProjectError(Exception): |
|
248 |
pass |
|
249 |
|
|
250 |
|
|
251 |
class ProjectNotFound(ProjectError): |
|
252 |
pass |
|
253 |
|
|
254 |
|
|
255 |
class ProjectForbidden(ProjectError): |
|
256 |
pass |
|
257 |
|
|
258 |
|
|
259 |
class ProjectBadRequest(ProjectError): |
|
260 |
pass |
|
261 |
|
|
262 |
|
|
263 |
class ProjectConflict(ProjectError): |
|
264 |
pass |
|
265 |
|
|
247 | 266 |
AUTO_ACCEPT_POLICY = 1 |
248 | 267 |
MODERATED_POLICY = 2 |
249 | 268 |
CLOSED_POLICY = 3 |
... | ... | |
264 | 283 |
return Project.objects.get(id=project_id) |
265 | 284 |
except Project.DoesNotExist: |
266 | 285 |
m = _(astakos_messages.UNKNOWN_PROJECT_ID) % project_id |
267 |
raise IOError(m)
|
|
286 |
raise ProjectNotFound(m)
|
|
268 | 287 |
|
269 | 288 |
|
270 | 289 |
def get_project_for_update(project_id): |
... | ... | |
272 | 291 |
return Project.objects.get_for_update(id=project_id) |
273 | 292 |
except Project.DoesNotExist: |
274 | 293 |
m = _(astakos_messages.UNKNOWN_PROJECT_ID) % project_id |
275 |
raise IOError(m)
|
|
294 |
raise ProjectNotFound(m)
|
|
276 | 295 |
|
277 | 296 |
|
278 | 297 |
def get_project_of_application_for_update(app_id): |
... | ... | |
285 | 304 |
return ProjectApplication.objects.get(id=application_id) |
286 | 305 |
except ProjectApplication.DoesNotExist: |
287 | 306 |
m = _(astakos_messages.UNKNOWN_PROJECT_APPLICATION_ID) % application_id |
288 |
raise IOError(m)
|
|
307 |
raise ProjectNotFound(m)
|
|
289 | 308 |
|
290 | 309 |
|
291 | 310 |
def get_project_of_membership_for_update(memb_id): |
... | ... | |
298 | 317 |
return AstakosUser.objects.get(id=user_id) |
299 | 318 |
except AstakosUser.DoesNotExist: |
300 | 319 |
m = _(astakos_messages.UNKNOWN_USER_ID) % user_id |
301 |
raise IOError(m)
|
|
320 |
raise ProjectNotFound(m)
|
|
302 | 321 |
|
303 | 322 |
|
304 | 323 |
def get_user_by_uuid(uuid): |
... | ... | |
306 | 325 |
return AstakosUser.objects.get(uuid=uuid) |
307 | 326 |
except AstakosUser.DoesNotExist: |
308 | 327 |
m = _(astakos_messages.UNKNOWN_USER_ID) % uuid |
309 |
raise IOError(m)
|
|
328 |
raise ProjectNotFound(m)
|
|
310 | 329 |
|
311 | 330 |
|
312 | 331 |
def get_membership(project_id, user_id): |
... | ... | |
315 | 334 |
return objs.get(project__id=project_id, person__id=user_id) |
316 | 335 |
except ProjectMembership.DoesNotExist: |
317 | 336 |
m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST) |
318 |
raise IOError(m)
|
|
337 |
raise ProjectNotFound(m)
|
|
319 | 338 |
|
320 | 339 |
|
321 | 340 |
def get_membership_by_id(memb_id): |
... | ... | |
324 | 343 |
return objs.get(id=memb_id) |
325 | 344 |
except ProjectMembership.DoesNotExist: |
326 | 345 |
m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST) |
327 |
raise IOError(m)
|
|
346 |
raise ProjectNotFound(m)
|
|
328 | 347 |
|
329 | 348 |
|
330 | 349 |
def checkAllowed(entity, request_user, admin_only=False): |
... | ... | |
343 | 362 |
return |
344 | 363 |
|
345 | 364 |
m = _(astakos_messages.NOT_ALLOWED) |
346 |
raise PermissionDenied(m)
|
|
365 |
raise ProjectForbidden(m)
|
|
347 | 366 |
|
348 | 367 |
|
349 | 368 |
def checkAlive(project): |
350 | 369 |
if not project.is_alive: |
351 | 370 |
m = _(astakos_messages.NOT_ALIVE_PROJECT) % project.id |
352 |
raise PermissionDenied(m)
|
|
371 |
raise ProjectConflict(m)
|
|
353 | 372 |
|
354 | 373 |
|
355 | 374 |
def accept_membership_project_checks(project, request_user): |
... | ... | |
359 | 378 |
join_policy = project.application.member_join_policy |
360 | 379 |
if join_policy == CLOSED_POLICY: |
361 | 380 |
m = _(astakos_messages.MEMBER_JOIN_POLICY_CLOSED) |
362 |
raise PermissionDenied(m)
|
|
381 |
raise ProjectConflict(m)
|
|
363 | 382 |
|
364 | 383 |
if project.violates_members_limit(adding=1): |
365 | 384 |
m = _(astakos_messages.MEMBER_NUMBER_LIMIT_REACHED) |
366 |
raise PermissionDenied(m)
|
|
385 |
raise ProjectConflict(m)
|
|
367 | 386 |
|
368 | 387 |
|
369 | 388 |
def accept_membership_checks(membership, request_user): |
370 | 389 |
if not membership.can_accept(): |
371 | 390 |
m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST) |
372 |
raise PermissionDenied(m)
|
|
391 |
raise ProjectConflict(m)
|
|
373 | 392 |
|
374 | 393 |
project = membership.project |
375 | 394 |
accept_membership_project_checks(project, request_user) |
... | ... | |
392 | 411 |
def reject_membership_checks(membership, request_user): |
393 | 412 |
if not membership.can_reject(): |
394 | 413 |
m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST) |
395 |
raise PermissionDenied(m)
|
|
414 |
raise ProjectConflict(m)
|
|
396 | 415 |
|
397 | 416 |
project = membership.project |
398 | 417 |
checkAllowed(project, request_user) |
... | ... | |
415 | 434 |
def cancel_membership_checks(membership, request_user): |
416 | 435 |
if not membership.can_cancel(): |
417 | 436 |
m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST) |
418 |
raise PermissionDenied(m)
|
|
437 |
raise ProjectConflict(m)
|
|
419 | 438 |
|
420 | 439 |
if membership.person != request_user: |
421 |
raise PermissionDenied() |
|
440 |
msg = _(astakos_messages.NOT_ALLOWED) |
|
441 |
raise ProjectForbidden(msg) |
|
422 | 442 |
|
423 | 443 |
project = membership.project |
424 | 444 |
checkAlive(project) |
... | ... | |
436 | 456 |
def remove_membership_checks(membership, request_user=None): |
437 | 457 |
if not membership.can_remove(): |
438 | 458 |
m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP) |
439 |
raise PermissionDenied(m)
|
|
459 |
raise ProjectConflict(m)
|
|
440 | 460 |
|
441 | 461 |
project = membership.project |
442 | 462 |
checkAllowed(project, request_user) |
... | ... | |
445 | 465 |
leave_policy = project.application.member_leave_policy |
446 | 466 |
if leave_policy == CLOSED_POLICY: |
447 | 467 |
m = _(astakos_messages.MEMBER_LEAVE_POLICY_CLOSED) |
448 |
raise PermissionDenied(m)
|
|
468 |
raise ProjectConflict(m)
|
|
449 | 469 |
|
450 | 470 |
|
451 | 471 |
def remove_membership(memb_id, request_user=None): |
... | ... | |
464 | 484 |
|
465 | 485 |
def enroll_member(project_id, user, request_user=None): |
466 | 486 |
project = get_project_for_update(project_id) |
487 |
try: |
|
488 |
project = get_project_for_update(project_id) |
|
489 |
except ProjectNotFound as e: |
|
490 |
raise ProjectConflict(e.message) |
|
467 | 491 |
accept_membership_project_checks(project, request_user) |
468 | 492 |
|
469 | 493 |
try: |
470 | 494 |
membership = get_membership(project_id, user.id) |
471 | 495 |
if not membership.can_enroll(): |
472 | 496 |
m = _(astakos_messages.MEMBERSHIP_ACCEPTED) |
473 |
raise PermissionDenied(m)
|
|
497 |
raise ProjectConflict(m)
|
|
474 | 498 |
membership.join() |
475 |
except IOError:
|
|
499 |
except ProjectNotFound:
|
|
476 | 500 |
membership = new_membership(project, user) |
477 | 501 |
|
478 | 502 |
membership.accept() |
... | ... | |
487 | 511 |
def leave_project_checks(membership, request_user): |
488 | 512 |
if not membership.can_leave(): |
489 | 513 |
m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP) |
490 |
raise PermissionDenied(m)
|
|
514 |
raise ProjectConflict(m)
|
|
491 | 515 |
|
492 | 516 |
if membership.person != request_user: |
493 |
raise PermissionDenied() |
|
517 |
msg = _(astakos_messages.NOT_ALLOWED) |
|
518 |
raise ProjectForbidden(msg) |
|
494 | 519 |
|
495 | 520 |
project = membership.project |
496 | 521 |
checkAlive(project) |
... | ... | |
498 | 523 |
leave_policy = project.application.member_leave_policy |
499 | 524 |
if leave_policy == CLOSED_POLICY: |
500 | 525 |
m = _(astakos_messages.MEMBER_LEAVE_POLICY_CLOSED) |
501 |
raise PermissionDenied(m)
|
|
526 |
raise ProjectConflict(m)
|
|
502 | 527 |
|
503 | 528 |
|
504 | 529 |
def can_leave_request(project, user): |
... | ... | |
507 | 532 |
return False |
508 | 533 |
try: |
509 | 534 |
leave_project_checks(m, user) |
510 |
except PermissionDenied:
|
|
535 |
except ProjectError:
|
|
511 | 536 |
return False |
512 | 537 |
return True |
513 | 538 |
|
... | ... | |
539 | 564 |
join_policy = project.application.member_join_policy |
540 | 565 |
if join_policy == CLOSED_POLICY: |
541 | 566 |
m = _(astakos_messages.MEMBER_JOIN_POLICY_CLOSED) |
542 |
raise PermissionDenied(m)
|
|
567 |
raise ProjectConflict(m)
|
|
543 | 568 |
|
544 | 569 |
|
545 | 570 |
def can_join_request(project, user): |
546 | 571 |
try: |
547 | 572 |
join_project_checks(project) |
548 |
except PermissionDenied:
|
|
573 |
except ProjectError:
|
|
549 | 574 |
return False |
550 | 575 |
|
551 | 576 |
m = user.get_membership(project) |
... | ... | |
568 | 593 |
membership = get_membership(project.id, request_user.id) |
569 | 594 |
if not membership.can_join(): |
570 | 595 |
msg = _(astakos_messages.MEMBERSHIP_ASSOCIATED) |
571 |
raise PermissionDenied(msg)
|
|
596 |
raise ProjectConflict(msg)
|
|
572 | 597 |
membership.join() |
573 |
except IOError:
|
|
598 |
except ProjectNotFound:
|
|
574 | 599 |
membership = new_membership(project, request_user) |
575 | 600 |
|
576 | 601 |
join_policy = project.application.member_join_policy |
... | ... | |
602 | 627 |
try: |
603 | 628 |
check(membership, request_user) |
604 | 629 |
allowed.append(action) |
605 |
except PermissionDenied:
|
|
630 |
except ProjectError:
|
|
606 | 631 |
pass |
607 | 632 |
return allowed |
608 | 633 |
|
... | ... | |
630 | 655 |
not request_user.is_superuser |
631 | 656 |
and not request_user.is_project_admin())): |
632 | 657 |
m = _(astakos_messages.NOT_ALLOWED) |
633 |
raise PermissionDenied(m)
|
|
658 |
raise ProjectForbidden(m)
|
|
634 | 659 |
|
635 | 660 |
policies = validate_resource_policies(resources) |
636 | 661 |
|
... | ... | |
638 | 663 |
ok, limit = qh_add_pending_app(owner, project, force) |
639 | 664 |
if not ok: |
640 | 665 |
m = _(astakos_messages.REACHED_PENDING_APPLICATION_LIMIT) % limit |
641 |
raise PermissionDenied(m)
|
|
666 |
raise ProjectConflict(m)
|
|
642 | 667 |
|
643 | 668 |
application = ProjectApplication( |
644 | 669 |
applicant=request_user, |
... | ... | |
693 | 718 |
found = resource_d.keys() |
694 | 719 |
nonex = [name for name in resource_names if name not in found] |
695 | 720 |
if nonex: |
696 |
raise ValueError("Malformed resource policies")
|
|
721 |
raise ProjectBadRequest("Malformed resource policies")
|
|
697 | 722 |
|
698 | 723 |
pols = [] |
699 | 724 |
for resource_name, specs in policies.iteritems(): |
... | ... | |
701 | 726 |
m_capacity = specs.get("member_capacity") |
702 | 727 |
|
703 | 728 |
if p_capacity is not None and not isinstance(p_capacity, (int, long)): |
704 |
raise ValueError("Malformed resource policies")
|
|
729 |
raise ProjectBadRequest("Malformed resource policies")
|
|
705 | 730 |
if not isinstance(m_capacity, (int, long)): |
706 |
raise ValueError("Malformed resource policies")
|
|
731 |
raise ProjectBadRequest("Malformed resource policies")
|
|
707 | 732 |
pols.append((resource_d[resource_name], m_capacity, p_capacity)) |
708 | 733 |
return pols |
709 | 734 |
|
... | ... | |
724 | 749 |
if not application.can_cancel(): |
725 | 750 |
m = _(astakos_messages.APPLICATION_CANNOT_CANCEL % |
726 | 751 |
(application.id, application.state_display())) |
727 |
raise PermissionDenied(m)
|
|
752 |
raise ProjectConflict(m)
|
|
728 | 753 |
|
729 | 754 |
qh_release_pending_app(application.owner) |
730 | 755 |
|
... | ... | |
740 | 765 |
if not application.can_dismiss(): |
741 | 766 |
m = _(astakos_messages.APPLICATION_CANNOT_DISMISS % |
742 | 767 |
(application.id, application.state_display())) |
743 |
raise PermissionDenied(m)
|
|
768 |
raise ProjectConflict(m)
|
|
744 | 769 |
|
745 | 770 |
application.dismiss() |
746 | 771 |
logger.info("%s has been dismissed." % (application.log_display)) |
... | ... | |
755 | 780 |
if not application.can_deny(): |
756 | 781 |
m = _(astakos_messages.APPLICATION_CANNOT_DENY % |
757 | 782 |
(application.id, application.state_display())) |
758 |
raise PermissionDenied(m)
|
|
783 |
raise ProjectConflict(m)
|
|
759 | 784 |
|
760 | 785 |
qh_release_pending_app(application.owner) |
761 | 786 |
|
... | ... | |
775 | 800 |
m = (_("cannot approve: project with name '%s' " |
776 | 801 |
"already exists (id: %s)") % |
777 | 802 |
(new_project_name, conflicting_project.id)) |
778 |
raise PermissionDenied(m) # invalid argument
|
|
803 |
raise ProjectConflict(m) # invalid argument
|
|
779 | 804 |
except Project.DoesNotExist: |
780 | 805 |
pass |
781 | 806 |
|
... | ... | |
789 | 814 |
if not application.can_approve(): |
790 | 815 |
m = _(astakos_messages.APPLICATION_CANNOT_APPROVE % |
791 | 816 |
(application.id, application.state_display())) |
792 |
raise PermissionDenied(m)
|
|
817 |
raise ProjectConflict(m)
|
|
793 | 818 |
|
794 | 819 |
check_conflicting_projects(application) |
795 | 820 |
|
... | ... | |
853 | 878 |
|
854 | 879 |
if not project.is_suspended: |
855 | 880 |
m = _(astakos_messages.NOT_SUSPENDED_PROJECT) % project.id |
856 |
raise PermissionDenied(m)
|
|
881 |
raise ProjectConflict(m)
|
|
857 | 882 |
|
858 | 883 |
project.resume() |
859 | 884 |
qh_sync_project(project) |
Also available in: Unified diff