Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / projects.py @ 2556cf45

History | View | Annotate | Download (20.6 kB)

1 2556cf45 Giorgos Korfiatis
# Copyright 2013 GRNET S.A. All rights reserved.
2 2556cf45 Giorgos Korfiatis
#
3 2556cf45 Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or
4 2556cf45 Giorgos Korfiatis
# without modification, are permitted provided that the following
5 2556cf45 Giorgos Korfiatis
# conditions are met:
6 2556cf45 Giorgos Korfiatis
#
7 2556cf45 Giorgos Korfiatis
#   1. Redistributions of source code must retain the above
8 2556cf45 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
9 2556cf45 Giorgos Korfiatis
#      disclaimer.
10 2556cf45 Giorgos Korfiatis
#
11 2556cf45 Giorgos Korfiatis
#   2. Redistributions in binary form must reproduce the above
12 2556cf45 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
13 2556cf45 Giorgos Korfiatis
#      disclaimer in the documentation and/or other materials
14 2556cf45 Giorgos Korfiatis
#      provided with the distribution.
15 2556cf45 Giorgos Korfiatis
#
16 2556cf45 Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 2556cf45 Giorgos Korfiatis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 2556cf45 Giorgos Korfiatis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 2556cf45 Giorgos Korfiatis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 2556cf45 Giorgos Korfiatis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 2556cf45 Giorgos Korfiatis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 2556cf45 Giorgos Korfiatis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 2556cf45 Giorgos Korfiatis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 2556cf45 Giorgos Korfiatis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 2556cf45 Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 2556cf45 Giorgos Korfiatis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 2556cf45 Giorgos Korfiatis
# POSSIBILITY OF SUCH DAMAGE.
28 2556cf45 Giorgos Korfiatis
#
29 2556cf45 Giorgos Korfiatis
# The views and conclusions contained in the software and
30 2556cf45 Giorgos Korfiatis
# documentation are those of the authors and should not be
31 2556cf45 Giorgos Korfiatis
# interpreted as representing official policies, either expressed
32 2556cf45 Giorgos Korfiatis
# or implied, of GRNET S.A.
33 2556cf45 Giorgos Korfiatis
34 2556cf45 Giorgos Korfiatis
from django.utils import simplejson as json
35 2556cf45 Giorgos Korfiatis
from django.views.decorators.csrf import csrf_exempt
36 2556cf45 Giorgos Korfiatis
from django.http import HttpResponse
37 2556cf45 Giorgos Korfiatis
from django.db.models import Q
38 2556cf45 Giorgos Korfiatis
39 2556cf45 Giorgos Korfiatis
from snf_django.lib.db.transaction import commit_on_success_strict
40 2556cf45 Giorgos Korfiatis
from astakos.api.util import json_response
41 2556cf45 Giorgos Korfiatis
42 2556cf45 Giorgos Korfiatis
from snf_django.lib import api
43 2556cf45 Giorgos Korfiatis
from snf_django.lib.api import faults
44 2556cf45 Giorgos Korfiatis
from .util import user_from_token, invert_dict, read_json_body
45 2556cf45 Giorgos Korfiatis
46 2556cf45 Giorgos Korfiatis
from astakos.im import functions
47 2556cf45 Giorgos Korfiatis
from astakos.im.models import (
48 2556cf45 Giorgos Korfiatis
    AstakosUser, Project, ProjectApplication, ProjectMembership,
49 2556cf45 Giorgos Korfiatis
    ProjectResourceGrant, ProjectLog, ProjectMembershipLog)
50 2556cf45 Giorgos Korfiatis
import synnefo.util.date as date_util
51 2556cf45 Giorgos Korfiatis
52 2556cf45 Giorgos Korfiatis
53 2556cf45 Giorgos Korfiatis
MEMBERSHIP_POLICY_SHOW = {
54 2556cf45 Giorgos Korfiatis
    functions.AUTO_ACCEPT_POLICY: "auto",
55 2556cf45 Giorgos Korfiatis
    functions.MODERATED_POLICY:   "moderated",
56 2556cf45 Giorgos Korfiatis
    functions.CLOSED_POLICY:      "closed",
57 2556cf45 Giorgos Korfiatis
}
58 2556cf45 Giorgos Korfiatis
59 2556cf45 Giorgos Korfiatis
MEMBERSHIP_POLICY = invert_dict(MEMBERSHIP_POLICY_SHOW)
60 2556cf45 Giorgos Korfiatis
61 2556cf45 Giorgos Korfiatis
APPLICATION_STATE_SHOW = {
62 2556cf45 Giorgos Korfiatis
    ProjectApplication.PENDING:   "pending",
63 2556cf45 Giorgos Korfiatis
    ProjectApplication.APPROVED:  "approved",
64 2556cf45 Giorgos Korfiatis
    ProjectApplication.REPLACED:  "replaced",
65 2556cf45 Giorgos Korfiatis
    ProjectApplication.DENIED:    "denied",
66 2556cf45 Giorgos Korfiatis
    ProjectApplication.DISMISSED: "dismissed",
67 2556cf45 Giorgos Korfiatis
    ProjectApplication.CANCELLED: "cancelled",
68 2556cf45 Giorgos Korfiatis
}
69 2556cf45 Giorgos Korfiatis
70 2556cf45 Giorgos Korfiatis
PROJECT_STATE_SHOW = {
71 2556cf45 Giorgos Korfiatis
    Project.O_PENDING:    "pending",
72 2556cf45 Giorgos Korfiatis
    Project.O_ACTIVE:     "active",
73 2556cf45 Giorgos Korfiatis
    Project.O_DENIED:     "denied",
74 2556cf45 Giorgos Korfiatis
    Project.O_DISMISSED:  "dismissed",
75 2556cf45 Giorgos Korfiatis
    Project.O_CANCELLED:  "cancelled",
76 2556cf45 Giorgos Korfiatis
    Project.O_SUSPENDED:  "suspended",
77 2556cf45 Giorgos Korfiatis
    Project.O_TERMINATED: "terminated",
78 2556cf45 Giorgos Korfiatis
}
79 2556cf45 Giorgos Korfiatis
80 2556cf45 Giorgos Korfiatis
PROJECT_STATE = invert_dict(PROJECT_STATE_SHOW)
81 2556cf45 Giorgos Korfiatis
82 2556cf45 Giorgos Korfiatis
MEMBERSHIP_STATE_SHOW = {
83 2556cf45 Giorgos Korfiatis
    ProjectMembership.REQUESTED:       "requested",
84 2556cf45 Giorgos Korfiatis
    ProjectMembership.ACCEPTED:        "accepted",
85 2556cf45 Giorgos Korfiatis
    ProjectMembership.LEAVE_REQUESTED: "leave_requested",
86 2556cf45 Giorgos Korfiatis
    ProjectMembership.USER_SUSPENDED:  "suspended",
87 2556cf45 Giorgos Korfiatis
    ProjectMembership.REJECTED:        "rejected",
88 2556cf45 Giorgos Korfiatis
    ProjectMembership.CANCELLED:       "cancelled",
89 2556cf45 Giorgos Korfiatis
    ProjectMembership.REMOVED:         "removed",
90 2556cf45 Giorgos Korfiatis
}
91 2556cf45 Giorgos Korfiatis
92 2556cf45 Giorgos Korfiatis
93 2556cf45 Giorgos Korfiatis
def _application_details(application, all_grants):
94 2556cf45 Giorgos Korfiatis
    grants = all_grants.get(application.id, [])
