Revision c5b0bbb7

b/snf-astakos-app/astakos/im/functions.py
346 346
        raise ProjectNotFound(m)
347 347

  
348 348

  
349
def checkAllowed(entity, request_user, admin_only=False):
350
    if isinstance(entity, Project):
351
        application = entity.application
352
    elif isinstance(entity, ProjectApplication):
353
        application = entity
354
    else:
355
        m = "%s not a Project nor a ProjectApplication" % (entity,)
356
        raise ValueError(m)
357

  
358
    if not request_user or request_user.is_project_admin():
359
        return
349
ALLOWED_CHECKS = [
350
    (lambda u, a: not u or u.is_project_admin()),
351
    (lambda u, a: a.owner == u),
352
    (lambda u, a: a.applicant == u),
353
    (lambda u, a: a.chain.overall_state() == Project.O_ACTIVE
354
     or bool(a.chain.projectmembership_set.any_accepted().filter(person=u))),
355
]
356

  
357
ADMIN_LEVEL = 0
358
OWNER_LEVEL = 1
359
APPLICANT_LEVEL = 2
360
ANY_LEVEL = 3
361

  
362

  
363
def _check_yield(b, silent=False):
364
    if b:
365
        return True
360 366

  
361
    if not admin_only and application.owner == request_user:
362
        return
367
    if silent:
368
        return False
363 369

  
364 370
    m = _(astakos_messages.NOT_ALLOWED)
365 371
    raise ProjectForbidden(m)
366 372

  
367 373

  
374
def membership_check_allowed(membership, request_user,
375
                             level=OWNER_LEVEL, silent=False):
376
    r = project_check_allowed(
377
        membership.project, request_user, level, silent=True)
378

  
379
    return _check_yield(r or membership.person == request_user, silent)
380

  
381

  
382
def project_check_allowed(project, request_user,
383
                          level=OWNER_LEVEL, silent=False):
384
    return app_check_allowed(project.application, request_user, level, silent)
385

  
386

  
387
def app_check_allowed(application, request_user,
388
                      level=OWNER_LEVEL, silent=False):
389
    checks = (f(request_user, application) for f in ALLOWED_CHECKS[:level+1])
390
    return _check_yield(any(checks), silent)
391

  
392

  
368 393
def checkAlive(project):
369 394
    if not project.is_alive:
370 395
        m = _(astakos_messages.NOT_ALIVE_PROJECT) % project.id
......
372 397

  
373 398

  
374 399
def accept_membership_project_checks(project, request_user):
375
    checkAllowed(project, request_user)
400
    project_check_allowed(project, request_user)
376 401
    checkAlive(project)
377 402

  
378 403
    join_policy = project.application.member_join_policy
......
414 439
        raise ProjectConflict(m)
415 440

  
416 441
    project = membership.project
417
    checkAllowed(project, request_user)
442
    project_check_allowed(project, request_user)
418 443
    checkAlive(project)
419 444

  
420 445

  
......
436 461
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
437 462
        raise ProjectConflict(m)
438 463

  
439
    if membership.person != request_user:
440
        msg = _(astakos_messages.NOT_ALLOWED)
441
        raise ProjectForbidden(msg)
442

  
464
    membership_check_allowed(membership, request_user, level=ADMIN_LEVEL)
443 465
    project = membership.project
444 466
    checkAlive(project)
445 467

  
......
459 481
        raise ProjectConflict(m)
460 482

  
461 483
    project = membership.project
462
    checkAllowed(project, request_user)
484
    project_check_allowed(project, request_user)
463 485
    checkAlive(project)
464 486

  
465 487
    leave_policy = project.application.member_leave_policy
......
513 535
        m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP)
514 536
        raise ProjectConflict(m)
515 537

  
516
    if membership.person != request_user:
517
        msg = _(astakos_messages.NOT_ALLOWED)
518
        raise ProjectForbidden(msg)
519

  
538
    membership_check_allowed(membership, request_user, level=ADMIN_LEVEL)
520 539
    project = membership.project
521 540
    checkAlive(project)
522 541

  
......
649 668
    project = None
650 669
    if project_id is not None:
651 670
        project = get_project_for_update(project_id)
652

  
653
        if (request_user and
654
            (not project.application.owner == request_user and
655
             not request_user.is_superuser
656
             and not request_user.is_project_admin())):
657
            m = _(astakos_messages.NOT_ALLOWED)
658
            raise ProjectForbidden(m)
671
        project_check_allowed(project, request_user, level=APPLICANT_LEVEL)
659 672

  
660 673
    policies = validate_resource_policies(resources)
661 674

  
......
744 757
def cancel_application(application_id, request_user=None, reason=""):
745 758
    get_project_of_application_for_update(application_id)
746 759
    application = get_application(application_id)
747
    checkAllowed(application, request_user)
760
    app_check_allowed(application, request_user, level=APPLICANT_LEVEL)
748 761

  
749 762
    if not application.can_cancel():
750 763
        m = _(astakos_messages.APPLICATION_CANNOT_CANCEL %
......
760 773
def dismiss_application(application_id, request_user=None, reason=""):
761 774
    get_project_of_application_for_update(application_id)
762 775
    application = get_application(application_id)
763
    checkAllowed(application, request_user)
776
    app_check_allowed(application, request_user, level=APPLICANT_LEVEL)
764 777

  
765 778
    if not application.can_dismiss():
766 779
        m = _(astakos_messages.APPLICATION_CANNOT_DISMISS %
......
775 788
    get_project_of_application_for_update(application_id)
776 789
    application = get_application(application_id)
777 790

  
778
    checkAllowed(application, request_user, admin_only=True)
791
    app_check_allowed(application, request_user, level=ADMIN_LEVEL)
779 792

  
780 793
    if not application.can_deny():
781 794
        m = _(astakos_messages.APPLICATION_CANNOT_DENY %
......
809 822
    project = get_project_of_application_for_update(app_id)
810 823
    application = get_application(app_id)
811 824

  
812
    checkAllowed(application, request_user, admin_only=True)
825
    app_check_allowed(application, request_user, level=ADMIN_LEVEL)
813 826

  
814 827
    if not application.can_approve():
815 828
        m = _(astakos_messages.APPLICATION_CANNOT_APPROVE %
......
850 863

  
851 864
def terminate(project_id, request_user=None):
852 865
    project = get_project_for_update(project_id)
853
    checkAllowed(project, request_user, admin_only=True)
866
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
854 867
    checkAlive(project)
855 868

  
856 869
    project.terminate()
......
862 875

  
863 876
def suspend(project_id, request_user=None):
864 877
    project = get_project_for_update(project_id)
865
    checkAllowed(project, request_user, admin_only=True)
878
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
866 879
    checkAlive(project)
867 880

  
868 881
    project.suspend()
......
874 887

  
875 888
def resume(project_id, request_user=None):
876 889
    project = get_project_for_update(project_id)
877
    checkAllowed(project, request_user, admin_only=True)
890
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
878 891

  
879 892
    if not project.is_suspended:
880 893
        m = _(astakos_messages.NOT_SUSPENDED_PROJECT) % project.id

Also available in: Unified diff