Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / projects.py @ a3e3917f

History | View | Annotate | Download (24.8 kB)

1 9fb7a900 Giorgos Korfiatis
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
2 70e11eaa Sofia Papagiannaki
#
3 70e11eaa Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 70e11eaa Sofia Papagiannaki
# without modification, are permitted provided that the following
5 70e11eaa Sofia Papagiannaki
# conditions are met:
6 70e11eaa Sofia Papagiannaki
#
7 70e11eaa Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 70e11eaa Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 70e11eaa Sofia Papagiannaki
#      disclaimer.
10 70e11eaa Sofia Papagiannaki
#
11 70e11eaa Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 70e11eaa Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 70e11eaa Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 70e11eaa Sofia Papagiannaki
#      provided with the distribution.
15 70e11eaa Sofia Papagiannaki
#
16 70e11eaa Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 70e11eaa Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 70e11eaa Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 70e11eaa Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 70e11eaa Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 70e11eaa Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 70e11eaa Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 70e11eaa Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 70e11eaa Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 70e11eaa Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 70e11eaa Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 70e11eaa Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 70e11eaa Sofia Papagiannaki
#
29 70e11eaa Sofia Papagiannaki
# The views and conclusions contained in the software and
30 70e11eaa Sofia Papagiannaki
# documentation are those of the authors and should not be
31 70e11eaa Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 70e11eaa Sofia Papagiannaki
# or implied, of GRNET S.A.
33 70e11eaa Sofia Papagiannaki
34 70e11eaa Sofia Papagiannaki
import logging
35 70e11eaa Sofia Papagiannaki
import inflect
36 70e11eaa Sofia Papagiannaki
37 70e11eaa Sofia Papagiannaki
engine = inflect.engine()
38 70e11eaa Sofia Papagiannaki
39 70e11eaa Sofia Papagiannaki
from django_tables2 import RequestConfig
40 70e11eaa Sofia Papagiannaki
41 70e11eaa Sofia Papagiannaki
from django.shortcuts import get_object_or_404
42 70e11eaa Sofia Papagiannaki
from django.contrib import messages
43 70e11eaa Sofia Papagiannaki
from django.core.urlresolvers import reverse
44 3e0a032d Sofia Papagiannaki
from django.http import Http404
45 70e11eaa Sofia Papagiannaki
from django.shortcuts import redirect
46 70e11eaa Sofia Papagiannaki
from django.utils.html import escape
47 70e11eaa Sofia Papagiannaki
from django.utils.translation import ugettext as _
48 70e11eaa Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
49 3e0a032d Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
50 70e11eaa Sofia Papagiannaki
from django.views.decorators.http import require_http_methods
51 a3e3917f Giorgos Korfiatis
from django.db import transaction
52 70e11eaa Sofia Papagiannaki
53 70e11eaa Sofia Papagiannaki
import astakos.im.messages as astakos_messages
54 70e11eaa Sofia Papagiannaki
55 70e11eaa Sofia Papagiannaki
from astakos.im import tables
56 6d583e07 Giorgos Korfiatis
from astakos.im.models import ProjectApplication, ProjectMembership, Project
57 3e0a032d Sofia Papagiannaki
from astakos.im.util import get_context, restrict_next
58 3e0a032d Sofia Papagiannaki
from astakos.im.forms import ProjectApplicationForm, AddProjectMembersForm, \
59 3e0a032d Sofia Papagiannaki
    ProjectSearchForm
60 3e0a032d Sofia Papagiannaki
from astakos.im.functions import check_pending_app_quota, accept_membership, \
61 3e0a032d Sofia Papagiannaki
    reject_membership, remove_membership, cancel_membership, leave_project, \
62 3e0a032d Sofia Papagiannaki
    join_project, enroll_member, can_join_request, can_leave_request, \
63 6d583e07 Giorgos Korfiatis
    get_related_project_id, approve_application, \
64 f12bcb3d Giorgos Korfiatis
    deny_application, cancel_application, dismiss_application, ProjectError
65 8998f09a Sofia Papagiannaki
from astakos.im import settings
66 59eb6ec5 Kostas Papadimitriou
from astakos.im.util import redirect_back
67 70e11eaa Sofia Papagiannaki
from astakos.im.views.util import render_response, _create_object, \
68 9fb7a900 Giorgos Korfiatis
    _update_object, _resources_catalog, ExceptionHandler
69 70e11eaa Sofia Papagiannaki
from astakos.im.views.decorators import cookie_fix, signed_terms_required,\
70 b6496f0c Kostas Papadimitriou
    valid_astakos_user_required, login_required
71 70e11eaa Sofia Papagiannaki
72 70e11eaa Sofia Papagiannaki
logger = logging.getLogger(__name__)
73 70e11eaa Sofia Papagiannaki
74 70e11eaa Sofia Papagiannaki
75 70e11eaa Sofia Papagiannaki
@cookie_fix
76 70e11eaa Sofia Papagiannaki
def how_it_works(request):
77 70e11eaa Sofia Papagiannaki
    return render_response(
78 70e11eaa Sofia Papagiannaki
        'im/how_it_works.html',
79 70e11eaa Sofia Papagiannaki
        context_instance=get_context(request))
80 70e11eaa Sofia Papagiannaki
81 70e11eaa Sofia Papagiannaki
82 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
83 70e11eaa Sofia Papagiannaki
@cookie_fix
84 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
85 70e11eaa Sofia Papagiannaki
def project_add(request):
86 70e11eaa Sofia Papagiannaki
    user = request.user
87 70e11eaa Sofia Papagiannaki
    if not user.is_project_admin():
88 70e11eaa Sofia Papagiannaki
        ok, limit = check_pending_app_quota(user)
89 70e11eaa Sofia Papagiannaki
        if not ok:
90 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_ADD) % limit
91 70e11eaa Sofia Papagiannaki
            messages.error(request, m)
92 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_list')
93 8998f09a Sofia Papagiannaki
            next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
94 70e11eaa Sofia Papagiannaki
            return redirect(next)
