Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / projects.py @ 62d30634

History | View | Annotate | Download (21.4 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 2aba7764 Sofia Papagiannaki
    return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
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 62d30634 Giorgos Korfiatis
        active = (Project.o_state_q(Project.O_ACTIVE) &
297 62d30634 Giorgos Korfiatis
                  Q(application__private=False))
298 2556cf45 Giorgos Korfiatis
        projects = projects.filter(is_memb | owned | active)
299 2556cf45 Giorgos Korfiatis
    return projects.select_related(
300 2556cf45 Giorgos Korfiatis
        "application", "application__owner", "application__applicant")
301 2556cf45 Giorgos Korfiatis
302 2556cf45 Giorgos Korfiatis
303 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
304 2556cf45 Giorgos Korfiatis
@user_from_token
305 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
306 2556cf45 Giorgos Korfiatis
def create_project(request):
307 2556cf45 Giorgos Korfiatis
    user = request.user
308 b694875c Christos Stavrakakis
    data = request.body
309 2556cf45 Giorgos Korfiatis
    app_data = json.loads(data)
310 2556cf45 Giorgos Korfiatis
    return submit_application(app_data, user, project_id=None)
311 2556cf45 Giorgos Korfiatis
312 2556cf45 Giorgos Korfiatis
313 2556cf45 Giorgos Korfiatis
@csrf_exempt
314 2556cf45 Giorgos Korfiatis
def project(request, project_id):
315 2556cf45 Giorgos Korfiatis
    method = request.method
316 2556cf45 Giorgos Korfiatis
    if method == "GET":
317 2556cf45 Giorgos Korfiatis
        return get_project(request, project_id)
318 2556cf45 Giorgos Korfiatis
    if method == "POST":
319 2556cf45 Giorgos Korfiatis
        return modify_project(request, project_id)
320 2aba7764 Sofia Papagiannaki
    return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
321 2556cf45 Giorgos Korfiatis
322 2556cf45 Giorgos Korfiatis
323 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
324 2556cf45 Giorgos Korfiatis
@user_from_token
325 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
326 2556cf45 Giorgos Korfiatis
def get_project(request, project_id):
327 2556cf45 Giorgos Korfiatis
    user = request.user
328 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
329 2556cf45 Giorgos Korfiatis
        project = _get_project(project_id, request_user=user)
330 2556cf45 Giorgos Korfiatis
    data = get_project_details(project, user)
331 2556cf45 Giorgos Korfiatis
    return json_response(data)
332 2556cf45 Giorgos Korfiatis
333 2556cf45 Giorgos Korfiatis
334 2556cf45 Giorgos Korfiatis
def _get_project(project_id, request_user=None):
335 2556cf45 Giorgos Korfiatis
    project = functions.get_project_by_id(project_id)
336 2556cf45 Giorgos Korfiatis
    functions.project_check_allowed(
337 2556cf45 Giorgos Korfiatis
        project, request_user, level=functions.ANY_LEVEL)
338 2556cf45 Giorgos Korfiatis
    return project
339 2556cf45 Giorgos Korfiatis
340 2556cf45 Giorgos Korfiatis
341 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
342 2556cf45 Giorgos Korfiatis
@user_from_token
343 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
344 2556cf45 Giorgos Korfiatis
def modify_project(request, project_id):
345 2556cf45 Giorgos Korfiatis
    user = request.user
346 b694875c Christos Stavrakakis
    data = request.body
347 2556cf45 Giorgos Korfiatis
    app_data = json.loads(data)
348 2556cf45 Giorgos Korfiatis
    return submit_application(app_data, user, project_id=project_id)
349 2556cf45 Giorgos Korfiatis
350 2556cf45 Giorgos Korfiatis
351 2556cf45 Giorgos Korfiatis
def _get_date(d, key):
352 2556cf45 Giorgos Korfiatis
    date_str = d.get(key)
353 2556cf45 Giorgos Korfiatis
    if date_str is not None:
354 2556cf45 Giorgos Korfiatis
        try:
355 2556cf45 Giorgos Korfiatis
            return date_util.isoparse(date_str)
356 2556cf45 Giorgos Korfiatis
        except:
357 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("Invalid %s" % key)
358 2556cf45 Giorgos Korfiatis
    else:
359 2556cf45 Giorgos Korfiatis
        return None
360 2556cf45 Giorgos Korfiatis
361 2556cf45 Giorgos Korfiatis
362 2556cf45 Giorgos Korfiatis
def _get_maybe_string(d, key):
363 2556cf45 Giorgos Korfiatis
    value = d.get(key)
364 2556cf45 Giorgos Korfiatis
    if value is not None and not isinstance(value, basestring):
365 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("%s must be string" % key)
366 2556cf45 Giorgos Korfiatis
    return value
367 2556cf45 Giorgos Korfiatis
368 2556cf45 Giorgos Korfiatis
369 62d30634 Giorgos Korfiatis
def _get_maybe_boolean(d, key):
370 62d30634 Giorgos Korfiatis
    value = d.get(key)
371 62d30634 Giorgos Korfiatis
    if value is not None and not isinstance(value, bool):
372 62d30634 Giorgos Korfiatis
        raise faults.BadRequest("%s must be boolean" % key)
373 62d30634 Giorgos Korfiatis
    return value
374 62d30634 Giorgos Korfiatis
375 62d30634 Giorgos Korfiatis
376 a23ac2f7 Giorgos Korfiatis
DOMAIN_VALUE_REGEX = re.compile(
377 a23ac2f7 Giorgos Korfiatis
    r'^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$',
378 a23ac2f7 Giorgos Korfiatis
    re.IGNORECASE)
379 a23ac2f7 Giorgos Korfiatis
380 a23ac2f7 Giorgos Korfiatis
381 a23ac2f7 Giorgos Korfiatis
def valid_project_name(name):
382 a23ac2f7 Giorgos Korfiatis
    return DOMAIN_VALUE_REGEX.match(name) is not None
383 a23ac2f7 Giorgos Korfiatis
384 a23ac2f7 Giorgos Korfiatis
385 2556cf45 Giorgos Korfiatis
def submit_application(app_data, user, project_id=None):
386 2556cf45 Giorgos Korfiatis
    uuid = app_data.get("owner")
387 2556cf45 Giorgos Korfiatis
    if uuid is None:
388 2556cf45 Giorgos Korfiatis
        owner = user
389 2556cf45 Giorgos Korfiatis
    else:
390 2556cf45 Giorgos Korfiatis
        try:
391 733f013d Giorgos Korfiatis
            owner = AstakosUser.objects.accepted().get(uuid=uuid)
392 2556cf45 Giorgos Korfiatis
        except AstakosUser.DoesNotExist:
393 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("User does not exist.")
394 2556cf45 Giorgos Korfiatis
395 2556cf45 Giorgos Korfiatis
    try:
396 2556cf45 Giorgos Korfiatis
        name = app_data["name"]
397 2556cf45 Giorgos Korfiatis
    except KeyError:
398 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Name missing.")
399 2556cf45 Giorgos Korfiatis
400 a23ac2f7 Giorgos Korfiatis
    if not valid_project_name(name):
401 a23ac2f7 Giorgos Korfiatis
        raise faults.BadRequest("Project name should be in domain format")
402 a23ac2f7 Giorgos Korfiatis
403 2556cf45 Giorgos Korfiatis
    join_policy = app_data.get("join_policy", "moderated")
404 2556cf45 Giorgos Korfiatis
    try:
405 2556cf45 Giorgos Korfiatis
        join_policy = MEMBERSHIP_POLICY[join_policy]
406 2556cf45 Giorgos Korfiatis
    except KeyError:
407 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Invalid join policy")
408 2556cf45 Giorgos Korfiatis
409 2556cf45 Giorgos Korfiatis
    leave_policy = app_data.get("leave_policy", "auto")
410 2556cf45 Giorgos Korfiatis
    try:
411 2556cf45 Giorgos Korfiatis
        leave_policy = MEMBERSHIP_POLICY[leave_policy]
412 2556cf45 Giorgos Korfiatis
    except KeyError:
413 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Invalid leave policy")
414 2556cf45 Giorgos Korfiatis
415 2556cf45 Giorgos Korfiatis
    start_date = _get_date(app_data, "start_date")
416 2556cf45 Giorgos Korfiatis
    end_date = _get_date(app_data, "end_date")
417 2556cf45 Giorgos Korfiatis
418 2556cf45 Giorgos Korfiatis
    if end_date is None:
419 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Missing end date")
420 2556cf45 Giorgos Korfiatis
421 2556cf45 Giorgos Korfiatis
    max_members = app_data.get("max_members")
422 e98239db Giorgos Korfiatis
    if not isinstance(max_members, (int, long)) or max_members < 0:
423 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("Invalid max_members")
424 2556cf45 Giorgos Korfiatis
425 62d30634 Giorgos Korfiatis
    private = bool(_get_maybe_boolean(app_data, "private"))
426 2556cf45 Giorgos Korfiatis
    homepage = _get_maybe_string(app_data, "homepage")
427 2556cf45 Giorgos Korfiatis
    description = _get_maybe_string(app_data, "description")
428 2556cf45 Giorgos Korfiatis
    comments = _get_maybe_string(app_data, "comments")
429 2556cf45 Giorgos Korfiatis
    resources = app_data.get("resources", {})
430 2556cf45 Giorgos Korfiatis
431 2556cf45 Giorgos Korfiatis
    submit = functions.submit_application
432 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
433 2556cf45 Giorgos Korfiatis
        application = submit(
434 2556cf45 Giorgos Korfiatis
            owner=owner,
435 2556cf45 Giorgos Korfiatis
            name=name,
436 2556cf45 Giorgos Korfiatis
            project_id=project_id,
437 2556cf45 Giorgos Korfiatis
            homepage=homepage,
438 2556cf45 Giorgos Korfiatis
            description=description,
439 2556cf45 Giorgos Korfiatis
            start_date=start_date,
440 2556cf45 Giorgos Korfiatis
            end_date=end_date,
441 2556cf45 Giorgos Korfiatis
            member_join_policy=join_policy,
442 2556cf45 Giorgos Korfiatis
            member_leave_policy=leave_policy,
443 2556cf45 Giorgos Korfiatis
            limit_on_members_number=max_members,
444 62d30634 Giorgos Korfiatis
            private=private,
445 2556cf45 Giorgos Korfiatis
            comments=comments,
446 2556cf45 Giorgos Korfiatis
            resources=resources,
447 2556cf45 Giorgos Korfiatis
            request_user=user)
448 2556cf45 Giorgos Korfiatis
449 2556cf45 Giorgos Korfiatis
    result = {"application": application.id,
450 2556cf45 Giorgos Korfiatis
              "id": application.chain_id
451 2556cf45 Giorgos Korfiatis
              }
452 2556cf45 Giorgos Korfiatis
    return json_response(result, status_code=201)
453 2556cf45 Giorgos Korfiatis
454 2556cf45 Giorgos Korfiatis
455 2556cf45 Giorgos Korfiatis
def get_action(actions, input_data):
456 2556cf45 Giorgos Korfiatis
    action = None
457 2556cf45 Giorgos Korfiatis
    data = None
458 2556cf45 Giorgos Korfiatis
    for option in actions.keys():
459 2556cf45 Giorgos Korfiatis
        if option in input_data:
460 2556cf45 Giorgos Korfiatis
            if action:
461 2556cf45 Giorgos Korfiatis
                raise faults.BadRequest("Multiple actions not supported")
462 2556cf45 Giorgos Korfiatis
            else:
463 2556cf45 Giorgos Korfiatis
                action = option
464 2556cf45 Giorgos Korfiatis
                data = input_data[action]
465 2556cf45 Giorgos Korfiatis
    if not action:
466 2556cf45 Giorgos Korfiatis
        raise faults.BadRequest("No recognized action")
467 2556cf45 Giorgos Korfiatis
    return actions[action], data
468 2556cf45 Giorgos Korfiatis
469 2556cf45 Giorgos Korfiatis
470 2556cf45 Giorgos Korfiatis
PROJECT_ACTION = {
471 2556cf45 Giorgos Korfiatis
    "terminate": functions.terminate,
472 2556cf45 Giorgos Korfiatis
    "suspend":   functions.suspend,
473 2556cf45 Giorgos Korfiatis
    "unsuspend": functions.unsuspend,
474 2556cf45 Giorgos Korfiatis
    "reinstate": functions.reinstate,
475 2556cf45 Giorgos Korfiatis
}
476 2556cf45 Giorgos Korfiatis
477 2556cf45 Giorgos Korfiatis
478 2556cf45 Giorgos Korfiatis
@csrf_exempt
479 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
480 2556cf45 Giorgos Korfiatis
@user_from_token
481 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
482 2556cf45 Giorgos Korfiatis
def project_action(request, project_id):
483 2556cf45 Giorgos Korfiatis
    user = request.user
484 b694875c Christos Stavrakakis
    data = request.body
485 2556cf45 Giorgos Korfiatis
    input_data = json.loads(data)
486 2556cf45 Giorgos Korfiatis
487 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(PROJECT_ACTION, input_data)
488 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
489 2556cf45 Giorgos Korfiatis
        func(project_id, request_user=user, reason=action_data)
490 2556cf45 Giorgos Korfiatis
    return HttpResponse()
491 2556cf45 Giorgos Korfiatis
492 2556cf45 Giorgos Korfiatis
493 2556cf45 Giorgos Korfiatis
@csrf_exempt
494 2556cf45 Giorgos Korfiatis
def applications(request):
495 2556cf45 Giorgos Korfiatis
    method = request.method
496 2556cf45 Giorgos Korfiatis
    if method == "GET":
497 2556cf45 Giorgos Korfiatis
        return get_applications(request)
498 2aba7764 Sofia Papagiannaki
    return api.api_method_not_allowed(request, allowed_methods=['GET'])
499 2556cf45 Giorgos Korfiatis
500 2556cf45 Giorgos Korfiatis
501 2556cf45 Giorgos Korfiatis
def make_application_query(input_data):
502 2556cf45 Giorgos Korfiatis
    project_id = input_data.get("project")
503 2556cf45 Giorgos Korfiatis
    if project_id is not None:
504 2556cf45 Giorgos Korfiatis
        if not isinstance(project_id, (int, long)):
505 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("'project' must be integer")
506 2556cf45 Giorgos Korfiatis
        return Q(chain=project_id)
507 2556cf45 Giorgos Korfiatis
    return Q()
508 2556cf45 Giorgos Korfiatis
509 2556cf45 Giorgos Korfiatis
510 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
511 2556cf45 Giorgos Korfiatis
@user_from_token
512 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
513 2556cf45 Giorgos Korfiatis
def get_applications(request):
514 2556cf45 Giorgos Korfiatis
    user = request.user
515 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
516 2556cf45 Giorgos Korfiatis
    query = make_application_query(input_data)
517 2556cf45 Giorgos Korfiatis
    apps = _get_applications(query, request_user=user)
518 2556cf45 Giorgos Korfiatis
    data = get_applications_details(apps)
519 2556cf45 Giorgos Korfiatis
    return json_response(data)
520 2556cf45 Giorgos Korfiatis
521 2556cf45 Giorgos Korfiatis
522 2556cf45 Giorgos Korfiatis
def _get_applications(query, request_user=None):
523 2556cf45 Giorgos Korfiatis
    apps = ProjectApplication.objects.filter(query)
524 2556cf45 Giorgos Korfiatis
525 2556cf45 Giorgos Korfiatis
    if not request_user.is_project_admin():
526 2556cf45 Giorgos Korfiatis
        owned = (Q(owner=request_user) |
527 2556cf45 Giorgos Korfiatis
                 Q(applicant=request_user))
528 2556cf45 Giorgos Korfiatis
        apps = apps.filter(owned)
529 2556cf45 Giorgos Korfiatis
    return apps.select_related()
530 2556cf45 Giorgos Korfiatis
531 2556cf45 Giorgos Korfiatis
532 2556cf45 Giorgos Korfiatis
@csrf_exempt
533 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
534 2556cf45 Giorgos Korfiatis
@user_from_token
535 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
536 2556cf45 Giorgos Korfiatis
def application(request, app_id):
537 2556cf45 Giorgos Korfiatis
    user = request.user
538 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
539 2556cf45 Giorgos Korfiatis
        application = _get_application(app_id, user)
540 2556cf45 Giorgos Korfiatis
    data = get_application_details(application)
541 2556cf45 Giorgos Korfiatis
    return json_response(data)
542 2556cf45 Giorgos Korfiatis
543 2556cf45 Giorgos Korfiatis
544 2556cf45 Giorgos Korfiatis
def _get_application(app_id, request_user=None):
545 2556cf45 Giorgos Korfiatis
    application = functions.get_application(app_id)
546 2556cf45 Giorgos Korfiatis
    functions.app_check_allowed(
547 2556cf45 Giorgos Korfiatis
        application, request_user, level=functions.APPLICANT_LEVEL)
548 2556cf45 Giorgos Korfiatis
    return application
549 2556cf45 Giorgos Korfiatis
550 2556cf45 Giorgos Korfiatis
551 2556cf45 Giorgos Korfiatis
APPLICATION_ACTION = {
552 2556cf45 Giorgos Korfiatis
    "approve": functions.approve_application,
553 2556cf45 Giorgos Korfiatis
    "deny": functions.deny_application,
554 2556cf45 Giorgos Korfiatis
    "dismiss": functions.dismiss_application,
555 2556cf45 Giorgos Korfiatis
    "cancel": functions.cancel_application,
556 2556cf45 Giorgos Korfiatis
}
557 2556cf45 Giorgos Korfiatis
558 2556cf45 Giorgos Korfiatis
559 2556cf45 Giorgos Korfiatis
@csrf_exempt
560 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
561 2556cf45 Giorgos Korfiatis
@user_from_token
562 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
563 2556cf45 Giorgos Korfiatis
def application_action(request, app_id):
564 2556cf45 Giorgos Korfiatis
    user = request.user
565 b694875c Christos Stavrakakis
    data = request.body
566 2556cf45 Giorgos Korfiatis
    input_data = json.loads(data)
567 2556cf45 Giorgos Korfiatis
568 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(APPLICATION_ACTION, input_data)
569 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
570 2556cf45 Giorgos Korfiatis
        func(app_id, request_user=user, reason=action_data)
571 2556cf45 Giorgos Korfiatis
572 2556cf45 Giorgos Korfiatis
    return HttpResponse()
573 2556cf45 Giorgos Korfiatis
574 2556cf45 Giorgos Korfiatis
575 2556cf45 Giorgos Korfiatis
@csrf_exempt
576 2556cf45 Giorgos Korfiatis
def memberships(request):
577 2556cf45 Giorgos Korfiatis
    method = request.method
578 2556cf45 Giorgos Korfiatis
    if method == "GET":
579 2556cf45 Giorgos Korfiatis
        return get_memberships(request)
580 2556cf45 Giorgos Korfiatis
    elif method == "POST":
581 2556cf45 Giorgos Korfiatis
        return post_memberships(request)
582 2aba7764 Sofia Papagiannaki
    return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
583 2556cf45 Giorgos Korfiatis
584 2556cf45 Giorgos Korfiatis
585 2556cf45 Giorgos Korfiatis
def make_membership_query(input_data):
586 2556cf45 Giorgos Korfiatis
    project_id = input_data.get("project")
587 2556cf45 Giorgos Korfiatis
    if project_id is not None:
588 2556cf45 Giorgos Korfiatis
        if not isinstance(project_id, (int, long)):
589 2556cf45 Giorgos Korfiatis
            raise faults.BadRequest("'project' must be integer")
590 2556cf45 Giorgos Korfiatis
        return Q(project=project_id)
591 2556cf45 Giorgos Korfiatis
    return Q()
592 2556cf45 Giorgos Korfiatis
593 2556cf45 Giorgos Korfiatis
594 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
595 2556cf45 Giorgos Korfiatis
@user_from_token
596 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
597 2556cf45 Giorgos Korfiatis
def get_memberships(request):
598 2556cf45 Giorgos Korfiatis
    user = request.user
599 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
600 2556cf45 Giorgos Korfiatis
    query = make_membership_query(input_data)
601 2556cf45 Giorgos Korfiatis
    memberships = _get_memberships(query, request_user=user)
602 2556cf45 Giorgos Korfiatis
    data = get_memberships_details(memberships, user)
603 2556cf45 Giorgos Korfiatis
    return json_response(data)
604 2556cf45 Giorgos Korfiatis
605 2556cf45 Giorgos Korfiatis
606 2556cf45 Giorgos Korfiatis
def _get_memberships(query, request_user=None):
607 2556cf45 Giorgos Korfiatis
    memberships = ProjectMembership.objects
608 2556cf45 Giorgos Korfiatis
    if not request_user.is_project_admin():
609 2556cf45 Giorgos Korfiatis
        owned = Q(project__application__owner=request_user)
610 2556cf45 Giorgos Korfiatis
        memb = Q(person=request_user)
611 2556cf45 Giorgos Korfiatis
        memberships = memberships.filter(owned | memb)
612 2556cf45 Giorgos Korfiatis
613 2556cf45 Giorgos Korfiatis
    return memberships.select_related(
614 2556cf45 Giorgos Korfiatis
        "project", "project__application",
615 2556cf45 Giorgos Korfiatis
        "project__application__owner", "project__application__applicant",
616 2556cf45 Giorgos Korfiatis
        "person").filter(query)
617 2556cf45 Giorgos Korfiatis
618 2556cf45 Giorgos Korfiatis
619 2556cf45 Giorgos Korfiatis
def join_project(data, request_user):
620 2556cf45 Giorgos Korfiatis
    project_id = data.get("project")
621 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
622 2556cf45 Giorgos Korfiatis
        membership = functions.join_project(project_id, request_user)
623 2556cf45 Giorgos Korfiatis
    response = {"id": membership.id}
624 2556cf45 Giorgos Korfiatis
    return json_response(response)
625 2556cf45 Giorgos Korfiatis
626 2556cf45 Giorgos Korfiatis
627 2556cf45 Giorgos Korfiatis
def enroll_user(data, request_user):
628 2556cf45 Giorgos Korfiatis
    project_id = data.get("project")
629 2556cf45 Giorgos Korfiatis
    email = data.get("user")
630 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
631 2556cf45 Giorgos Korfiatis
        m = functions.enroll_member_by_email(
632 2556cf45 Giorgos Korfiatis
            project_id, email, request_user)
633 2556cf45 Giorgos Korfiatis
634 2556cf45 Giorgos Korfiatis
    response = {"id": m.id}
635 2556cf45 Giorgos Korfiatis
    return json_response(response)
636 2556cf45 Giorgos Korfiatis
637 2556cf45 Giorgos Korfiatis
638 2556cf45 Giorgos Korfiatis
MEMBERSHIPS_ACTION = {
639 2556cf45 Giorgos Korfiatis
    "join":   join_project,
640 2556cf45 Giorgos Korfiatis
    "enroll": enroll_user,
641 2556cf45 Giorgos Korfiatis
}
642 2556cf45 Giorgos Korfiatis
643 2556cf45 Giorgos Korfiatis
644 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
645 2556cf45 Giorgos Korfiatis
@user_from_token
646 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
647 2556cf45 Giorgos Korfiatis
def post_memberships(request):
648 2556cf45 Giorgos Korfiatis
    user = request.user
649 b694875c Christos Stavrakakis
    data = request.body
650 2556cf45 Giorgos Korfiatis
    input_data = json.loads(data)
651 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(MEMBERSHIPS_ACTION, input_data)
652 2556cf45 Giorgos Korfiatis
    return func(action_data, user)
653 2556cf45 Giorgos Korfiatis
654 2556cf45 Giorgos Korfiatis
655 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="GET", token_required=True, user_required=False)
656 2556cf45 Giorgos Korfiatis
@user_from_token
657 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
658 2556cf45 Giorgos Korfiatis
def membership(request, memb_id):
659 2556cf45 Giorgos Korfiatis
    user = request.user
