Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / projects.py @ 85ae5a4c

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