Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / projects.py @ 381a548c

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