95 70e11eaa Sofia Papagiannaki
96 70e11eaa Sofia Papagiannaki
    details_fields = ["name", "homepage", "description", "start_date",
97 70e11eaa Sofia Papagiannaki
                      "end_date", "comments"]
98 70e11eaa Sofia Papagiannaki
    membership_fields = ["member_join_policy", "member_leave_policy",
99 70e11eaa Sofia Papagiannaki
                         "limit_on_members_number"]
100 70e11eaa Sofia Papagiannaki
    resource_catalog, resource_groups = _resources_catalog(for_project=True)
101 70e11eaa Sofia Papagiannaki
    if resource_catalog is False:
102 70e11eaa Sofia Papagiannaki
        # on fail resource_groups contains the result object
103 70e11eaa Sofia Papagiannaki
        result = resource_groups
104 70e11eaa Sofia Papagiannaki
        messages.error(request, 'Unable to retrieve system resources: %s' %
105 70e11eaa Sofia Papagiannaki
                       result.reason)
106 70e11eaa Sofia Papagiannaki
    extra_context = {
107 70e11eaa Sofia Papagiannaki
        'resource_catalog': resource_catalog,
108 70e11eaa Sofia Papagiannaki
        'resource_groups': resource_groups,
109 70e11eaa Sofia Papagiannaki
        'show_form': True,
110 70e11eaa Sofia Papagiannaki
        'details_fields': details_fields,
111 70e11eaa Sofia Papagiannaki
        'membership_fields': membership_fields}
112 70e11eaa Sofia Papagiannaki
113 70e11eaa Sofia Papagiannaki
    response = None
114 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
115 9024ed2e Giorgos Korfiatis
        response = create_app_object(request, extra_context=extra_context)
116 70e11eaa Sofia Papagiannaki
117 70e11eaa Sofia Papagiannaki
    if response is not None:
118 70e11eaa Sofia Papagiannaki
        return response
119 70e11eaa Sofia Papagiannaki
120 70e11eaa Sofia Papagiannaki
    next = reverse('astakos.im.views.project_list')
121 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
122 70e11eaa Sofia Papagiannaki
    return redirect(next)
123 70e11eaa Sofia Papagiannaki
124 70e11eaa Sofia Papagiannaki
125 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
126 9024ed2e Giorgos Korfiatis
def create_app_object(request, extra_context=None):
127 9024ed2e Giorgos Korfiatis
    try:
128 bb528b2e Giorgos Korfiatis
        summary = 'im/projects/projectapplication_form_summary.html'
129 9024ed2e Giorgos Korfiatis
        return _create_object(
130 9024ed2e Giorgos Korfiatis
            request,
131 9024ed2e Giorgos Korfiatis
            template_name='im/projects/projectapplication_form.html',
132 bb528b2e Giorgos Korfiatis
            summary_template_name=summary,
133 9024ed2e Giorgos Korfiatis
            extra_context=extra_context,
134 9024ed2e Giorgos Korfiatis
            post_save_redirect=reverse('project_list'),
135 9024ed2e Giorgos Korfiatis
            form_class=ProjectApplicationForm,
136 9024ed2e Giorgos Korfiatis
            msg=_("The %(verbose_name)s has been received and "
137 9024ed2e Giorgos Korfiatis
                  "is under consideration."))
138 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
139 9024ed2e Giorgos Korfiatis
        messages.error(request, e)
140 9024ed2e Giorgos Korfiatis
141 9024ed2e Giorgos Korfiatis
142 b10ceccd Giorgos Korfiatis
def get_user_projects_table(projects, user, prefix):
143 b10ceccd Giorgos Korfiatis
    apps = ProjectApplication.objects.pending_per_project(projects)
144 b10ceccd Giorgos Korfiatis
    memberships = user.projectmembership_set.one_per_project()
145 b10ceccd Giorgos Korfiatis
    objs = ProjectMembership.objects
146 b10ceccd Giorgos Korfiatis
    accepted_ms = objs.any_accepted_per_project(projects)
147 b10ceccd Giorgos Korfiatis
    requested_ms = objs.requested_per_project(projects)
148 b10ceccd Giorgos Korfiatis
    return tables.UserProjectsTable(projects, user=user,
149 b10ceccd Giorgos Korfiatis
                                    prefix=prefix,
150 b10ceccd Giorgos Korfiatis
                                    pending_apps=apps,
151 b10ceccd Giorgos Korfiatis
                                    memberships=memberships,
152 b10ceccd Giorgos Korfiatis
                                    accepted=accepted_ms,
153 b10ceccd Giorgos Korfiatis
                                    requested=requested_ms)
154 b10ceccd Giorgos Korfiatis
155 b10ceccd Giorgos Korfiatis
156 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET"])
157 70e11eaa Sofia Papagiannaki
@cookie_fix
158 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
159 70e11eaa Sofia Papagiannaki
def project_list(request):
160 b10ceccd Giorgos Korfiatis
    projects = Project.objects.user_accessible_projects(request.user)
161 b10ceccd Giorgos Korfiatis
    table = get_user_projects_table(projects, user=request.user,
162 b10ceccd Giorgos Korfiatis
                                    prefix="my_projects_")
163 70e11eaa Sofia Papagiannaki
    return object_list(
164 70e11eaa Sofia Papagiannaki
        request,
165 70e11eaa Sofia Papagiannaki
        projects,
166 70e11eaa Sofia Papagiannaki
        template_name='im/projects/project_list.html',
167 70e11eaa Sofia Papagiannaki
        extra_context={
168 8fb8d0cf Giorgos Korfiatis
            'is_search': False,
169 70e11eaa Sofia Papagiannaki
            'table': table,
170 70e11eaa Sofia Papagiannaki
        })
171 70e11eaa Sofia Papagiannaki
172 70e11eaa Sofia Papagiannaki
173 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
174 70e11eaa Sofia Papagiannaki
@cookie_fix
175 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
176 70e11eaa Sofia Papagiannaki
def project_app_cancel(request, application_id):
177 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
178 70e11eaa Sofia Papagiannaki
    chain_id = None
179 70e11eaa Sofia Papagiannaki
180 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
181 70e11eaa Sofia Papagiannaki
        chain_id = _project_app_cancel(request, application_id)