660 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
661 2556cf45 Giorgos Korfiatis
        m = _get_membership(memb_id, request_user=user)
662 2556cf45 Giorgos Korfiatis
    data = get_membership_details(m, user)
663 2556cf45 Giorgos Korfiatis
    return json_response(data)
664 2556cf45 Giorgos Korfiatis
665 2556cf45 Giorgos Korfiatis
666 2556cf45 Giorgos Korfiatis
def _get_membership(memb_id, request_user=None):
667 2556cf45 Giorgos Korfiatis
    membership = functions.get_membership_by_id(memb_id)
668 2556cf45 Giorgos Korfiatis
    functions.membership_check_allowed(membership, request_user)
669 2556cf45 Giorgos Korfiatis
    return membership
670 2556cf45 Giorgos Korfiatis
671 2556cf45 Giorgos Korfiatis
672 2556cf45 Giorgos Korfiatis
MEMBERSHIP_ACTION = {
673 2556cf45 Giorgos Korfiatis
    "leave":  functions.leave_project,
674 2556cf45 Giorgos Korfiatis
    "cancel": functions.cancel_membership,
675 2556cf45 Giorgos Korfiatis
    "accept": functions.accept_membership,
676 2556cf45 Giorgos Korfiatis
    "reject": functions.reject_membership,
677 2556cf45 Giorgos Korfiatis
    "remove": functions.remove_membership,
678 2556cf45 Giorgos Korfiatis
}
679 2556cf45 Giorgos Korfiatis
680 2556cf45 Giorgos Korfiatis
681 2556cf45 Giorgos Korfiatis
@csrf_exempt
682 2556cf45 Giorgos Korfiatis
@api.api_method(http_method="POST", token_required=True, user_required=False)
683 2556cf45 Giorgos Korfiatis
@user_from_token
684 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
685 2556cf45 Giorgos Korfiatis
def membership_action(request, memb_id):
686 2556cf45 Giorgos Korfiatis
    user = request.user
687 2556cf45 Giorgos Korfiatis
    input_data = read_json_body(request, default={})
688 2556cf45 Giorgos Korfiatis
    func, action_data = get_action(MEMBERSHIP_ACTION, input_data)
689 2556cf45 Giorgos Korfiatis
    with ExceptionHandler():
690 2556cf45 Giorgos Korfiatis
        func(memb_id, user, reason=action_data)
691 2556cf45 Giorgos Korfiatis
    return HttpResponse()