95 2556cf45 Giorgos Korfiatis
    resources = {}
96 2556cf45 Giorgos Korfiatis
    for grant in grants:
97 2556cf45 Giorgos Korfiatis
        resources[grant.resource.name] = {
98 2556cf45 Giorgos Korfiatis
            "member_capacity": grant.member_capacity,
99 2556cf45 Giorgos Korfiatis
            "project_capacity": grant.project_capacity,
100 2556cf45 Giorgos Korfiatis
        }
101 2556cf45 Giorgos Korfiatis
102 2556cf45 Giorgos Korfiatis
    join_policy = MEMBERSHIP_POLICY_SHOW[application.member_join_policy]
103 2556cf45 Giorgos Korfiatis
    leave_policy = MEMBERSHIP_POLICY_SHOW[application.member_leave_policy]
104 2556cf45 Giorgos Korfiatis
105 2556cf45 Giorgos Korfiatis
    d = {
106 2556cf45 Giorgos Korfiatis
        "name": application.name,
107 2556cf45 Giorgos Korfiatis
        "owner": application.owner.uuid,
108 2556cf45 Giorgos Korfiatis
        "applicant": application.applicant.uuid,
109 2556cf45 Giorgos Korfiatis
        "homepage": application.homepage,
110 2556cf45 Giorgos Korfiatis
        "description": application.description,
111 2556cf45 Giorgos Korfiatis
        "start_date": application.start_date,
112 2556cf45 Giorgos Korfiatis
        "end_date": application.end_date,
113 2556cf45 Giorgos Korfiatis
        "join_policy": join_policy,
114 2556cf45 Giorgos Korfiatis
        "leave_policy": leave_policy,
115 2556cf45 Giorgos Korfiatis
        "max_members": application.limit_on_members_number,
116 2556cf45 Giorgos Korfiatis
        "resources": resources,
117 2556cf45 Giorgos Korfiatis
    }
118 2556cf45 Giorgos Korfiatis
    return d
119 2556cf45 Giorgos Korfiatis
120 2556cf45 Giorgos Korfiatis
121 2556cf45 Giorgos Korfiatis
def get_applications_details(applications):
122 2556cf45 Giorgos Korfiatis
    grants = ProjectResourceGrant.objects.grants_per_app(applications)
123 2556cf45 Giorgos Korfiatis
124 2556cf45 Giorgos Korfiatis
    l = []
125 2556cf45 Giorgos Korfiatis
    for application in applications:
126 2556cf45 Giorgos Korfiatis
        d = {
127 2556cf45 Giorgos Korfiatis
            "id": application.id,
128 2556cf45 Giorgos Korfiatis
            "project": application.chain_id,
129 2556cf45 Giorgos Korfiatis
            "state": APPLICATION_STATE_SHOW[application.state],
130 2556cf45 Giorgos Korfiatis
            "comments": application.comments,
131 2556cf45 Giorgos Korfiatis
        }
132 2556cf45 Giorgos Korfiatis
        d.update(_application_details(application, grants))
133 2556cf45 Giorgos Korfiatis
        l.append(d)
134 2556cf45 Giorgos Korfiatis
    return l
135 2556cf45 Giorgos Korfiatis
136 2556cf45 Giorgos Korfiatis
137 2556cf45 Giorgos Korfiatis
def get_application_details(application):
138 2556cf45 Giorgos Korfiatis
    return get_applications_details([application])[0]
139 2556cf45 Giorgos Korfiatis
140 2556cf45 Giorgos Korfiatis
141 2556cf45 Giorgos Korfiatis
def get_projects_details(projects, request_user=None):
142 2556cf45 Giorgos Korfiatis
    pendings = ProjectApplication.objects.pending_per_project(projects)
143 2556cf45 Giorgos Korfiatis
    applications = [p.application for p in projects]
144 2556cf45 Giorgos Korfiatis
    grants = ProjectResourceGrant.objects.grants_per_app(applications)
145 2556cf45 Giorgos Korfiatis
    deactivations = ProjectLog.objects.last_deactivations(projects)
146 2556cf45 Giorgos Korfiatis
147 2556cf45 Giorgos Korfiatis
    l = []
148 2556cf45 Giorgos Korfiatis
    for project in projects:
149 2556cf45 Giorgos Korfiatis
        application = project.application