182 70e11eaa Sofia Papagiannaki
183 70e11eaa Sofia Papagiannaki
    if not next:
184 70e11eaa Sofia Papagiannaki
        if chain_id:
185 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_detail', args=(chain_id,))
186 70e11eaa Sofia Papagiannaki
        else:
187 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_list')
188 70e11eaa Sofia Papagiannaki
189 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
190 70e11eaa Sofia Papagiannaki
    return redirect(next)
191 70e11eaa Sofia Papagiannaki
192 8fb8d0cf Giorgos Korfiatis
193 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
194 70e11eaa Sofia Papagiannaki
def _project_app_cancel(request, application_id):
195 70e11eaa Sofia Papagiannaki
    chain_id = None
196 70e11eaa Sofia Papagiannaki
    try:
197 70e11eaa Sofia Papagiannaki
        application_id = int(application_id)
198 70e11eaa Sofia Papagiannaki
        chain_id = get_related_project_id(application_id)
199 70e11eaa Sofia Papagiannaki
        cancel_application(application_id, request.user)
200 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
201 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
202 70e11eaa Sofia Papagiannaki
203 70e11eaa Sofia Papagiannaki
    else:
204 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.APPLICATION_CANCELLED)
205 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
206 70e11eaa Sofia Papagiannaki
        return chain_id
207 70e11eaa Sofia Papagiannaki
208 70e11eaa Sofia Papagiannaki
209 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
210 70e11eaa Sofia Papagiannaki
@cookie_fix
211 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
212 70e11eaa Sofia Papagiannaki
def project_modify(request, application_id):
213 70e11eaa Sofia Papagiannaki
214 70e11eaa Sofia Papagiannaki
    try:
215 70e11eaa Sofia Papagiannaki
        app = ProjectApplication.objects.get(id=application_id)
216 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
217 70e11eaa Sofia Papagiannaki
        raise Http404
218 70e11eaa Sofia Papagiannaki
219 70e11eaa Sofia Papagiannaki
    user = request.user
220 70e11eaa Sofia Papagiannaki
    if not (user.owns_application(app) or user.is_project_admin(app.id)):
221 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
222 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
223 70e11eaa Sofia Papagiannaki
224 70e11eaa Sofia Papagiannaki
    if not user.is_project_admin():
225 70e11eaa Sofia Papagiannaki
        owner = app.owner
226 c4028837 Giorgos Korfiatis
        ok, limit = check_pending_app_quota(owner, project=app.chain)
227 70e11eaa Sofia Papagiannaki
        if not ok:
228 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_MODIFY) % limit
229 70e11eaa Sofia Papagiannaki
            messages.error(request, m)
230 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_list')
231 8998f09a Sofia Papagiannaki
            next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
232 70e11eaa Sofia Papagiannaki
            return redirect(next)
233 70e11eaa Sofia Papagiannaki
234 70e11eaa Sofia Papagiannaki
    details_fields = ["name", "homepage", "description", "start_date",
235 70e11eaa Sofia Papagiannaki
                      "end_date", "comments"]
236 70e11eaa Sofia Papagiannaki
    membership_fields = ["member_join_policy", "member_leave_policy",
237 70e11eaa Sofia Papagiannaki
                         "limit_on_members_number"]
238 70e11eaa Sofia Papagiannaki
    resource_catalog, resource_groups = _resources_catalog(for_project=True)
239 70e11eaa Sofia Papagiannaki
    if resource_catalog is False:
240 70e11eaa Sofia Papagiannaki
        # on fail resource_groups contains the result object
241 70e11eaa Sofia Papagiannaki
        result = resource_groups
242 70e11eaa Sofia Papagiannaki
        messages.error(request, 'Unable to retrieve system resources: %s' %
243 70e11eaa Sofia Papagiannaki
                       result.reason)
244 70e11eaa Sofia Papagiannaki
    extra_context = {
245 70e11eaa Sofia Papagiannaki
        'resource_catalog': resource_catalog,
246 70e11eaa Sofia Papagiannaki
        'resource_groups': resource_groups,
247 70e11eaa Sofia Papagiannaki
        'show_form': True,
248 70e11eaa Sofia Papagiannaki
        'details_fields': details_fields,
249 70e11eaa Sofia Papagiannaki
        'update_form': True,
250 70e11eaa Sofia Papagiannaki
        'membership_fields': membership_fields
251 70e11eaa Sofia Papagiannaki
    }
252 70e11eaa Sofia Papagiannaki
253 70e11eaa Sofia Papagiannaki
    response = None
254 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
255 9024ed2e Giorgos Korfiatis
        response = update_app_object(request, application_id,
256 9024ed2e Giorgos Korfiatis
                                     extra_context=extra_context)
257 70e11eaa Sofia Papagiannaki
258 70e11eaa Sofia Papagiannaki
    if response is not None:
259 70e11eaa Sofia Papagiannaki
        return response
260 70e11eaa Sofia Papagiannaki
261 70e11eaa Sofia Papagiannaki
    next = reverse('astakos.im.views.project_list')
262 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
263 70e11eaa Sofia Papagiannaki
    return redirect(next)
264 70e11eaa Sofia Papagiannaki
265 8fb8d0cf Giorgos Korfiatis
266 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
267 9024ed2e Giorgos Korfiatis
def update_app_object(request, object_id, extra_context=None):
268 9024ed2e Giorgos Korfiatis
    try:
269 bb528b2e Giorgos Korfiatis
        summary = 'im/projects/projectapplication_form_summary.html'
270 9024ed2e Giorgos Korfiatis
        return _update_object(
271 9024ed2e Giorgos Korfiatis
            request,
272 9024ed2e Giorgos Korfiatis
            object_id=object_id,
273 9024ed2e Giorgos Korfiatis
            template_name='im/projects/projectapplication_form.html',
274 bb528b2e Giorgos Korfiatis
            summary_template_name=summary,
275 9024ed2e Giorgos Korfiatis
            extra_context=extra_context,
276 9024ed2e Giorgos Korfiatis
            post_save_redirect=reverse('project_list'),
277 9024ed2e Giorgos Korfiatis
            form_class=ProjectApplicationForm,
278 9024ed2e Giorgos Korfiatis
            msg=_("The %(verbose_name)s has been received and is under "
279 9024ed2e Giorgos Korfiatis
                  "consideration."))
