Revision 8cf9b2dd
b/snf-astakos-app/astakos/im/functions.py | ||
---|---|---|
67 | 67 |
from astakos.im.notifications import build_notification, NotificationError |
68 | 68 |
from astakos.im.models import ( |
69 | 69 |
AstakosUser, ProjectMembership, ProjectApplication, Project, |
70 |
sync_projects, PendingMembershipError, get_resource_names, new_chain)
|
|
70 |
PendingMembershipError, get_resource_names, new_chain) |
|
71 | 71 |
from astakos.im.project_notif import ( |
72 | 72 |
membership_change_notify, |
73 | 73 |
application_submit_notify, application_approve_notify, |
... | ... | |
515 | 515 |
raise PermissionDenied(m) |
516 | 516 |
|
517 | 517 |
membership.accept() |
518 |
sync_projects() |
|
519 | 518 |
|
520 | 519 |
membership_change_notify(project, membership.person, 'accepted') |
521 | 520 |
|
... | ... | |
569 | 568 |
raise PermissionDenied(m) |
570 | 569 |
|
571 | 570 |
membership.remove() |
572 |
sync_projects() |
|
573 | 571 |
|
574 | 572 |
membership_change_notify(project, membership.person, 'removed') |
575 | 573 |
|
... | ... | |
585 | 583 |
raise PermissionDenied(m) |
586 | 584 |
|
587 | 585 |
membership.accept() |
588 |
sync_projects() |
|
589 | 586 |
|
590 | 587 |
# TODO send proper notification |
591 | 588 |
return membership |
... | ... | |
608 | 605 |
leave_policy = project.application.member_leave_policy |
609 | 606 |
if leave_policy == AUTO_ACCEPT_POLICY: |
610 | 607 |
membership.remove() |
611 |
sync_projects() |
|
612 | 608 |
else: |
613 | 609 |
membership.leave_request_date = datetime.now() |
614 | 610 |
membership.save() |
... | ... | |
630 | 626 |
if (join_policy == AUTO_ACCEPT_POLICY and |
631 | 627 |
not project.violates_members_limit(adding=1)): |
632 | 628 |
membership.accept() |
633 |
sync_projects() |
|
634 | 629 |
return membership |
635 | 630 |
|
636 | 631 |
def submit_application(kw, request_user=None): |
... | ... | |
718 | 713 |
raise PermissionDenied(m) |
719 | 714 |
|
720 | 715 |
application.approve() |
721 |
sync_projects() |
|
722 |
|
|
723 | 716 |
application_approve_notify(application) |
724 | 717 |
|
725 | 718 |
def check_expiration(execute=False): |
... | ... | |
736 | 729 |
checkAlive(project) |
737 | 730 |
|
738 | 731 |
project.terminate() |
739 |
sync_projects() |
|
740 | 732 |
|
741 | 733 |
project_termination_notify(project) |
742 | 734 |
|
... | ... | |
745 | 737 |
checkAlive(project) |
746 | 738 |
|
747 | 739 |
project.suspend() |
748 |
sync_projects() |
|
749 | 740 |
|
750 | 741 |
project_suspension_notify(project) |
751 | 742 |
|
... | ... | |
757 | 748 |
raise PermissionDenied(m) |
758 | 749 |
|
759 | 750 |
project.resume() |
760 |
sync_projects() |
|
761 | 751 |
|
762 | 752 |
def get_by_chain_or_404(chain_id): |
763 | 753 |
try: |
b/snf-astakos-app/astakos/im/management/commands/project-admin-checks.py | ||
---|---|---|
33 | 33 |
|
34 | 34 |
from optparse import make_option |
35 | 35 |
from django.core.management.base import BaseCommand, CommandError |
36 |
from django.db import transaction |
|
37 | 36 |
|
38 | 37 |
from astakos.im.functions import check_expiration |
38 |
from astakos.im.project_xctx import project_transaction_context |
|
39 | 39 |
|
40 |
@transaction.commit_manually |
|
41 | 40 |
class Command(BaseCommand): |
42 | 41 |
help = "Perform administration checks on projects" |
43 | 42 |
|
... | ... | |
84 | 83 |
def handle(self, *args, **options): |
85 | 84 |
|
86 | 85 |
execute = options['execute'] |
86 |
if options['expire']: |
|
87 |
self.expire(execute=execute) |
|
87 | 88 |
|
89 |
@project_transaction_context(sync=True) |
|
90 |
def expire(self, execute=False, ctx=None): |
|
88 | 91 |
try: |
89 |
if options['expire']: |
|
90 |
projects = check_expiration(execute=execute) |
|
91 |
self.print_expired(projects, execute) |
|
92 |
projects = check_expiration(execute=execute) |
|
93 |
self.print_expired(projects, execute) |
|
92 | 94 |
except BaseException as e: |
93 |
transaction.rollback() |
|
95 |
if ctx: |
|
96 |
ctx.mark_rollback() |
|
94 | 97 |
raise CommandError(e) |
95 |
else: |
|
96 |
transaction.commit() |
b/snf-astakos-app/astakos/im/management/commands/project-approve.py | ||
---|---|---|
34 | 34 |
from optparse import make_option |
35 | 35 |
|
36 | 36 |
from django.core.management.base import BaseCommand, CommandError |
37 |
from django.db import transaction |
|
38 | 37 |
|
39 | 38 |
from astakos.im.models import ProjectApplication |
40 | 39 |
from astakos.im.functions import approve_application |
41 |
|
|
40 |
from astakos.im.project_xctx import project_transaction_context |
|
41 |
|
|
42 | 42 |
class Command(BaseCommand): |
43 | 43 |
args = "<project application id>" |
44 |
help = "Update project state"
|
|
44 |
help = "Approve project application"
|
|
45 | 45 |
|
46 |
@transaction.commit_manually |
|
47 | 46 |
def handle(self, *args, **options): |
48 | 47 |
if len(args) < 1: |
49 |
raise CommandError("Please provide a group identifier")
|
|
50 |
|
|
48 |
raise CommandError("Please provide an application id")
|
|
49 |
|
|
51 | 50 |
try: |
52 | 51 |
id = int(args[0]) |
53 | 52 |
except ValueError: |
... | ... | |
58 | 57 |
app = ProjectApplication.objects.get(id=id) |
59 | 58 |
except ProjectApplication.DoesNotExist: |
60 | 59 |
raise CommandError('Invalid id') |
61 |
try: |
|
62 |
approve_application(app) |
|
63 |
except BaseException, e: |
|
64 |
transaction.rollback() |
|
65 |
raise CommandError(e) |
|
66 |
else: |
|
67 |
transaction.commit() |
|
60 |
|
|
61 |
approve(app) |
|
62 |
|
|
63 |
@project_transaction_context(sync=True) |
|
64 |
def approve(app, ctx=None): |
|
65 |
try: |
|
66 |
approve_application(app) |
|
67 |
except BaseException as e: |
|
68 |
if ctx: |
|
69 |
ctx.mark_rollback() |
|
70 |
raise CommandError(e) |
b/snf-astakos-app/astakos/im/management/commands/project-update.py | ||
---|---|---|
34 | 34 |
from optparse import make_option |
35 | 35 |
|
36 | 36 |
from django.core.management.base import BaseCommand, CommandError |
37 |
from django.db import transaction |
|
38 |
from django.views.generic.create_update import lookup_object |
|
39 |
from django.http import Http404 |
|
40 |
|
|
41 |
from astakos.im.models import ( |
|
42 |
ProjectApplication, Project) |
|
43 |
|
|
44 | 37 |
from astakos.im.functions import terminate, suspend, resume |
38 |
from astakos.im.project_xctx import project_transaction_context |
|
45 | 39 |
|
46 |
@transaction.commit_manually |
|
47 | 40 |
class Command(BaseCommand): |
48 | 41 |
args = "<project id>" |
49 | 42 |
help = "Update project state" |
... | ... | |
53 | 46 |
action='store_true', |
54 | 47 |
dest='terminate', |
55 | 48 |
default=False, |
56 |
help="Terminate group"),
|
|
49 |
help="Terminate project"),
|
|
57 | 50 |
make_option('--resume', |
58 | 51 |
action='store_true', |
59 | 52 |
dest='resume', |
60 | 53 |
default=False, |
61 |
help="Resume group"),
|
|
54 |
help="Resume project"),
|
|
62 | 55 |
make_option('--suspend', |
63 | 56 |
action='store_true', |
64 | 57 |
dest='suspend', |
65 | 58 |
default=False, |
66 |
help="Suspend group")
|
|
59 |
help="Suspend project")
|
|
67 | 60 |
) |
68 | 61 |
|
69 | 62 |
def handle(self, *args, **options): |
70 | 63 |
if len(args) < 1: |
71 |
raise CommandError("Please provide a group identifier") |
|
72 |
|
|
64 |
raise CommandError("Please provide a project id") |
|
73 | 65 |
try: |
74 | 66 |
id = int(args[0]) |
75 | 67 |
except ValueError: |
76 | 68 |
raise CommandError('Invalid id') |
77 | 69 |
else: |
78 |
try: |
|
79 |
if options['terminate']: |
|
80 |
terminate(id) |
|
81 |
elif options['resume']: |
|
82 |
resume(id) |
|
83 |
elif options['suspend']: |
|
84 |
suspend(id) |
|
85 |
except BaseException, e: |
|
86 |
transaction.rollback() |
|
87 |
raise CommandError(e) |
|
88 |
else: |
|
89 |
transaction.commit() |
|
70 |
if options['terminate']: |
|
71 |
run_command(terminate, id) |
|
72 |
elif options['resume']: |
|
73 |
run_command(resume, id) |
|
74 |
elif options['suspend']: |
|
75 |
run_command(suspend, id) |
|
76 |
|
|
77 |
@project_transaction_context(sync=True) |
|
78 |
def run_command(func, id, ctx=None): |
|
79 |
try: |
|
80 |
func(id) |
|
81 |
except BaseException as e: |
|
82 |
if ctx: |
|
83 |
ctx.mark_rollback() |
|
84 |
raise CommandError(e) |
b/snf-astakos-app/astakos/im/notification_xctx.py | ||
---|---|---|
1 |
# Copyright 2013 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from synnefo.lib.db.xctx import TransactionContext, TransactionHandler |
|
35 |
from astakos.im.notifications import Notification |
|
36 |
|
|
37 |
# USAGE |
|
38 |
# ===== |
|
39 |
# @notification_transaction_context(notify=False) |
|
40 |
# def a_view(args, ctx=None): |
|
41 |
# ... |
|
42 |
# if ctx: |
|
43 |
# ctx.mark_rollback() |
|
44 |
# ... |
|
45 |
# return http response |
|
46 |
# |
|
47 |
# OR |
|
48 |
# |
|
49 |
# def a_view(args): |
|
50 |
# with notification_transaction_context(notify=False) as ctx: |
|
51 |
# ... |
|
52 |
# ctx.mark_rollback() |
|
53 |
# ... |
|
54 |
# return http response |
|
55 |
|
|
56 |
def notification_transaction_context(**kwargs): |
|
57 |
return TransactionHandler(ctx=NotificationTransactionContext, **kwargs) |
|
58 |
|
|
59 |
class NotificationTransactionContext(TransactionContext): |
|
60 |
def __init__(self, notify=True, **kwargs): |
|
61 |
self._notifications = [] |
|
62 |
self._messages = [] |
|
63 |
self._notify = notify |
|
64 |
TransactionContext.__init__(self, **kwargs) |
|
65 |
|
|
66 |
def register(self, o): |
|
67 |
if isinstance(o, dict): |
|
68 |
msg = o.get('msg', None) |
|
69 |
if msg is not None and request is not None: |
|
70 |
if isinstance(msg, basestring): |
|
71 |
self.queue_message(msg) |
|
72 |
|
|
73 |
notif = o.get('notif', None) |
|
74 |
fst, snd = o |
|
75 |
if isinstance(snd, Notification): |
|
76 |
self.queue_notification(snd) |
|
77 |
return fst |
|
78 |
return o |
|
79 |
|
|
80 |
def queue_message(m): |
|
81 |
self._messages.append(m) |
|
82 |
|
|
83 |
def queue_notification(self, n): |
|
84 |
self._notifications.append(n) |
|
85 |
|
|
86 |
def _send_notifications(self): |
|
87 |
if self._notifications is None: |
|
88 |
return |
|
89 |
# send mail |
|
90 |
|
|
91 |
def postprocess(self): |
|
92 |
if self._notify: |
|
93 |
self._send_notifications() |
|
94 |
TransactionContext.postprocess(self) |
b/snf-astakos-app/astakos/im/project_xctx.py | ||
---|---|---|
1 |
# Copyright 2013 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from synnefo.lib.db.xctx import TransactionHandler |
|
35 |
from astakos.im.notification_xctx import NotificationTransactionContext |
|
36 |
from astakos.im.models import sync_projects |
|
37 |
|
|
38 |
# USAGE |
|
39 |
# ===== |
|
40 |
# @project_transaction_context(sync=True) |
|
41 |
# def a_view(args, ctx=None): |
|
42 |
# ... |
|
43 |
# if ctx: |
|
44 |
# ctx.mark_rollback() |
|
45 |
# ... |
|
46 |
# return http response |
|
47 |
# |
|
48 |
# OR |
|
49 |
# |
|
50 |
# def a_view(args): |
|
51 |
# with project_transaction_context(sync=True) as ctx: |
|
52 |
# ... |
|
53 |
# ctx.mark_rollback() |
|
54 |
# ... |
|
55 |
# return http response |
|
56 |
|
|
57 |
def project_transaction_context(**kwargs): |
|
58 |
return TransactionHandler(ctx=ProjectTransactionContext, **kwargs) |
|
59 |
|
|
60 |
class ProjectTransactionContext(NotificationTransactionContext): |
|
61 |
def __init__(self, sync=False, **kwargs): |
|
62 |
self._sync = sync |
|
63 |
NotificationTransactionContext.__init__(self, **kwargs) |
|
64 |
|
|
65 |
def postprocess(self): |
|
66 |
if self._sync: |
|
67 |
sync_projects() |
|
68 |
NotificationTransactionContext.postprocess(self) |
b/snf-astakos-app/astakos/im/views.py | ||
---|---|---|
108 | 108 |
from astakos.im import settings as astakos_settings |
109 | 109 |
from astakos.im.api.callpoint import AstakosCallpoint |
110 | 110 |
from astakos.im import auth_providers |
111 |
from astakos.im.project_xctx import project_transaction_context |
|
111 | 112 |
|
112 | 113 |
logger = logging.getLogger(__name__) |
113 | 114 |
|
... | ... | |
913 | 914 |
'im/how_it_works.html', |
914 | 915 |
context_instance=get_context(request)) |
915 | 916 |
|
916 |
@transaction.commit_manually
|
|
917 |
@project_transaction_context()
|
|
917 | 918 |
def _create_object(request, model=None, template_name=None, |
918 | 919 |
template_loader=template_loader, extra_context=None, post_save_redirect=None, |
919 | 920 |
login_required=False, context_processors=None, form_class=None, |
920 |
msg=None): |
|
921 |
msg=None, ctx=None):
|
|
921 | 922 |
""" |
922 | 923 |
Based of django.views.generic.create_update.create_object which displays a |
923 | 924 |
summary page before creating the object. |
924 | 925 |
""" |
925 |
rollback = False |
|
926 | 926 |
response = None |
927 | 927 |
|
928 | 928 |
if extra_context is None: extra_context = {} |
... | ... | |
954 | 954 |
except BaseException, e: |
955 | 955 |
logger.exception(e) |
956 | 956 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
957 |
rollback = True |
|
957 |
if ctx: |
|
958 |
ctx.mark_rollback() |
|
958 | 959 |
finally: |
959 |
if rollback: |
|
960 |
transaction.rollback() |
|
961 |
else: |
|
962 |
transaction.commit() |
|
963 |
|
|
964 | 960 |
if response == None: |
965 | 961 |
# Create the template, context, response |
966 | 962 |
if not template_name: |
... | ... | |
974 | 970 |
response = HttpResponse(t.render(c)) |
975 | 971 |
return response |
976 | 972 |
|
977 |
@transaction.commit_manually
|
|
973 |
@project_transaction_context()
|
|
978 | 974 |
def _update_object(request, model=None, object_id=None, slug=None, |
979 | 975 |
slug_field='slug', template_name=None, template_loader=template_loader, |
980 | 976 |
extra_context=None, post_save_redirect=None, login_required=False, |
981 | 977 |
context_processors=None, template_object_name='object', |
982 |
form_class=None, msg=None): |
|
978 |
form_class=None, msg=None, ctx=None):
|
|
983 | 979 |
""" |
984 | 980 |
Based of django.views.generic.create_update.update_object which displays a |
985 | 981 |
summary page before updating the object. |
986 | 982 |
""" |
987 |
rollback = False |
|
988 | 983 |
response = None |
989 | 984 |
|
990 | 985 |
if extra_context is None: extra_context = {} |
... | ... | |
1017 | 1012 |
except BaseException, e: |
1018 | 1013 |
logger.exception(e) |
1019 | 1014 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1020 |
rollback = True
|
|
1015 |
ctx.mark_rollback()
|
|
1021 | 1016 |
finally: |
1022 |
if rollback: |
|
1023 |
transaction.rollback() |
|
1024 |
else: |
|
1025 |
transaction.commit() |
|
1026 | 1017 |
if response == None: |
1027 | 1018 |
if not template_name: |
1028 | 1019 |
template_name = "%s/%s_form.html" %\ |
... | ... | |
1132 | 1123 |
@require_http_methods(["GET", "POST"]) |
1133 | 1124 |
@signed_terms_required |
1134 | 1125 |
@login_required |
1135 |
@transaction.commit_on_success |
|
1136 | 1126 |
def project_app(request, application_id): |
1137 | 1127 |
return common_detail(request, application_id, is_chain=False) |
1138 | 1128 |
|
1139 | 1129 |
@require_http_methods(["GET", "POST"]) |
1140 | 1130 |
@signed_terms_required |
1141 | 1131 |
@login_required |
1142 |
@transaction.commit_on_success |
|
1143 | 1132 |
def project_detail(request, chain_id): |
1144 | 1133 |
return common_detail(request, chain_id) |
1145 | 1134 |
|
1146 |
def addmembers(request, chain_id): |
|
1135 |
@project_transaction_context(sync=True) |
|
1136 |
def addmembers(request, chain_id, ctx=None): |
|
1147 | 1137 |
addmembers_form = AddProjectMembersForm( |
1148 | 1138 |
request.POST, |
1149 | 1139 |
chain_id=int(chain_id), |
1150 | 1140 |
request_user=request.user) |
1151 | 1141 |
if addmembers_form.is_valid(): |
1152 | 1142 |
try: |
1153 |
rollback = False |
|
1154 | 1143 |
chain_id = int(chain_id) |
1155 | 1144 |
map(lambda u: enroll_member( |
1156 | 1145 |
chain_id, |
... | ... | |
1160 | 1149 |
except (IOError, PermissionDenied), e: |
1161 | 1150 |
messages.error(request, e) |
1162 | 1151 |
except BaseException, e: |
1163 |
rollback = True |
|
1152 |
if ctx: |
|
1153 |
ctx.mark_rollback() |
|
1164 | 1154 |
messages.error(request, e) |
1165 |
finally: |
|
1166 |
if rollback == True: |
|
1167 |
transaction.rollback() |
|
1168 |
else: |
|
1169 |
transaction.commit() |
|
1170 | 1155 |
|
1171 | 1156 |
def common_detail(request, chain_or_app_id, is_chain=True): |
1172 | 1157 |
if is_chain: |
... | ... | |
1265 | 1250 |
@require_http_methods(["POST", "GET"]) |
1266 | 1251 |
@signed_terms_required |
1267 | 1252 |
@login_required |
1268 |
@transaction.commit_manually
|
|
1269 |
def project_join(request, chain_id): |
|
1253 |
@project_transaction_context(sync=True)
|
|
1254 |
def project_join(request, chain_id, ctx=None):
|
|
1270 | 1255 |
next = request.GET.get('next') |
1271 | 1256 |
if not next: |
1272 | 1257 |
next = reverse('astakos.im.views.project_detail', |
1273 | 1258 |
args=(chain_id,)) |
1274 | 1259 |
|
1275 |
rollback = False |
|
1276 | 1260 |
try: |
1277 | 1261 |
chain_id = int(chain_id) |
1278 | 1262 |
join_project(chain_id, request.user) |
... | ... | |
1283 | 1267 |
except BaseException, e: |
1284 | 1268 |
logger.exception(e) |
1285 | 1269 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1286 |
rollback = True |
|
1287 |
finally: |
|
1288 |
if rollback: |
|
1289 |
transaction.rollback() |
|
1290 |
else: |
|
1291 |
transaction.commit() |
|
1270 |
if ctx: |
|
1271 |
ctx.mark_rollback() |
|
1292 | 1272 |
next = restrict_next(next, domain=COOKIE_DOMAIN) |
1293 | 1273 |
return redirect(next) |
1294 | 1274 |
|
1295 | 1275 |
@require_http_methods(["POST"]) |
1296 | 1276 |
@signed_terms_required |
1297 | 1277 |
@login_required |
1298 |
@transaction.commit_manually
|
|
1299 |
def project_leave(request, chain_id): |
|
1278 |
@project_transaction_context(sync=True)
|
|
1279 |
def project_leave(request, chain_id, ctx=None):
|
|
1300 | 1280 |
next = request.GET.get('next') |
1301 | 1281 |
if not next: |
1302 | 1282 |
next = reverse('astakos.im.views.project_list') |
1303 | 1283 |
|
1304 |
rollback = False |
|
1305 | 1284 |
try: |
1306 | 1285 |
chain_id = int(chain_id) |
1307 | 1286 |
leave_project(chain_id, request.user) |
... | ... | |
1310 | 1289 |
except BaseException, e: |
1311 | 1290 |
logger.exception(e) |
1312 | 1291 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1313 |
rollback = True |
|
1314 |
finally: |
|
1315 |
if rollback: |
|
1316 |
transaction.rollback() |
|
1317 |
else: |
|
1318 |
transaction.commit() |
|
1319 |
|
|
1292 |
if ctx: |
|
1293 |
ctx.mark_rollback() |
|
1320 | 1294 |
next = restrict_next(next, domain=COOKIE_DOMAIN) |
1321 | 1295 |
return redirect(next) |
1322 | 1296 |
|
1323 | 1297 |
@require_http_methods(["POST"]) |
1324 | 1298 |
@signed_terms_required |
1325 | 1299 |
@login_required |
1326 |
@transaction.commit_manually
|
|
1327 |
def project_cancel(request, chain_id): |
|
1300 |
@project_transaction_context()
|
|
1301 |
def project_cancel(request, chain_id, ctx=None):
|
|
1328 | 1302 |
next = request.GET.get('next') |
1329 | 1303 |
if not next: |
1330 | 1304 |
next = reverse('astakos.im.views.project_list') |
1331 | 1305 |
|
1332 |
rollback = False |
|
1333 | 1306 |
try: |
1334 | 1307 |
chain_id = int(chain_id) |
1335 | 1308 |
cancel_membership(chain_id, request.user) |
... | ... | |
1338 | 1311 |
except BaseException, e: |
1339 | 1312 |
logger.exception(e) |
1340 | 1313 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1341 |
rollback = True |
|
1342 |
finally: |
|
1343 |
if rollback: |
|
1344 |
transaction.rollback() |
|
1345 |
else: |
|
1346 |
transaction.commit() |
|
1314 |
if ctx: |
|
1315 |
ctx.mark_rollback() |
|
1347 | 1316 |
|
1348 | 1317 |
next = restrict_next(next, domain=COOKIE_DOMAIN) |
1349 | 1318 |
return redirect(next) |
... | ... | |
1351 | 1320 |
@require_http_methods(["POST"]) |
1352 | 1321 |
@signed_terms_required |
1353 | 1322 |
@login_required |
1354 |
@transaction.commit_manually |
|
1355 |
def project_accept_member(request, chain_id, user_id): |
|
1356 |
rollback = False |
|
1323 |
@project_transaction_context(sync=True) |
|
1324 |
def project_accept_member(request, chain_id, user_id, ctx=None): |
|
1357 | 1325 |
try: |
1358 | 1326 |
chain_id = int(chain_id) |
1359 | 1327 |
user_id = int(user_id) |
... | ... | |
1363 | 1331 |
except BaseException, e: |
1364 | 1332 |
logger.exception(e) |
1365 | 1333 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1366 |
rollback = True |
|
1334 |
if ctx: |
|
1335 |
ctx.mark_rollback() |
|
1367 | 1336 |
else: |
1368 | 1337 |
realname = m.person.realname |
1369 | 1338 |
msg = _(astakos_messages.USER_JOINED_PROJECT) % locals() |
1370 | 1339 |
messages.success(request, msg) |
1371 |
finally: |
|
1372 |
if rollback: |
|
1373 |
transaction.rollback() |
|
1374 |
else: |
|
1375 |
transaction.commit() |
|
1376 | 1340 |
return redirect(reverse('project_detail', args=(chain_id,))) |
1377 | 1341 |
|
1378 | 1342 |
@require_http_methods(["POST"]) |
1379 | 1343 |
@signed_terms_required |
1380 | 1344 |
@login_required |
1381 |
@transaction.commit_manually |
|
1382 |
def project_remove_member(request, chain_id, user_id): |
|
1383 |
rollback = False |
|
1345 |
@project_transaction_context(sync=True) |
|
1346 |
def project_remove_member(request, chain_id, user_id, ctx=None): |
|
1384 | 1347 |
try: |
1385 | 1348 |
chain_id = int(chain_id) |
1386 | 1349 |
user_id = int(user_id) |
... | ... | |
1390 | 1353 |
except BaseException, e: |
1391 | 1354 |
logger.exception(e) |
1392 | 1355 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1393 |
rollback = True |
|
1356 |
if ctx: |
|
1357 |
ctx.mark_rollback() |
|
1394 | 1358 |
else: |
1395 | 1359 |
realname = m.person.realname |
1396 | 1360 |
msg = _(astakos_messages.USER_LEFT_PROJECT) % locals() |
1397 | 1361 |
messages.success(request, msg) |
1398 |
finally: |
|
1399 |
if rollback: |
|
1400 |
transaction.rollback() |
|
1401 |
else: |
|
1402 |
transaction.commit() |
|
1403 | 1362 |
return redirect(reverse('project_detail', args=(chain_id,))) |
1404 | 1363 |
|
1405 | 1364 |
@require_http_methods(["POST"]) |
1406 | 1365 |
@signed_terms_required |
1407 | 1366 |
@login_required |
1408 |
@transaction.commit_manually |
|
1409 |
def project_reject_member(request, chain_id, user_id): |
|
1410 |
rollback = False |
|
1367 |
@project_transaction_context() |
|
1368 |
def project_reject_member(request, chain_id, user_id, ctx=None): |
|
1411 | 1369 |
try: |
1412 | 1370 |
chain_id = int(chain_id) |
1413 | 1371 |
user_id = int(user_id) |
... | ... | |
1417 | 1375 |
except BaseException, e: |
1418 | 1376 |
logger.exception(e) |
1419 | 1377 |
messages.error(request, _(astakos_messages.GENERIC_ERROR)) |
1420 |
rollback = True |
|
1378 |
if ctx: |
|
1379 |
ctx.mark_rollback() |
|
1421 | 1380 |
else: |
1422 | 1381 |
realname = m.person.realname |
1423 | 1382 |
msg = _(astakos_messages.USER_LEFT_PROJECT) % locals() |
1424 | 1383 |
messages.success(request, msg) |
1425 |
finally: |
|
1426 |
if rollback: |
|
1427 |
transaction.rollback() |
|
1428 |
else: |
|
1429 |
transaction.commit() |
|
1430 | 1384 |
return redirect(reverse('project_detail', args=(chain_id,))) |
1431 | 1385 |
|
1432 | 1386 |
def landing(request): |
Also available in: Unified diff