150 2556cf45 Giorgos Korfiatis
        d = {
151 2556cf45 Giorgos Korfiatis
            "id": project.id,
152 2556cf45 Giorgos Korfiatis
            "application": application.id,
153 2556cf45 Giorgos Korfiatis
            "state": PROJECT_STATE_SHOW[project.overall_state()],
154 2556cf45 Giorgos Korfiatis
            "creation_date": project.creation_date,
155 2556cf45 Giorgos Korfiatis
        }
156 2556cf45 Giorgos Korfiatis
        check = functions.project_check_allowed
157 2556cf45 Giorgos Korfiatis
        if check(project, request_user,
158 2556cf45 Giorgos Korfiatis
                 level=functions.APPLICANT_LEVEL, silent=True):
159 2556cf45 Giorgos Korfiatis
            d["comments"] = application.comments
160 2556cf45 Giorgos Korfiatis
            pending = pendings.get(project.id)
161 2556cf45 Giorgos Korfiatis
            d["pending_application"] = pending.id if pending else None
162 2556cf45 Giorgos Korfiatis
            deact = deactivations.get(project.id)
163 2556cf45 Giorgos Korfiatis
            if deact is not None:
164 2556cf45 Giorgos Korfiatis
                d["deactivation_date"] = deact.date
165 2556cf45 Giorgos Korfiatis
        d.update(_application_details(application, grants))
166 2556cf45 Giorgos Korfiatis
        l.append(d)
167 2556cf45 Giorgos Korfiatis
    return l
168 2556cf45 Giorgos Korfiatis
169 2556cf45 Giorgos Korfiatis
170 2556cf45 Giorgos Korfiatis
def get_project_details(project, request_user=None):
171 2556cf45 Giorgos Korfiatis
    return get_projects_details([project], request_user=request_user)[0]
172 2556cf45 Giorgos Korfiatis
173 2556cf45 Giorgos Korfiatis
174 2556cf45 Giorgos Korfiatis
def get_memberships_details(memberships, request_user):
175 2556cf45 Giorgos Korfiatis
    all_logs = ProjectMembershipLog.objects.last_logs(memberships)
176 2556cf45 Giorgos Korfiatis
177 2556cf45 Giorgos Korfiatis
    l = []
178 2556cf45 Giorgos Korfiatis
    for membership in memberships:
179 2556cf45 Giorgos Korfiatis
        logs = all_logs.get(membership.id, {})
180 2556cf45 Giorgos Korfiatis
        dates = {}
181 2556cf45 Giorgos Korfiatis
        for s, log in logs.iteritems():
182 2556cf45 Giorgos Korfiatis
            dates[MEMBERSHIP_STATE_SHOW[s]] = log.date
183 2556cf45 Giorgos Korfiatis
184 2556cf45 Giorgos Korfiatis
        allowed_actions = functions.membership_allowed_actions(
185 2556cf45 Giorgos Korfiatis
            membership, request_user)
186 2556cf45 Giorgos Korfiatis
        d = {
187 2556cf45 Giorgos Korfiatis
            "id": membership.id,
188 2556cf45 Giorgos Korfiatis
            "user": membership.person.uuid,
189 2556cf45 Giorgos Korfiatis
            "project": membership.project_id,
190 2556cf45 Giorgos Korfiatis
            "state": MEMBERSHIP_STATE_SHOW[membership.state],
191 2556cf45 Giorgos Korfiatis
            "allowed_actions": allowed_actions,
192 2556cf45 Giorgos Korfiatis
        }
193 2556cf45 Giorgos Korfiatis
        d.update(dates)
194 2556cf45 Giorgos Korfiatis
        l.append(d)
195 2556cf45 Giorgos Korfiatis
    return l
196 2556cf45 Giorgos Korfiatis
197 2556cf45 Giorgos Korfiatis
198 2556cf45 Giorgos Korfiatis
def get_membership_details(membership, request_user):
199 2556cf45 Giorgos Korfiatis
    return get_memberships_details([membership], request_user)[0]
200 2556cf45 Giorgos Korfiatis
201 2556cf45 Giorgos Korfiatis
202 2556cf45 Giorgos Korfiatis
def _query(attr):
203 2556cf45 Giorgos Korfiatis
    def inner(val):
204 2556cf45 Giorgos Korfiatis
        kw = attr + "__in" if isinstance(val, list) else attr
205 2556cf45 Giorgos Korfiatis
        return Q(**{kw: val})
206 2556cf45 Giorgos Korfiatis
    return inner
207 2556cf45 Giorgos Korfiatis
208 2556cf45 Giorgos Korfiatis
209 2556cf45 Giorgos Korfiatis
def _get_project_state(val):
210 2556cf45 Giorgos Korfiatis
    try:
211 2556cf45 Giorgos Korfiatis
        return PROJECT_STATE[val]
212 2556cf45 Giorgos Korfiatis
    except KeyError:
213 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Unrecognized state %s" % val)
214 2556cf45 Giorgos Korfiatis
215 2556cf45 Giorgos Korfiatis
216 2556cf45 Giorgos Korfiatis
def _project_state_query(val):
217 2556cf45 Giorgos Korfiatis
    if isinstance(val, list):
218 2556cf45 Giorgos Korfiatis
        states = [_get_project_state(v) for v in val]
219 2556cf45 Giorgos Korfiatis
        return Project.o_states_q(states)
220 2556cf45 Giorgos Korfiatis
    return Project.o_state_q(_get_project_state(val))
221 2556cf45 Giorgos Korfiatis
222 2556cf45 Giorgos Korfiatis
223 2556cf45 Giorgos Korfiatis
PROJECT_QUERY = {
224 2556cf45 Giorgos Korfiatis
    "name": _query("application__name"),
225 2556cf45 Giorgos Korfiatis
    "owner": _query("application__owner__uuid"),
226 2556cf45 Giorgos Korfiatis
    "state": _project_state_query,
227 2556cf45 Giorgos Korfiatis
}
228 2556cf45 Giorgos Korfiatis
229 2556cf45 Giorgos Korfiatis
230 2556cf45 Giorgos Korfiatis
def make_project_query(filters):
231 2556cf45 Giorgos Korfiatis
    qs = Q()