280 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
281 9024ed2e Giorgos Korfiatis
        messages.error(request, e)
282 9024ed2e Giorgos Korfiatis
283 9024ed2e Giorgos Korfiatis
284 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
285 70e11eaa Sofia Papagiannaki
@cookie_fix
286 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
287 70e11eaa Sofia Papagiannaki
def project_app(request, application_id):
288 70e11eaa Sofia Papagiannaki
    return common_detail(request, application_id, project_view=False)
289 70e11eaa Sofia Papagiannaki
290 8fb8d0cf Giorgos Korfiatis
291 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
292 70e11eaa Sofia Papagiannaki
@cookie_fix
293 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
294 70e11eaa Sofia Papagiannaki
def project_detail(request, chain_id):
295 70e11eaa Sofia Papagiannaki
    return common_detail(request, chain_id)
296 70e11eaa Sofia Papagiannaki
297 8fb8d0cf Giorgos Korfiatis
298 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
299 70e11eaa Sofia Papagiannaki
def addmembers(request, chain_id, addmembers_form):
300 70e11eaa Sofia Papagiannaki
    if addmembers_form.is_valid():
301 70e11eaa Sofia Papagiannaki
        try:
302 70e11eaa Sofia Papagiannaki
            chain_id = int(chain_id)
303 8fb8d0cf Giorgos Korfiatis
            map(lambda u: enroll_member(chain_id,
304 8fb8d0cf Giorgos Korfiatis
                                        u,
305 8fb8d0cf Giorgos Korfiatis
                                        request_user=request.user),
306 70e11eaa Sofia Papagiannaki
                addmembers_form.valid_users)
307 f12bcb3d Giorgos Korfiatis
        except ProjectError as e:
308 70e11eaa Sofia Papagiannaki
            messages.error(request, e)
309 70e11eaa Sofia Papagiannaki
310 460b907d Kostas Papadimitriou
311 d895de37 Giorgos Korfiatis
MEMBERSHIP_STATUS_FILTER = {
312 d895de37 Giorgos Korfiatis
    0: lambda x: x.requested(),
313 d895de37 Giorgos Korfiatis
    1: lambda x: x.any_accepted(),
314 d895de37 Giorgos Korfiatis
}
315 d895de37 Giorgos Korfiatis
316 d895de37 Giorgos Korfiatis
317 460b907d Kostas Papadimitriou
def common_detail(request, chain_or_app_id, project_view=True,
318 460b907d Kostas Papadimitriou
                  template_name='im/projects/project_detail.html',
319 460b907d Kostas Papadimitriou
                  members_status_filter=None):
320 70e11eaa Sofia Papagiannaki
    project = None
321 9df6f541 Kostas Papadimitriou
    approved_members_count = 0
322 9df6f541 Kostas Papadimitriou
    pending_members_count = 0
323 8c8f856b Olga Brani
    remaining_memberships_count = None
324 70e11eaa Sofia Papagiannaki
    if project_view:
325 70e11eaa Sofia Papagiannaki
        chain_id = chain_or_app_id
326 70e11eaa Sofia Papagiannaki
        if request.method == 'POST':
327 70e11eaa Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm(
328 70e11eaa Sofia Papagiannaki
                request.POST,
329 70e11eaa Sofia Papagiannaki
                chain_id=int(chain_id),
330 70e11eaa Sofia Papagiannaki
                request_user=request.user)
331 70e11eaa Sofia Papagiannaki
            with ExceptionHandler(request):
332 70e11eaa Sofia Papagiannaki
                addmembers(request, chain_id, addmembers_form)
333 70e11eaa Sofia Papagiannaki
334 70e11eaa Sofia Papagiannaki
            if addmembers_form.is_valid():
335 70e11eaa Sofia Papagiannaki
                addmembers_form = AddProjectMembersForm()  # clear form data
336 70e11eaa Sofia Papagiannaki
        else:
337 70e11eaa Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm()  # initialize form
338 70e11eaa Sofia Papagiannaki
339 6d583e07 Giorgos Korfiatis
        project = get_object_or_404(Project, pk=chain_id)
340 6d583e07 Giorgos Korfiatis
        application = project.application
341 70e11eaa Sofia Papagiannaki
        if project:
342 d895de37 Giorgos Korfiatis
            members = project.projectmembership_set
343 d895de37 Giorgos Korfiatis
            approved_members_count = project.members_count()
344 460b907d Kostas Papadimitriou
            pending_members_count = project.count_pending_memberships()
345 8c8f856b Olga Brani
            _limit = application.limit_on_members_number
346 8c8f856b Olga Brani
            if _limit is not None:
347 8c8f856b Olga Brani
                remaining_memberships_count = \
348 8c8f856b Olga Brani
                    max(0, _limit - approved_members_count)
349 d895de37 Giorgos Korfiatis
            flt = MEMBERSHIP_STATUS_FILTER.get(members_status_filter)
350 d895de37 Giorgos Korfiatis
            if flt is not None:
351 d895de37 Giorgos Korfiatis
                members = flt(members)
352 f243d667 Giorgos Korfiatis
            else:
353 f243d667 Giorgos Korfiatis
                members = members.associated()
354 d895de37 Giorgos Korfiatis
            members = members.select_related()
355 70e11eaa Sofia Papagiannaki
            members_table = tables.ProjectMembersTable(project,
356 70e11eaa Sofia Papagiannaki
                                                       members,
357 70e11eaa Sofia Papagiannaki
                                                       user=request.user,
358 70e11eaa Sofia Papagiannaki
                                                       prefix="members_")
359 8998f09a Sofia Papagiannaki
            RequestConfig(request, paginate={"per_page": settings.PAGINATE_BY}
360 70e11eaa Sofia Papagiannaki
                          ).configure(members_table)
361 70e11eaa Sofia Papagiannaki
362 70e11eaa Sofia Papagiannaki
        else:
363 70e11eaa Sofia Papagiannaki
            members_table = None
364 70e11eaa Sofia Papagiannaki
365 460b907d Kostas Papadimitriou
    else:
366 460b907d Kostas Papadimitriou
        # is application
367 70e11eaa Sofia Papagiannaki
        application_id = chain_or_app_id
368 70e11eaa Sofia Papagiannaki
        application = get_object_or_404(ProjectApplication, pk=application_id)
369 70e11eaa Sofia Papagiannaki
        members_table = None
370 70e11eaa Sofia Papagiannaki
        addmembers_form = None
371 70e11eaa Sofia Papagiannaki
372 70e11eaa Sofia Papagiannaki
    user = request.user
373 70e11eaa Sofia Papagiannaki
    is_project_admin = user.is_project_admin(application_id=application.id)
374 70e11eaa Sofia Papagiannaki
    is_owner = user.owns_application(application)
375 70e11eaa Sofia Papagiannaki
    if not (is_owner or is_project_admin) and not project_view:
376 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
377 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
378 70e11eaa Sofia Papagiannaki
379 8fb8d0cf Giorgos Korfiatis
    if (
380 8fb8d0cf Giorgos Korfiatis
        not (is_owner or is_project_admin) and project_view and
381 8fb8d0cf Giorgos Korfiatis
        not user.non_owner_can_view(project)
382 8fb8d0cf Giorgos Korfiatis
    ):
383 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
384 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
385 70e11eaa Sofia Papagiannaki
386 dc946891 Giorgos Korfiatis
    membership = user.get_membership(project) if project else None
387 dc946891 Giorgos Korfiatis
    membership_id = membership.id if membership else None
388 70e11eaa Sofia Papagiannaki
    mem_display = user.membership_display(project) if project else None
389 70e11eaa Sofia Papagiannaki
    can_join_req = can_join_request(project, user) if project else False
390 70e11eaa Sofia Papagiannaki
    can_leave_req = can_leave_request(project, user) if project else False
391 70e11eaa Sofia Papagiannaki
392 70e11eaa Sofia Papagiannaki
    return object_detail(
393 70e11eaa Sofia Papagiannaki
        request,
394 70e11eaa Sofia Papagiannaki
        queryset=ProjectApplication.objects.select_related(),
395 70e11eaa Sofia Papagiannaki
        object_id=application.id,
396 460b907d Kostas Papadimitriou
        template_name=template_name,
397 70e11eaa Sofia Papagiannaki
        extra_context={
398 70e11eaa Sofia Papagiannaki
            'project_view': project_view,
399 8eb176ab Kostas Papadimitriou
            'chain_id': chain_or_app_id,
400 8eb176ab Kostas Papadimitriou
            'application': application,
401 460b907d Kostas Papadimitriou
            'addmembers_form': addmembers_form,
402 460b907d Kostas Papadimitriou
            'approved_members_count': approved_members_count,
403 460b907d Kostas Papadimitriou
            'pending_members_count': pending_members_count,
404 70e11eaa Sofia Papagiannaki
            'members_table': members_table,
405 70e11eaa Sofia Papagiannaki
            'owner_mode': is_owner,
406 70e11eaa Sofia Papagiannaki
            'admin_mode': is_project_admin,
407 70e11eaa Sofia Papagiannaki
            'mem_display': mem_display,
408 dc946891 Giorgos Korfiatis
            'membership_id': membership_id,
409 70e11eaa Sofia Papagiannaki
            'can_join_request': can_join_req,
410 70e11eaa Sofia Papagiannaki
            'can_leave_request': can_leave_req,
411 8fb8d0cf Giorgos Korfiatis
            'members_status_filter': members_status_filter,
412 8c8f856b Olga Brani
            'remaining_memberships_count': remaining_memberships_count,
413 0f433ce2 Giorgos Korfiatis
        })
414 0f433ce2 Giorgos Korfiatis
415 70e11eaa Sofia Papagiannaki
416 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
417 70e11eaa Sofia Papagiannaki
@cookie_fix
418 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
419 70e11eaa Sofia Papagiannaki
def project_search(request):
420 70e11eaa Sofia Papagiannaki
    q = request.GET.get('q', '')
421 70e11eaa Sofia Papagiannaki
    form = ProjectSearchForm()
422 70e11eaa Sofia Papagiannaki
    q = q.strip()
423 70e11eaa Sofia Papagiannaki
424 70e11eaa Sofia Papagiannaki
    if request.method == "POST":
425 70e11eaa Sofia Papagiannaki
        form = ProjectSearchForm(request.POST)
426 70e11eaa Sofia Papagiannaki
        if form.is_valid():
427 70e11eaa Sofia Papagiannaki
            q = form.cleaned_data['q'].strip()
428 70e11eaa Sofia Papagiannaki
        else:
429 70e11eaa Sofia Papagiannaki
            q = None
430 70e11eaa Sofia Papagiannaki
431 70e11eaa Sofia Papagiannaki
    if q is None:
432 f243d667 Giorgos Korfiatis
        projects = Project.objects.none()
433 70e11eaa Sofia Papagiannaki
    else:
434 f243d667 Giorgos Korfiatis
        accepted = request.user.projectmembership_set.filter(
435 f243d667 Giorgos Korfiatis
            state__in=ProjectMembership.ACCEPTED_STATES).values_list(
436 f243d667 Giorgos Korfiatis
                'project', flat=True)
437 f243d667 Giorgos Korfiatis
438 f243d667 Giorgos Korfiatis
        projects = Project.objects.search_by_name(q)
439 f243d667 Giorgos Korfiatis
        projects = projects.filter(Project.o_state_q(Project.O_ACTIVE))
440 b10ceccd Giorgos Korfiatis
        projects = projects.exclude(id__in=accepted).select_related(
441 b10ceccd Giorgos Korfiatis
            'application', 'application__owner', 'application__applicant')