232 2556cf45 Giorgos Korfiatis
    for attr, val in filters.iteritems():
233 2556cf45 Giorgos Korfiatis
        try:
234 2556cf45 Giorgos Korfiatis
            _q = PROJECT_QUERY[attr]
235 2556cf45 Giorgos Korfiatis
        except KeyError:
236 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("Unrecognized filter %s" % attr)
237 2556cf45 Giorgos Korfiatis
        qs &= _q(val)
238 2556cf45 Giorgos Korfiatis
    return qs
239 2556cf45 Giorgos Korfiatis
240 2556cf45 Giorgos Korfiatis
241 2556cf45 Giorgos Korfiatis
class ExceptionHandler(object):
242 2556cf45 Giorgos Korfiatis
    def __enter__(self):
243 2556cf45 Giorgos Korfiatis
        pass
244 2556cf45 Giorgos Korfiatis
245 2556cf45 Giorgos Korfiatis
    EXCS = {
246 2556cf45 Giorgos Korfiatis
        functions.ProjectNotFound:   faults.ItemNotFound,
247 2556cf45 Giorgos Korfiatis
        functions.ProjectForbidden:  faults.Forbidden,
248 2556cf45 Giorgos Korfiatis
        functions.ProjectBadRequest: faults.BadRequest,
249 2556cf45 Giorgos Korfiatis
        functions.ProjectConflict:   faults.Conflict,
250 2556cf45 Giorgos Korfiatis
    }
251 2556cf45 Giorgos Korfiatis
252 2556cf45 Giorgos Korfiatis
    def __exit__(self, exc_type, value, traceback):
253 2556cf45 Giorgos Korfiatis
        if value is not None:  # exception
254 2556cf45 Giorgos Korfiatis
            try:
255 2556cf45 Giorgos Korfiatis
                e = self.EXCS[exc_type]
256 2556cf45 Giorgos Korfiatis
            except KeyError:
257 2556cf45 Giorgos Korfiatis
                return False  # reraise
258 2556cf45 Giorgos Korfiatis
            raise e(value.message)
259 2556cf45 Giorgos Korfiatis
260 2556cf45 Giorgos Korfiatis
261 2556cf45 Giorgos Korfiatis
@csrf_exempt
262 2556cf45 Giorgos Korfiatis
def projects(request):
263 2556cf45 Giorgos Korfiatis
    method = request.method
264 2556cf45 Giorgos Korfiatis
    if method == "GET":
265 2556cf45 Giorgos Korfiatis
        return get_projects(request)
266 2556cf45 Giorgos Korfiatis
    elif method == "POST":
267 2556cf45 Giorgos Korfiatis
        return create_project(request)
268 2556cf45 Giorgos Korfiatis
    return api.api_method_not_allowed(request)
269 2556cf45 Giorgos Korfiatis
270 2556cf45 Giorgos Korfiatis
271 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
272 2556cf45 Giorgos Korfiatis
@user_from_token
273 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
274 2556cf45 Giorgos Korfiatis
def get_projects(request):
275 2556cf45 Giorgos Korfiatis
    user = request.user
276 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
277 2556cf45 Giorgos Korfiatis
    filters = input_data.get("filter", {})
278 2556cf45 Giorgos Korfiatis
    query = make_project_query(filters)
279 2556cf45 Giorgos Korfiatis
    projects = _get_projects(query, request_user=user)
280 2556cf45 Giorgos Korfiatis
    data = get_projects_details(projects, request_user=user)
281 2556cf45 Giorgos Korfiatis
    return json_response(data)
282 2556cf45 Giorgos Korfiatis
283 2556cf45 Giorgos Korfiatis
284 2556cf45 Giorgos Korfiatis
def _get_projects(query, request_user=None):
285 2556cf45 Giorgos Korfiatis
    projects = Project.objects.filter(query)
286 2556cf45 Giorgos Korfiatis
287 2556cf45 Giorgos Korfiatis
    if not request_user.is_project_admin():
288 2556cf45 Giorgos Korfiatis
        membs = request_user.projectmembership_set.any_accepted()
289 2556cf45 Giorgos Korfiatis
        memb_projects = membs.values_list("project", flat=True)
290 2556cf45 Giorgos Korfiatis
        is_memb = Q(id__in=memb_projects)
291 2556cf45 Giorgos Korfiatis
        owned = (Q(application__owner=request_user) |
292 2556cf45 Giorgos Korfiatis
                 Q(application__applicant=request_user))
293 2556cf45 Giorgos Korfiatis
        active = Project.o_state_q(Project.O_ACTIVE)
294 2556cf45 Giorgos Korfiatis
        projects = projects.filter(is_memb | owned | active)
295 2556cf45 Giorgos Korfiatis
    return projects.select_related(
296 2556cf45 Giorgos Korfiatis
        "application", "application__owner", "application__applicant")
297 2556cf45 Giorgos Korfiatis
298 2556cf45 Giorgos Korfiatis
299 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
300 2556cf45 Giorgos Korfiatis
@user_from_token
301 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
302 2556cf45 Giorgos Korfiatis
def create_project(request):
303 2556cf45 Giorgos Korfiatis
    user = request.user
304 2556cf45 Giorgos Korfiatis
    data = request.raw_post_data
305 2556cf45 Giorgos Korfiatis
    app_data = json.loads(data)
306 2556cf45 Giorgos Korfiatis
    return submit_application(app_data, user, project_id=None)
307 2556cf45 Giorgos Korfiatis
308 2556cf45 Giorgos Korfiatis
309 2556cf45 Giorgos Korfiatis
@csrf_exempt
310 2556cf45 Giorgos Korfiatis
def project(request, project_id):
311 2556cf45 Giorgos Korfiatis
    method = request.method
312 2556cf45 Giorgos Korfiatis
    if method == "GET":
313 2556cf45 Giorgos Korfiatis
        return get_project(request, project_id)
314 2556cf45 Giorgos Korfiatis
    if method == "POST":
315 2556cf45 Giorgos Korfiatis
        return modify_project(request, project_id)
316 2556cf45 Giorgos Korfiatis
    return api.api_method_not_allowed(request)
317 2556cf45 Giorgos Korfiatis
318 2556cf45 Giorgos Korfiatis
319 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
320 2556cf45 Giorgos Korfiatis
@user_from_token
321 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
322 2556cf45 Giorgos Korfiatis
def get_project(request, project_id):
323 2556cf45 Giorgos Korfiatis
    user = request.user
324 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
325 2556cf45 Giorgos Korfiatis
        project = _get_project(project_id, request_user=user)
326 2556cf45 Giorgos Korfiatis
    data = get_project_details(project, user)
327 2556cf45 Giorgos Korfiatis
    return json_response(data)
328 2556cf45 Giorgos Korfiatis
329 2556cf45 Giorgos Korfiatis
330 2556cf45 Giorgos Korfiatis
def _get_project(project_id, request_user=None):
331 2556cf45 Giorgos Korfiatis
    project = functions.get_project_by_id(project_id)
332 2556cf45 Giorgos Korfiatis
    functions.project_check_allowed(
333 2556cf45 Giorgos Korfiatis
        project, request_user, level=functions.ANY_LEVEL)
334 2556cf45 Giorgos Korfiatis
    return project
335 2556cf45 Giorgos Korfiatis
336 2556cf45 Giorgos Korfiatis
337 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
338 2556cf45 Giorgos Korfiatis
@user_from_token
339 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
340 2556cf45 Giorgos Korfiatis
def modify_project(request, project_id):
341 2556cf45 Giorgos Korfiatis
    user = request.user
342 2556cf45 Giorgos Korfiatis
    data = request.raw_post_data
343 2556cf45 Giorgos Korfiatis
    app_data = json.loads(data)
344 2556cf45 Giorgos Korfiatis
    return submit_application(app_data, user, project_id=project_id)
345 2556cf45 Giorgos Korfiatis
346 2556cf45 Giorgos Korfiatis
347 2556cf45 Giorgos Korfiatis
def _get_date(d, key):
348 2556cf45 Giorgos Korfiatis
    date_str = d.get(key)
349 2556cf45 Giorgos Korfiatis
    if date_str is not None:
350 2556cf45 Giorgos Korfiatis
        try:
351 2556cf45 Giorgos Korfiatis
            return date_util.isoparse(date_str)
352 2556cf45 Giorgos Korfiatis
        except:
353 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("Invalid %s" % key)
354 2556cf45 Giorgos Korfiatis
    else:
355 2556cf45 Giorgos Korfiatis
        return None
356 2556cf45 Giorgos Korfiatis
357 2556cf45 Giorgos Korfiatis
358 2556cf45 Giorgos Korfiatis
def _get_maybe_string(d, key):
359 2556cf45 Giorgos Korfiatis
    value = d.get(key)
360 2556cf45 Giorgos Korfiatis
    if value is not None and not isinstance(value, basestring):
361 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("%s must be string" % key)
362 2556cf45 Giorgos Korfiatis
    return value
363 2556cf45 Giorgos Korfiatis
364 2556cf45 Giorgos Korfiatis
365 2556cf45 Giorgos Korfiatis
def submit_application(app_data, user, project_id=None):
366 2556cf45 Giorgos Korfiatis
    uuid = app_data.get("owner")
367 2556cf45 Giorgos Korfiatis
    if uuid is None:
368 2556cf45 Giorgos Korfiatis
        owner = user
369 2556cf45 Giorgos Korfiatis
    else:
370 2556cf45 Giorgos Korfiatis
        try:
371 2556cf45 Giorgos Korfiatis
            owner = AstakosUser.objects.get(uuid=uuid, email_verified=True)
372 2556cf45 Giorgos Korfiatis
        except AstakosUser.DoesNotExist:
373 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("User does not exist.")
374 2556cf45 Giorgos Korfiatis
375 2556cf45 Giorgos Korfiatis
    try:
376 2556cf45 Giorgos Korfiatis
        name = app_data["name"]
377 2556cf45 Giorgos Korfiatis
    except KeyError:
378 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Name missing.")
379 2556cf45 Giorgos Korfiatis
380 2556cf45 Giorgos Korfiatis
    join_policy = app_data.get("join_policy", "moderated")
381 2556cf45 Giorgos Korfiatis
    try:
382 2556cf45 Giorgos Korfiatis
        join_policy = MEMBERSHIP_POLICY[join_policy]
383 2556cf45 Giorgos Korfiatis
    except KeyError:
384 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Invalid join policy")
385 2556cf45 Giorgos Korfiatis
386 2556cf45 Giorgos Korfiatis
    leave_policy = app_data.get("leave_policy", "auto")
387 2556cf45 Giorgos Korfiatis
    try:
388 2556cf45 Giorgos Korfiatis
        leave_policy = MEMBERSHIP_POLICY[leave_policy]
389 2556cf45 Giorgos Korfiatis
    except KeyError:
390 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Invalid leave policy")
391 2556cf45 Giorgos Korfiatis
392 2556cf45 Giorgos Korfiatis
    start_date = _get_date(app_data, "start_date")
393 2556cf45 Giorgos Korfiatis
    end_date = _get_date(app_data, "end_date")
394 2556cf45 Giorgos Korfiatis
395 2556cf45 Giorgos Korfiatis
    if end_date is None:
396 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Missing end date")
397 2556cf45 Giorgos Korfiatis
398 2556cf45 Giorgos Korfiatis
    max_members = app_data.get("max_members")
399 2556cf45 Giorgos Korfiatis
    if max_members is not None and \