442 f243d667 Giorgos Korfiatis
443 b10ceccd Giorgos Korfiatis
    table = get_user_projects_table(projects, user=request.user,
444 b10ceccd Giorgos Korfiatis
                                    prefix="my_projects_")
445 70e11eaa Sofia Papagiannaki
    if request.method == "POST":
446 70e11eaa Sofia Papagiannaki
        table.caption = _('SEARCH RESULTS')
447 70e11eaa Sofia Papagiannaki
    else:
448 70e11eaa Sofia Papagiannaki
        table.caption = _('ALL PROJECTS')
449 70e11eaa Sofia Papagiannaki
450 70e11eaa Sofia Papagiannaki
    return object_list(
451 70e11eaa Sofia Papagiannaki
        request,
452 70e11eaa Sofia Papagiannaki
        projects,
453 70e11eaa Sofia Papagiannaki
        template_name='im/projects/project_list.html',
454 70e11eaa Sofia Papagiannaki
        extra_context={
455 8fb8d0cf Giorgos Korfiatis
            'form': form,
456 8fb8d0cf Giorgos Korfiatis
            'is_search': True,
457 8fb8d0cf Giorgos Korfiatis
            'q': q,
458 8fb8d0cf Giorgos Korfiatis
            'table': table
459 70e11eaa Sofia Papagiannaki
        })
460 70e11eaa Sofia Papagiannaki
461 8fb8d0cf Giorgos Korfiatis
462 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
463 70e11eaa Sofia Papagiannaki
@cookie_fix
464 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
465 70e11eaa Sofia Papagiannaki
def project_join(request, chain_id):
466 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
467 70e11eaa Sofia Papagiannaki
    if not next:
468 70e11eaa Sofia Papagiannaki
        next = reverse('astakos.im.views.project_detail',
469 70e11eaa Sofia Papagiannaki
                       args=(chain_id,))
470 70e11eaa Sofia Papagiannaki
471 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
472 70e11eaa Sofia Papagiannaki
        _project_join(request, chain_id)
473 70e11eaa Sofia Papagiannaki
474 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
475 70e11eaa Sofia Papagiannaki
    return redirect(next)
476 70e11eaa Sofia Papagiannaki
477 70e11eaa Sofia Papagiannaki
478 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
479 70e11eaa Sofia Papagiannaki
def _project_join(request, chain_id):
480 70e11eaa Sofia Papagiannaki
    try:
481 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
482 e1723ca1 Giorgos Korfiatis
        membership = join_project(chain_id, request.user)
483 e1723ca1 Giorgos Korfiatis
        if membership.state != membership.REQUESTED:
484 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_JOINED_PROJECT)
485 70e11eaa Sofia Papagiannaki
        else:
486 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_JOIN_REQUEST_SUBMITTED)
487 70e11eaa Sofia Papagiannaki
        messages.success(request, m)
488 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
489 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
490 70e11eaa Sofia Papagiannaki
491 70e11eaa Sofia Papagiannaki
492 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
493 70e11eaa Sofia Papagiannaki
@cookie_fix
494 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
495 dc946891 Giorgos Korfiatis
def project_leave(request, memb_id):
496 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
497 70e11eaa Sofia Papagiannaki
    if not next:
498 70e11eaa Sofia Papagiannaki
        next = reverse('astakos.im.views.project_list')
499 70e11eaa Sofia Papagiannaki
500 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
501 dc946891 Giorgos Korfiatis
        _project_leave(request, memb_id)
502 70e11eaa Sofia Papagiannaki
503 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
504 70e11eaa Sofia Papagiannaki
    return redirect(next)
505 70e11eaa Sofia Papagiannaki
506 70e11eaa Sofia Papagiannaki
507 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
508 dc946891 Giorgos Korfiatis
def _project_leave(request, memb_id):
509 70e11eaa Sofia Papagiannaki
    try:
510 dc946891 Giorgos Korfiatis
        memb_id = int(memb_id)
511 dc946891 Giorgos Korfiatis
        auto_accepted = leave_project(memb_id, request.user)
512 70e11eaa Sofia Papagiannaki
        if auto_accepted:
513 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_LEFT_PROJECT)
514 70e11eaa Sofia Papagiannaki
        else:
515 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_LEAVE_REQUEST_SUBMITTED)
516 70e11eaa Sofia Papagiannaki
        messages.success(request, m)
517 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
518 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
519 70e11eaa Sofia Papagiannaki
520 70e11eaa Sofia Papagiannaki
521 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
522 70e11eaa Sofia Papagiannaki
@cookie_fix
523 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
524 dc946891 Giorgos Korfiatis
def project_cancel_member(request, memb_id):
525 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
526 70e11eaa Sofia Papagiannaki
    if not next:
527 70e11eaa Sofia Papagiannaki
        next = reverse('astakos.im.views.project_list')
528 70e11eaa Sofia Papagiannaki
529 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
530 dc946891 Giorgos Korfiatis
        _project_cancel_member(request, memb_id)
531 70e11eaa Sofia Papagiannaki
532 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
533 70e11eaa Sofia Papagiannaki
    return redirect(next)
534 70e11eaa Sofia Papagiannaki
535 70e11eaa Sofia Papagiannaki
536 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
537 dc946891 Giorgos Korfiatis
def _project_cancel_member(request, memb_id):
538 70e11eaa Sofia Papagiannaki
    try:
539 dc946891 Giorgos Korfiatis
        cancel_membership(memb_id, request.user)
540 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.USER_REQUEST_CANCELLED)
541 70e11eaa Sofia Papagiannaki
        messages.success(request, m)
542 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
543 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
544 70e11eaa Sofia Papagiannaki
545 70e11eaa Sofia Papagiannaki
546 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
547 70e11eaa Sofia Papagiannaki
@cookie_fix
548 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
549 dc946891 Giorgos Korfiatis
def project_accept_member(request, memb_id):
550 70e11eaa Sofia Papagiannaki
551 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
552 dc946891 Giorgos Korfiatis
        _project_accept_member(request, memb_id)
553 70e11eaa Sofia Papagiannaki
554 59eb6ec5 Kostas Papadimitriou
    return redirect_back(request, 'project_list')
555 70e11eaa Sofia Papagiannaki
556 70e11eaa Sofia Papagiannaki
557 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
558 dc946891 Giorgos Korfiatis
def _project_accept_member(request, memb_id):
559 70e11eaa Sofia Papagiannaki
    try:
560 70e11eaa Sofia Papagiannaki
        memb_id = int(memb_id)
561 dc946891 Giorgos Korfiatis
        m = accept_membership(memb_id, request.user)
562 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
563 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
564 70e11eaa Sofia Papagiannaki
565 70e11eaa Sofia Papagiannaki
    else:
566 70e11eaa Sofia Papagiannaki
        email = escape(m.person.email)
567 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.USER_MEMBERSHIP_ACCEPTED) % email
568 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
569 70e11eaa Sofia Papagiannaki
570 70e11eaa Sofia Papagiannaki
571 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
572 70e11eaa Sofia Papagiannaki
@cookie_fix
573 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
574 dc946891 Giorgos Korfiatis
def project_remove_member(request, memb_id):
575 70e11eaa Sofia Papagiannaki
576 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
577 dc946891 Giorgos Korfiatis
        _project_remove_member(request, memb_id)
578 70e11eaa Sofia Papagiannaki
579 59eb6ec5 Kostas Papadimitriou
    return redirect_back(request, 'project_list')
580 70e11eaa Sofia Papagiannaki
581 70e11eaa Sofia Papagiannaki
582 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
583 dc946891 Giorgos Korfiatis
def _project_remove_member(request, memb_id):
584 70e11eaa Sofia Papagiannaki
    try:
585 70e11eaa Sofia Papagiannaki
        memb_id = int(memb_id)
586 dc946891 Giorgos Korfiatis
        m = remove_membership(memb_id, request.user)
587 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
588 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
589 70e11eaa Sofia Papagiannaki
    else:
590 70e11eaa Sofia Papagiannaki
        email = escape(m.person.email)
591 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.USER_MEMBERSHIP_REMOVED) % email
592 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
593 70e11eaa Sofia Papagiannaki
594 70e11eaa Sofia Papagiannaki
595 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
596 70e11eaa Sofia Papagiannaki
@cookie_fix
597 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
598 dc946891 Giorgos Korfiatis
def project_reject_member(request, memb_id):
599 70e11eaa Sofia Papagiannaki
600 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
601 dc946891 Giorgos Korfiatis
        _project_reject_member(request, memb_id)
602 70e11eaa Sofia Papagiannaki
603 59eb6ec5 Kostas Papadimitriou
    return redirect_back(request, 'project_list')
604 70e11eaa Sofia Papagiannaki
605 70e11eaa Sofia Papagiannaki
606 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
607 dc946891 Giorgos Korfiatis
def _project_reject_member(request, memb_id):
608 70e11eaa Sofia Papagiannaki
    try:
609 70e11eaa Sofia Papagiannaki
        memb_id = int(memb_id)
610 dc946891 Giorgos Korfiatis
        m = reject_membership(memb_id, request.user)
611 f12bcb3d Giorgos Korfiatis
    except ProjectError as e:
612 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
613 70e11eaa Sofia Papagiannaki
    else:
614 70e11eaa Sofia Papagiannaki
        email = escape(m.person.email)
615 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.USER_MEMBERSHIP_REJECTED) % email
616 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
617 70e11eaa Sofia Papagiannaki
618 70e11eaa Sofia Papagiannaki
619 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
620 70e11eaa Sofia Papagiannaki
@signed_terms_required
621 70e11eaa Sofia Papagiannaki
@login_required
622 70e11eaa Sofia Papagiannaki
@cookie_fix
623 70e11eaa Sofia Papagiannaki
def project_app_approve(request, application_id):
624 70e11eaa Sofia Papagiannaki
625 70e11eaa Sofia Papagiannaki
    if not request.user.is_project_admin():
626 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
627 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
628 70e11eaa Sofia Papagiannaki
629 70e11eaa Sofia Papagiannaki
    try:
630 51db2da2 Giorgos Korfiatis
        ProjectApplication.objects.get(id=application_id)
631 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
632 70e11eaa Sofia Papagiannaki
        raise Http404
633 70e11eaa Sofia Papagiannaki
634 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
635 70e11eaa Sofia Papagiannaki
        _project_app_approve(request, application_id)
636 70e11eaa Sofia Papagiannaki
637 70e11eaa Sofia Papagiannaki
    chain_id = get_related_project_id(application_id)
638 f5389699 Kostas Papadimitriou
    if not chain_id:
639 f5389699 Kostas Papadimitriou
        return redirect_back(request, 'project_list')
640 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(chain_id,)))
641 70e11eaa Sofia Papagiannaki
642 70e11eaa Sofia Papagiannaki
643 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
644 70e11eaa Sofia Papagiannaki
def _project_app_approve(request, application_id):
645 70e11eaa Sofia Papagiannaki
    approve_application(application_id)
646 70e11eaa Sofia Papagiannaki
647 70e11eaa Sofia Papagiannaki
648 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
649 70e11eaa Sofia Papagiannaki
@signed_terms_required
650 70e11eaa Sofia Papagiannaki
@login_required
651 70e11eaa Sofia Papagiannaki
@cookie_fix
652 70e11eaa Sofia Papagiannaki
def project_app_deny(request, application_id):
653 70e11eaa Sofia Papagiannaki
654 70e11eaa Sofia Papagiannaki
    reason = request.POST.get('reason', None)
655 70e11eaa Sofia Papagiannaki
    if not reason:
656 70e11eaa Sofia Papagiannaki
        reason = None
657 70e11eaa Sofia Papagiannaki
658 70e11eaa Sofia Papagiannaki
    if not request.user.is_project_admin():
659 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
660 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
661 70e11eaa Sofia Papagiannaki
662 70e11eaa Sofia Papagiannaki
    try:
663 51db2da2 Giorgos Korfiatis
        ProjectApplication.objects.get(id=application_id)
664 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
665 70e11eaa Sofia Papagiannaki
        raise Http404