400 2556cf45 Giorgos Korfiatis
            (not isinstance(max_members, (int, long)) or max_members < 0):
401 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Invalid max_members")
402 2556cf45 Giorgos Korfiatis
403 2556cf45 Giorgos Korfiatis
    homepage = _get_maybe_string(app_data, "homepage")
404 2556cf45 Giorgos Korfiatis
    description = _get_maybe_string(app_data, "description")
405 2556cf45 Giorgos Korfiatis
    comments = _get_maybe_string(app_data, "comments")
406 2556cf45 Giorgos Korfiatis
    resources = app_data.get("resources", {})
407 2556cf45 Giorgos Korfiatis
408 2556cf45 Giorgos Korfiatis
    submit = functions.submit_application
409 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
410 2556cf45 Giorgos Korfiatis
        application = submit(
411 2556cf45 Giorgos Korfiatis
            owner=owner,
412 2556cf45 Giorgos Korfiatis
            name=name,
413 2556cf45 Giorgos Korfiatis
            project_id=project_id,
414 2556cf45 Giorgos Korfiatis
            homepage=homepage,
415 2556cf45 Giorgos Korfiatis
            description=description,
416 2556cf45 Giorgos Korfiatis
            start_date=start_date,
417 2556cf45 Giorgos Korfiatis
            end_date=end_date,
418 2556cf45 Giorgos Korfiatis
            member_join_policy=join_policy,
419 2556cf45 Giorgos Korfiatis
            member_leave_policy=leave_policy,
420 2556cf45 Giorgos Korfiatis
            limit_on_members_number=max_members,
421 2556cf45 Giorgos Korfiatis
            comments=comments,
422 2556cf45 Giorgos Korfiatis
            resources=resources,
423 2556cf45 Giorgos Korfiatis
            request_user=user)
424 2556cf45 Giorgos Korfiatis
425 2556cf45 Giorgos Korfiatis
    result = {"application": application.id,
426 2556cf45 Giorgos Korfiatis
              "id": application.chain_id
427 2556cf45 Giorgos Korfiatis
              }
428 2556cf45 Giorgos Korfiatis
    return json_response(result, status_code=201)
429 2556cf45 Giorgos Korfiatis
430 2556cf45 Giorgos Korfiatis
431 2556cf45 Giorgos Korfiatis
def get_action(actions, input_data):
432 2556cf45 Giorgos Korfiatis
    action = None
433 2556cf45 Giorgos Korfiatis
    data = None
434 2556cf45 Giorgos Korfiatis
    for option in actions.keys():
435 2556cf45 Giorgos Korfiatis
        if option in input_data:
436 2556cf45 Giorgos Korfiatis
            if action:
437 2556cf45 Giorgos Korfiatis
                raise faults.BadRequest("Multiple actions not supported")
438 2556cf45 Giorgos Korfiatis
            else:
439 2556cf45 Giorgos Korfiatis
                action = option
440 2556cf45 Giorgos Korfiatis
                data = input_data[action]
441 2556cf45 Giorgos Korfiatis
    if not action:
442 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("No recognized action")
443 2556cf45 Giorgos Korfiatis
    return actions[action], data
444 2556cf45 Giorgos Korfiatis
445 2556cf45 Giorgos Korfiatis
446 2556cf45 Giorgos Korfiatis
PROJECT_ACTION = {
447 2556cf45 Giorgos Korfiatis
    "terminate": functions.terminate,
448 2556cf45 Giorgos Korfiatis
    "suspend":   functions.suspend,
449 2556cf45 Giorgos Korfiatis
    "unsuspend": functions.unsuspend,
450 2556cf45 Giorgos Korfiatis
    "reinstate": functions.reinstate,
451 2556cf45 Giorgos Korfiatis
}
452 2556cf45 Giorgos Korfiatis
453 2556cf45 Giorgos Korfiatis
454 2556cf45 Giorgos Korfiatis
@csrf_exempt
455 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
456 2556cf45 Giorgos Korfiatis
@user_from_token
457 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
458 2556cf45 Giorgos Korfiatis
def project_action(request, project_id):
459 2556cf45 Giorgos Korfiatis
    user = request.user
460 2556cf45 Giorgos Korfiatis
    data = request.raw_post_data
461 2556cf45 Giorgos Korfiatis
    input_data = json.loads(data)
462 2556cf45 Giorgos Korfiatis
463 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(PROJECT_ACTION, input_data)
464 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
465 2556cf45 Giorgos Korfiatis
        func(project_id, request_user=user, reason=action_data)
466 2556cf45 Giorgos Korfiatis
    return HttpResponse()
467 2556cf45 Giorgos Korfiatis
468 2556cf45 Giorgos Korfiatis
469 2556cf45 Giorgos Korfiatis
@csrf_exempt
470 2556cf45 Giorgos Korfiatis
def applications(request):
471 2556cf45 Giorgos Korfiatis
    method = request.method
472 2556cf45 Giorgos Korfiatis
    if method == "GET":
473 2556cf45 Giorgos Korfiatis
        return get_applications(request)
474 2556cf45 Giorgos Korfiatis
    return api.api_method_not_allowed(request)
475 2556cf45 Giorgos Korfiatis
476 2556cf45 Giorgos Korfiatis
477 2556cf45 Giorgos Korfiatis
def make_application_query(input_data):
478 2556cf45 Giorgos Korfiatis
    project_id = input_data.get("project")
479 2556cf45 Giorgos Korfiatis
    if project_id is not None:
480 2556cf45 Giorgos Korfiatis
        if not isinstance(project_id, (int, long)):
481 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("'project' must be integer")
482 2556cf45 Giorgos Korfiatis
        return Q(chain=project_id)
483 2556cf45 Giorgos Korfiatis
    return Q()
484 2556cf45 Giorgos Korfiatis
485 2556cf45 Giorgos Korfiatis
486 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
487 2556cf45 Giorgos Korfiatis
@user_from_token
488 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
489 2556cf45 Giorgos Korfiatis
def get_applications(request):
490 2556cf45 Giorgos Korfiatis
    user = request.user
491 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
492 2556cf45 Giorgos Korfiatis
    query = make_application_query(input_data)
493 2556cf45 Giorgos Korfiatis
    apps = _get_applications(query, request_user=user)
494 2556cf45 Giorgos Korfiatis
    data = get_applications_details(apps)
495 2556cf45 Giorgos Korfiatis
    return json_response(data)
496 2556cf45 Giorgos Korfiatis
497 2556cf45 Giorgos Korfiatis
498 2556cf45 Giorgos Korfiatis
def _get_applications(query, request_user=None):
499 2556cf45 Giorgos Korfiatis
    apps = ProjectApplication.objects.filter(query)
500 2556cf45 Giorgos Korfiatis
501 2556cf45 Giorgos Korfiatis
    if not request_user.is_project_admin():
502 2556cf45 Giorgos Korfiatis
        owned = (Q(owner=request_user) |
503 2556cf45 Giorgos Korfiatis
                 Q(applicant=request_user))
504 2556cf45 Giorgos Korfiatis
        apps = apps.filter(owned)
505 2556cf45 Giorgos Korfiatis
    return apps.select_related()
506 2556cf45 Giorgos Korfiatis
507 2556cf45 Giorgos Korfiatis
508 2556cf45 Giorgos Korfiatis
@csrf_exempt
509 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
510 2556cf45 Giorgos Korfiatis
@user_from_token
511 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
512 2556cf45 Giorgos Korfiatis
def application(request, app_id):
513 2556cf45 Giorgos Korfiatis
    user = request.user
514 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
515 2556cf45 Giorgos Korfiatis
        application = _get_application(app_id, user)
516 2556cf45 Giorgos Korfiatis
    data = get_application_details(application)
517 2556cf45 Giorgos Korfiatis
    return json_response(data)
518 2556cf45 Giorgos Korfiatis
519 2556cf45 Giorgos Korfiatis
520 2556cf45 Giorgos Korfiatis
def _get_application(app_id, request_user=None):
521 2556cf45 Giorgos Korfiatis
    application = functions.get_application(app_id)
522 2556cf45 Giorgos Korfiatis
    functions.app_check_allowed(
523 2556cf45 Giorgos Korfiatis
        application, request_user, level=functions.APPLICANT_LEVEL)
524 2556cf45 Giorgos Korfiatis
    return application
525 2556cf45 Giorgos Korfiatis
526 2556cf45 Giorgos Korfiatis
527 2556cf45 Giorgos Korfiatis
APPLICATION_ACTION = {
528 2556cf45 Giorgos Korfiatis
    "approve": functions.approve_application,
529 2556cf45 Giorgos Korfiatis
    "deny": functions.deny_application,
530 2556cf45 Giorgos Korfiatis
    "dismiss": functions.dismiss_application,
531 2556cf45 Giorgos Korfiatis
    "cancel": functions.cancel_application,
532 2556cf45 Giorgos Korfiatis
}
533 2556cf45 Giorgos Korfiatis
534 2556cf45 Giorgos Korfiatis
535 2556cf45 Giorgos Korfiatis
@csrf_exempt
536 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
537 2556cf45 Giorgos Korfiatis
@user_from_token
538 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
539 2556cf45 Giorgos Korfiatis
def application_action(request, app_id):
540 2556cf45 Giorgos Korfiatis
    user = request.user
541 2556cf45 Giorgos Korfiatis
    data = request.raw_post_data
542 2556cf45 Giorgos Korfiatis
    input_data = json.loads(data)
543 2556cf45 Giorgos Korfiatis
544 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(APPLICATION_ACTION, input_data)
545 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
546 2556cf45 Giorgos Korfiatis
        func(app_id, request_user=user, reason=action_data)
547 2556cf45 Giorgos Korfiatis
548 2556cf45 Giorgos Korfiatis
    return HttpResponse()
549 2556cf45 Giorgos Korfiatis
550 2556cf45 Giorgos Korfiatis
551 2556cf45 Giorgos Korfiatis
@csrf_exempt
552 2556cf45 Giorgos Korfiatis
def memberships(request):
553 2556cf45 Giorgos Korfiatis
    method = request.method
554 2556cf45 Giorgos Korfiatis
    if method == "GET":
555 2556cf45 Giorgos Korfiatis
        return get_memberships(request)
556 2556cf45 Giorgos Korfiatis
    elif method == "POST":
557 2556cf45 Giorgos Korfiatis
        return post_memberships(request)
558 2556cf45 Giorgos Korfiatis
    return api.api_method_not_allowed(request)
559 2556cf45 Giorgos Korfiatis
560 2556cf45 Giorgos Korfiatis
561 2556cf45 Giorgos Korfiatis
def make_membership_query(input_data):
562 2556cf45 Giorgos Korfiatis
    project_id = input_data.get("project")
563 2556cf45 Giorgos Korfiatis
    if project_id is not None:
564 2556cf45 Giorgos Korfiatis
        if not isinstance(project_id, (int, long)):
565 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("'project' must be integer")
566 2556cf45 Giorgos Korfiatis
        return Q(project=project_id)
567 2556cf45 Giorgos Korfiatis
    return Q()
568 2556cf45 Giorgos Korfiatis
569 2556cf45 Giorgos Korfiatis
570 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
571 2556cf45 Giorgos Korfiatis
@user_from_token
572 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
573 2556cf45 Giorgos Korfiatis
def get_memberships(request):
574 2556cf45 Giorgos Korfiatis
    user = request.user
575 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
576 2556cf45 Giorgos Korfiatis
    query = make_membership_query(input_data)
577 2556cf45 Giorgos Korfiatis
    memberships = _get_memberships(query, request_user=user)
578 2556cf45 Giorgos Korfiatis
    data = get_memberships_details(memberships, user)