666 70e11eaa Sofia Papagiannaki
667 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
668 70e11eaa Sofia Papagiannaki
        _project_app_deny(request, application_id, reason)
669 70e11eaa Sofia Papagiannaki
670 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_list'))
671 70e11eaa Sofia Papagiannaki
672 70e11eaa Sofia Papagiannaki
673 a3e3917f Giorgos Korfiatis
@transaction.commit_on_success
674 70e11eaa Sofia Papagiannaki
def _project_app_deny(request, application_id, reason):
675 70e11eaa Sofia Papagiannaki
    deny_application(application_id, reason=reason)
676 70e11eaa Sofia Papagiannaki
677 70e11eaa Sofia Papagiannaki
678 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
679 70e11eaa Sofia Papagiannaki
@signed_terms_required
680 70e11eaa Sofia Papagiannaki
@login_required
681 70e11eaa Sofia Papagiannaki
@cookie_fix
682 70e11eaa Sofia Papagiannaki
def project_app_dismiss(request, application_id):
683 70e11eaa Sofia Papagiannaki
    try:
684 70e11eaa Sofia Papagiannaki
        app = ProjectApplication.objects.get(id=application_id)
685 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
686 70e11eaa Sofia Papagiannaki
        raise Http404
687 70e11eaa Sofia Papagiannaki
688 70e11eaa Sofia Papagiannaki
    if not request.user.owns_application(app):
689 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
690 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
691 70e11eaa Sofia Papagiannaki
692 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
693 70e11eaa Sofia Papagiannaki
        _project_app_dismiss(request, application_id)
694 70e11eaa Sofia Papagiannaki
695 70e11eaa Sofia Papagiannaki
    chain_id = None
696 70e11eaa Sofia Papagiannaki
    chain_id = get_related_project_id(application_id)
697 70e11eaa Sofia Papagiannaki
    if chain_id:
698 70e11eaa Sofia Papagiannaki
        next = reverse('project_detail', args=(chain_id,))
699 70e11eaa Sofia Papagiannaki
    else:
700 70e11eaa Sofia Papagiannaki
        next = reverse('project_list')
701 70e11eaa Sofia Papagiannaki
    return redirect(next)
702 70e11eaa Sofia Papagiannaki
703 70e11eaa Sofia Papagiannaki
704 70e11eaa Sofia Papagiannaki
def _project_app_dismiss(request, application_id):
705 70e11eaa Sofia Papagiannaki
    # XXX: dismiss application also does authorization
706 70e11eaa Sofia Papagiannaki
    dismiss_application(application_id, request_user=request.user)
707 460b907d Kostas Papadimitriou
708 460b907d Kostas Papadimitriou
709 460b907d Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
710 460b907d Kostas Papadimitriou
@valid_astakos_user_required
711 460b907d Kostas Papadimitriou
def project_members(request, chain_id, members_status_filter=None,
712 460b907d Kostas Papadimitriou
                    template_name='im/projects/project_members.html'):
713 6d583e07 Giorgos Korfiatis
    project = get_object_or_404(Project, pk=chain_id)
714 7971e5da Kostas Papadimitriou
715 7971e5da Kostas Papadimitriou
    user = request.user
716 7971e5da Kostas Papadimitriou
    if not user.owns_project(project) and not user.is_project_admin():
717 7971e5da Kostas Papadimitriou
        return redirect(reverse('index'))
718 7971e5da Kostas Papadimitriou
719 460b907d Kostas Papadimitriou
    return common_detail(request, chain_id,
720 460b907d Kostas Papadimitriou
                         members_status_filter=members_status_filter,
721 460b907d Kostas Papadimitriou
                         template_name=template_name)
722 c363a678 Kostas Papadimitriou
723 c363a678 Kostas Papadimitriou
724 c363a678 Kostas Papadimitriou
@require_http_methods(["POST"])
725 c363a678 Kostas Papadimitriou
@valid_astakos_user_required
726 c363a678 Kostas Papadimitriou
def project_members_action(request, chain_id, action=None, redirect_to=''):
727 c363a678 Kostas Papadimitriou
728 c363a678 Kostas Papadimitriou
    actions_map = {
729 c363a678 Kostas Papadimitriou
        'remove': _project_remove_member,
730 c363a678 Kostas Papadimitriou
        'accept': _project_accept_member,
731 c363a678 Kostas Papadimitriou
        'reject': _project_reject_member
732 c363a678 Kostas Papadimitriou
    }
733 c363a678 Kostas Papadimitriou
734 c363a678 Kostas Papadimitriou
    if not action in actions_map.keys():
735 c363a678 Kostas Papadimitriou
        raise PermissionDenied
736 c363a678 Kostas Papadimitriou
737 c363a678 Kostas Papadimitriou
    member_ids = request.POST.getlist('members')
738 6d583e07 Giorgos Korfiatis
    project = get_object_or_404(Project, pk=chain_id)
739 c363a678 Kostas Papadimitriou
740 c363a678 Kostas Papadimitriou
    user = request.user
741 c363a678 Kostas Papadimitriou
    if not user.owns_project(project) and not user.is_project_admin():
742 c363a678 Kostas Papadimitriou
        return redirect(reverse('index'))
743 c363a678 Kostas Papadimitriou
744 06086f91 Kostas Papadimitriou
    logger.info("Batch members action from %s (chain: %r, action: %s, "
745 06086f91 Kostas Papadimitriou
                "members: %r)", user.log_display, chain_id, action, member_ids)
746 c363a678 Kostas Papadimitriou
747 c363a678 Kostas Papadimitriou
    action_func = actions_map.get(action)
748 c363a678 Kostas Papadimitriou
    for member_id in member_ids:
749 c363a678 Kostas Papadimitriou
        member_id = int(member_id)
750 c363a678 Kostas Papadimitriou
        with ExceptionHandler(request):
751 dc946891 Giorgos Korfiatis
            action_func(request, member_id)
752 c363a678 Kostas Papadimitriou
753 59eb6ec5 Kostas Papadimitriou
    return redirect_back(request, 'project_list')