579 2556cf45 Giorgos Korfiatis
    return json_response(data)
580 2556cf45 Giorgos Korfiatis
581 2556cf45 Giorgos Korfiatis
582 2556cf45 Giorgos Korfiatis
def _get_memberships(query, request_user=None):
583 2556cf45 Giorgos Korfiatis
    memberships = ProjectMembership.objects
584 2556cf45 Giorgos Korfiatis
    if not request_user.is_project_admin():
585 2556cf45 Giorgos Korfiatis
        owned = Q(project__application__owner=request_user)
586 2556cf45 Giorgos Korfiatis
        memb = Q(person=request_user)
587 2556cf45 Giorgos Korfiatis
        memberships = memberships.filter(owned | memb)
588 2556cf45 Giorgos Korfiatis
589 2556cf45 Giorgos Korfiatis
    return memberships.select_related(
590 2556cf45 Giorgos Korfiatis
        "project", "project__application",
591 2556cf45 Giorgos Korfiatis
        "project__application__owner", "project__application__applicant",
592 2556cf45 Giorgos Korfiatis
        "person").filter(query)
593 2556cf45 Giorgos Korfiatis
594 2556cf45 Giorgos Korfiatis
595 2556cf45 Giorgos Korfiatis
def join_project(data, request_user):
596 2556cf45 Giorgos Korfiatis
    project_id = data.get("project")
597 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
598 2556cf45 Giorgos Korfiatis
        membership = functions.join_project(project_id, request_user)
599 2556cf45 Giorgos Korfiatis
    response = {"id": membership.id}
600 2556cf45 Giorgos Korfiatis
    return json_response(response)
601 2556cf45 Giorgos Korfiatis
602 2556cf45 Giorgos Korfiatis
603 2556cf45 Giorgos Korfiatis
def enroll_user(data, request_user):
604 2556cf45 Giorgos Korfiatis
    project_id = data.get("project")
605 2556cf45 Giorgos Korfiatis
    email = data.get("user")
606 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
607 2556cf45 Giorgos Korfiatis
        m = functions.enroll_member_by_email(
608 2556cf45 Giorgos Korfiatis
            project_id, email, request_user)
609 2556cf45 Giorgos Korfiatis
610 2556cf45 Giorgos Korfiatis
    response = {"id": m.id}
611 2556cf45 Giorgos Korfiatis
    return json_response(response)
612 2556cf45 Giorgos Korfiatis
613 2556cf45 Giorgos Korfiatis
614 2556cf45 Giorgos Korfiatis
MEMBERSHIPS_ACTION = {
615 2556cf45 Giorgos Korfiatis
    "join":   join_project,
616 2556cf45 Giorgos Korfiatis
    "enroll": enroll_user,
617 2556cf45 Giorgos Korfiatis
}
618 2556cf45 Giorgos Korfiatis
619 2556cf45 Giorgos Korfiatis
620 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
621 2556cf45 Giorgos Korfiatis
@user_from_token
622 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
623 2556cf45 Giorgos Korfiatis
def post_memberships(request):
624 2556cf45 Giorgos Korfiatis
    user = request.user
625 2556cf45 Giorgos Korfiatis
    data = request.raw_post_data
626 2556cf45 Giorgos Korfiatis
    input_data = json.loads(data)
627 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(MEMBERSHIPS_ACTION, input_data)
628 2556cf45 Giorgos Korfiatis
    return func(action_data, user)
629 2556cf45 Giorgos Korfiatis
630 2556cf45 Giorgos Korfiatis
631 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
632 2556cf45 Giorgos Korfiatis
@user_from_token
633 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
634 2556cf45 Giorgos Korfiatis
def membership(request, memb_id):
635 2556cf45 Giorgos Korfiatis
    user = request.user
636 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
637 2556cf45 Giorgos Korfiatis
        m = _get_membership(memb_id, request_user=user)
638 2556cf45 Giorgos Korfiatis
    data = get_membership_details(m, user)
639 2556cf45 Giorgos Korfiatis
    return json_response(data)
640 2556cf45 Giorgos Korfiatis
641 2556cf45 Giorgos Korfiatis
642 2556cf45 Giorgos Korfiatis
def _get_membership(memb_id, request_user=None):
643 2556cf45 Giorgos Korfiatis
    membership = functions.get_membership_by_id(memb_id)
644 2556cf45 Giorgos Korfiatis
    functions.membership_check_allowed(membership, request_user)
645 2556cf45 Giorgos Korfiatis
    return membership
646 2556cf45 Giorgos Korfiatis
647 2556cf45 Giorgos Korfiatis
648 2556cf45 Giorgos Korfiatis
MEMBERSHIP_ACTION = {
649 2556cf45 Giorgos Korfiatis
    "leave":  functions.leave_project,
650 2556cf45 Giorgos Korfiatis
    "cancel": functions.cancel_membership,
651 2556cf45 Giorgos Korfiatis
    "accept": functions.accept_membership,
652 2556cf45 Giorgos Korfiatis
    "reject": functions.reject_membership,
653 2556cf45 Giorgos Korfiatis
    "remove": functions.remove_membership,
654 2556cf45 Giorgos Korfiatis
}
655 2556cf45 Giorgos Korfiatis
656 2556cf45 Giorgos Korfiatis
657 2556cf45 Giorgos Korfiatis
@csrf_exempt
658 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
659 2556cf45 Giorgos Korfiatis
@user_from_token
660 2556cf45 Giorgos Korfiatis
@commit_on_success_strict()
661 2556cf45 Giorgos Korfiatis
def membership_action(request, memb_id):
662 2556cf45 Giorgos Korfiatis
    user = request.user
663 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
664 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(MEMBERSHIP_ACTION, input_data)
665 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
666 2556cf45 Giorgos Korfiatis
        func(memb_id, user, reason=action_data)
667 2556cf45 Giorgos Korfiatis
    return HttpResponse()