Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (23.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.contrib.auth.decorators import login_required
44 70e11eaa Sofia Papagiannaki
from django.core.urlresolvers import reverse
45 3e0a032d Sofia Papagiannaki
from django.http import Http404
46 70e11eaa Sofia Papagiannaki
from django.shortcuts import redirect
47 70e11eaa Sofia Papagiannaki
from django.utils.html import escape
48 70e11eaa Sofia Papagiannaki
from django.utils.translation import ugettext as _
49 70e11eaa Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
50 3e0a032d Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
51 70e11eaa Sofia Papagiannaki
from django.views.decorators.http import require_http_methods
52 70e11eaa Sofia Papagiannaki
from django.db.models import Q
53 70e11eaa Sofia Papagiannaki
54 70e11eaa Sofia Papagiannaki
from snf_django.lib.db.transaction import commit_on_success_strict
55 70e11eaa Sofia Papagiannaki
56 70e11eaa Sofia Papagiannaki
import astakos.im.messages as astakos_messages
57 70e11eaa Sofia Papagiannaki
58 70e11eaa Sofia Papagiannaki
from astakos.im import tables
59 460b907d Kostas Papadimitriou
from astakos.im.models import ProjectApplication, ProjectMembership
60 3e0a032d Sofia Papagiannaki
from astakos.im.util import get_context, restrict_next
61 3e0a032d Sofia Papagiannaki
from astakos.im.forms import ProjectApplicationForm, AddProjectMembersForm, \
62 3e0a032d Sofia Papagiannaki
    ProjectSearchForm
63 3e0a032d Sofia Papagiannaki
from astakos.im.functions import check_pending_app_quota, accept_membership, \
64 3e0a032d Sofia Papagiannaki
    reject_membership, remove_membership, cancel_membership, leave_project, \
65 3e0a032d Sofia Papagiannaki
    join_project, enroll_member, can_join_request, can_leave_request, \
66 3e0a032d Sofia Papagiannaki
    get_related_project_id, get_by_chain_or_404, approve_application, \
67 3e0a032d Sofia Papagiannaki
    deny_application, cancel_application, dismiss_application
68 8998f09a Sofia Papagiannaki
from astakos.im import settings
69 70e11eaa Sofia Papagiannaki
from astakos.im.views.util import render_response, _create_object, \
70 9fb7a900 Giorgos Korfiatis
    _update_object, _resources_catalog, ExceptionHandler
71 70e11eaa Sofia Papagiannaki
from astakos.im.views.decorators import cookie_fix, signed_terms_required,\
72 3e0a032d Sofia Papagiannaki
    valid_astakos_user_required
73 70e11eaa Sofia Papagiannaki
74 70e11eaa Sofia Papagiannaki
logger = logging.getLogger(__name__)
75 70e11eaa Sofia Papagiannaki
76 70e11eaa Sofia Papagiannaki
77 70e11eaa Sofia Papagiannaki
@cookie_fix
78 70e11eaa Sofia Papagiannaki
def how_it_works(request):
79 70e11eaa Sofia Papagiannaki
    return render_response(
80 70e11eaa Sofia Papagiannaki
        'im/how_it_works.html',
81 70e11eaa Sofia Papagiannaki
        context_instance=get_context(request))
82 70e11eaa Sofia Papagiannaki
83 70e11eaa Sofia Papagiannaki
84 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
85 70e11eaa Sofia Papagiannaki
@cookie_fix
86 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
87 70e11eaa Sofia Papagiannaki
def project_add(request):
88 70e11eaa Sofia Papagiannaki
    user = request.user
89 70e11eaa Sofia Papagiannaki
    if not user.is_project_admin():
90 70e11eaa Sofia Papagiannaki
        ok, limit = check_pending_app_quota(user)
91 70e11eaa Sofia Papagiannaki
        if not ok:
92 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_ADD) % limit
93 70e11eaa Sofia Papagiannaki
            messages.error(request, m)
94 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_list')
95 8998f09a Sofia Papagiannaki
            next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
96 70e11eaa Sofia Papagiannaki
            return redirect(next)
97 70e11eaa Sofia Papagiannaki
98 70e11eaa Sofia Papagiannaki
    details_fields = ["name", "homepage", "description", "start_date",
99 70e11eaa Sofia Papagiannaki
                      "end_date", "comments"]
100 70e11eaa Sofia Papagiannaki
    membership_fields = ["member_join_policy", "member_leave_policy",
101 70e11eaa Sofia Papagiannaki
                         "limit_on_members_number"]
102 70e11eaa Sofia Papagiannaki
    resource_catalog, resource_groups = _resources_catalog(for_project=True)
103 70e11eaa Sofia Papagiannaki
    if resource_catalog is False:
104 70e11eaa Sofia Papagiannaki
        # on fail resource_groups contains the result object
105 70e11eaa Sofia Papagiannaki
        result = resource_groups
106 70e11eaa Sofia Papagiannaki
        messages.error(request, 'Unable to retrieve system resources: %s' %
107 70e11eaa Sofia Papagiannaki
                       result.reason)
108 70e11eaa Sofia Papagiannaki
    extra_context = {
109 70e11eaa Sofia Papagiannaki
        'resource_catalog': resource_catalog,
110 70e11eaa Sofia Papagiannaki
        'resource_groups': resource_groups,
111 70e11eaa Sofia Papagiannaki
        'show_form': True,
112 70e11eaa Sofia Papagiannaki
        'details_fields': details_fields,
113 70e11eaa Sofia Papagiannaki
        'membership_fields': membership_fields}
114 70e11eaa Sofia Papagiannaki
115 70e11eaa Sofia Papagiannaki
    response = None
116 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
117 70e11eaa Sofia Papagiannaki
        response = _create_object(
118 70e11eaa Sofia Papagiannaki
            request,
119 70e11eaa Sofia Papagiannaki
            template_name='im/projects/projectapplication_form.html',
120 70e11eaa Sofia Papagiannaki
            extra_context=extra_context,
121 70e11eaa Sofia Papagiannaki
            post_save_redirect=reverse('project_list'),
122 70e11eaa Sofia Papagiannaki
            form_class=ProjectApplicationForm,
123 70e11eaa Sofia Papagiannaki
            msg=_("The %(verbose_name)s has been received and "
124 70e11eaa Sofia Papagiannaki
                  "is under consideration."),
125 70e11eaa Sofia Papagiannaki
            )
126 70e11eaa Sofia Papagiannaki
127 70e11eaa Sofia Papagiannaki
    if response is not None:
128 70e11eaa Sofia Papagiannaki
        return response
129 70e11eaa Sofia Papagiannaki
130 70e11eaa Sofia Papagiannaki
    next = reverse('astakos.im.views.project_list')
131 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
132 70e11eaa Sofia Papagiannaki
    return redirect(next)
133 70e11eaa Sofia Papagiannaki
134 70e11eaa Sofia Papagiannaki
135 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET"])
136 70e11eaa Sofia Papagiannaki
@cookie_fix
137 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
138 70e11eaa Sofia Papagiannaki
def project_list(request):
139 70e11eaa Sofia Papagiannaki
    projects = ProjectApplication.objects.user_accessible_projects(request.user).select_related()
140 70e11eaa Sofia Papagiannaki
    table = tables.UserProjectApplicationsTable(projects, user=request.user,
141 70e11eaa Sofia Papagiannaki
                                                prefix="my_projects_")
142 8998f09a Sofia Papagiannaki
    RequestConfig(request, paginate={"per_page": settings.PAGINATE_BY}).configure(table)
143 70e11eaa Sofia Papagiannaki
144 70e11eaa Sofia Papagiannaki
    return object_list(
145 70e11eaa Sofia Papagiannaki
        request,
146 70e11eaa Sofia Papagiannaki
        projects,
147 70e11eaa Sofia Papagiannaki
        template_name='im/projects/project_list.html',
148 70e11eaa Sofia Papagiannaki
        extra_context={
149 70e11eaa Sofia Papagiannaki
            'is_search':False,
150 70e11eaa Sofia Papagiannaki
            'table': table,
151 70e11eaa Sofia Papagiannaki
        })
152 70e11eaa Sofia Papagiannaki
153 70e11eaa Sofia Papagiannaki
154 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
155 70e11eaa Sofia Papagiannaki
@cookie_fix
156 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
157 70e11eaa Sofia Papagiannaki
def project_app_cancel(request, application_id):
158 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
159 70e11eaa Sofia Papagiannaki
    chain_id = None
160 70e11eaa Sofia Papagiannaki
161 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
162 70e11eaa Sofia Papagiannaki
        chain_id = _project_app_cancel(request, application_id)
163 70e11eaa Sofia Papagiannaki
164 70e11eaa Sofia Papagiannaki
    if not next:
165 70e11eaa Sofia Papagiannaki
        if chain_id:
166 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_detail', args=(chain_id,))
167 70e11eaa Sofia Papagiannaki
        else:
168 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_list')
169 70e11eaa Sofia Papagiannaki
170 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
171 70e11eaa Sofia Papagiannaki
    return redirect(next)
172 70e11eaa Sofia Papagiannaki
173 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
174 70e11eaa Sofia Papagiannaki
def _project_app_cancel(request, application_id):
175 70e11eaa Sofia Papagiannaki
    chain_id = None
176 70e11eaa Sofia Papagiannaki
    try:
177 70e11eaa Sofia Papagiannaki
        application_id = int(application_id)
178 70e11eaa Sofia Papagiannaki
        chain_id = get_related_project_id(application_id)
179 70e11eaa Sofia Papagiannaki
        cancel_application(application_id, request.user)
180 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
181 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
182 70e11eaa Sofia Papagiannaki
183 70e11eaa Sofia Papagiannaki
    else:
184 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.APPLICATION_CANCELLED)
185 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
186 70e11eaa Sofia Papagiannaki
        return chain_id
187 70e11eaa Sofia Papagiannaki
188 70e11eaa Sofia Papagiannaki
189 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
190 70e11eaa Sofia Papagiannaki
@cookie_fix
191 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
192 70e11eaa Sofia Papagiannaki
def project_modify(request, application_id):
193 70e11eaa Sofia Papagiannaki
194 70e11eaa Sofia Papagiannaki
    try:
195 70e11eaa Sofia Papagiannaki
        app = ProjectApplication.objects.get(id=application_id)
196 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
197 70e11eaa Sofia Papagiannaki
        raise Http404
198 70e11eaa Sofia Papagiannaki
199 70e11eaa Sofia Papagiannaki
    user = request.user
200 70e11eaa Sofia Papagiannaki
    if not (user.owns_application(app) or user.is_project_admin(app.id)):
201 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
202 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
203 70e11eaa Sofia Papagiannaki
204 70e11eaa Sofia Papagiannaki
    if not user.is_project_admin():
205 70e11eaa Sofia Papagiannaki
        owner = app.owner
206 70e11eaa Sofia Papagiannaki
        ok, limit = check_pending_app_quota(owner, precursor=app)
207 70e11eaa Sofia Papagiannaki
        if not ok:
208 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_MODIFY) % limit
209 70e11eaa Sofia Papagiannaki
            messages.error(request, m)
210 70e11eaa Sofia Papagiannaki
            next = reverse('astakos.im.views.project_list')
211 8998f09a Sofia Papagiannaki
            next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
212 70e11eaa Sofia Papagiannaki
            return redirect(next)
213 70e11eaa Sofia Papagiannaki
214 70e11eaa Sofia Papagiannaki
    details_fields = ["name", "homepage", "description", "start_date",
215 70e11eaa Sofia Papagiannaki
                      "end_date", "comments"]
216 70e11eaa Sofia Papagiannaki
    membership_fields = ["member_join_policy", "member_leave_policy",
217 70e11eaa Sofia Papagiannaki
                         "limit_on_members_number"]
218 70e11eaa Sofia Papagiannaki
    resource_catalog, resource_groups = _resources_catalog(for_project=True)
219 70e11eaa Sofia Papagiannaki
    if resource_catalog is False:
220 70e11eaa Sofia Papagiannaki
        # on fail resource_groups contains the result object
221 70e11eaa Sofia Papagiannaki
        result = resource_groups
222 70e11eaa Sofia Papagiannaki
        messages.error(request, 'Unable to retrieve system resources: %s' %
223 70e11eaa Sofia Papagiannaki
                       result.reason)
224 70e11eaa Sofia Papagiannaki
    extra_context = {
225 70e11eaa Sofia Papagiannaki
        'resource_catalog': resource_catalog,
226 70e11eaa Sofia Papagiannaki
        'resource_groups': resource_groups,
227 70e11eaa Sofia Papagiannaki
        'show_form': True,
228 70e11eaa Sofia Papagiannaki
        'details_fields': details_fields,
229 70e11eaa Sofia Papagiannaki
        'update_form': True,
230 70e11eaa Sofia Papagiannaki
        'membership_fields': membership_fields
231 70e11eaa Sofia Papagiannaki
    }
232 70e11eaa Sofia Papagiannaki
233 70e11eaa Sofia Papagiannaki
    response = None
234 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
235 70e11eaa Sofia Papagiannaki
        response = _update_object(
236 70e11eaa Sofia Papagiannaki
            request,
237 70e11eaa Sofia Papagiannaki
            object_id=application_id,
238 70e11eaa Sofia Papagiannaki
            template_name='im/projects/projectapplication_form.html',
239 70e11eaa Sofia Papagiannaki
            extra_context=extra_context,
240 70e11eaa Sofia Papagiannaki
            post_save_redirect=reverse('project_list'),
241 70e11eaa Sofia Papagiannaki
            form_class=ProjectApplicationForm,
242 70e11eaa Sofia Papagiannaki
            msg=_("The %(verbose_name)s has been received and is under "
243 70e11eaa Sofia Papagiannaki
                  "consideration."))
244 70e11eaa Sofia Papagiannaki
245 70e11eaa Sofia Papagiannaki
    if response is not None:
246 70e11eaa Sofia Papagiannaki
        return response
247 70e11eaa Sofia Papagiannaki
248 70e11eaa Sofia Papagiannaki
    next = reverse('astakos.im.views.project_list')
249 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
250 70e11eaa Sofia Papagiannaki
    return redirect(next)
251 70e11eaa Sofia Papagiannaki
252 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
253 70e11eaa Sofia Papagiannaki
@cookie_fix
254 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
255 70e11eaa Sofia Papagiannaki
def project_app(request, application_id):
256 70e11eaa Sofia Papagiannaki
    return common_detail(request, application_id, project_view=False)
257 70e11eaa Sofia Papagiannaki
258 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
259 70e11eaa Sofia Papagiannaki
@cookie_fix
260 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
261 70e11eaa Sofia Papagiannaki
def project_detail(request, chain_id):
262 70e11eaa Sofia Papagiannaki
    return common_detail(request, chain_id)
263 70e11eaa Sofia Papagiannaki
264 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
265 70e11eaa Sofia Papagiannaki
def addmembers(request, chain_id, addmembers_form):
266 70e11eaa Sofia Papagiannaki
    if addmembers_form.is_valid():
267 70e11eaa Sofia Papagiannaki
        try:
268 70e11eaa Sofia Papagiannaki
            chain_id = int(chain_id)
269 70e11eaa Sofia Papagiannaki
            map(lambda u: enroll_member(
270 70e11eaa Sofia Papagiannaki
                    chain_id,
271 70e11eaa Sofia Papagiannaki
                    u,
272 70e11eaa Sofia Papagiannaki
                    request_user=request.user),
273 70e11eaa Sofia Papagiannaki
                addmembers_form.valid_users)
274 70e11eaa Sofia Papagiannaki
        except (IOError, PermissionDenied), e:
275 70e11eaa Sofia Papagiannaki
            messages.error(request, e)
276 70e11eaa Sofia Papagiannaki
277 460b907d Kostas Papadimitriou
278 460b907d Kostas Papadimitriou
def common_detail(request, chain_or_app_id, project_view=True,
279 460b907d Kostas Papadimitriou
                  template_name='im/projects/project_detail.html',
280 460b907d Kostas Papadimitriou
                  members_status_filter=None):
281 70e11eaa Sofia Papagiannaki
    project = None
282 70e11eaa Sofia Papagiannaki
    if project_view:
283 70e11eaa Sofia Papagiannaki
        chain_id = chain_or_app_id
284 70e11eaa Sofia Papagiannaki
        if request.method == 'POST':
285 70e11eaa Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm(
286 70e11eaa Sofia Papagiannaki
                request.POST,
287 70e11eaa Sofia Papagiannaki
                chain_id=int(chain_id),
288 70e11eaa Sofia Papagiannaki
                request_user=request.user)
289 70e11eaa Sofia Papagiannaki
            with ExceptionHandler(request):
290 70e11eaa Sofia Papagiannaki
                addmembers(request, chain_id, addmembers_form)
291 70e11eaa Sofia Papagiannaki
292 70e11eaa Sofia Papagiannaki
            if addmembers_form.is_valid():
293 70e11eaa Sofia Papagiannaki
                addmembers_form = AddProjectMembersForm()  # clear form data
294 70e11eaa Sofia Papagiannaki
        else:
295 70e11eaa Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm()  # initialize form
296 70e11eaa Sofia Papagiannaki
297 460b907d Kostas Papadimitriou
        approved_members_count = 0
298 460b907d Kostas Papadimitriou
        pending_members_count = 0
299 460b907d Kostas Papadimitriou
        remaining_memberships_count = 0
300 70e11eaa Sofia Papagiannaki
        project, application = get_by_chain_or_404(chain_id)
301 70e11eaa Sofia Papagiannaki
        if project:
302 70e11eaa Sofia Papagiannaki
            members = project.projectmembership_set.select_related()
303 460b907d Kostas Papadimitriou
            approved_members_count = \
304 460b907d Kostas Papadimitriou
                    project.count_actually_accepted_memberships()
305 460b907d Kostas Papadimitriou
            pending_members_count = project.count_pending_memberships()
306 460b907d Kostas Papadimitriou
            if members_status_filter in (ProjectMembership.REQUESTED,
307 460b907d Kostas Papadimitriou
                ProjectMembership.ACCEPTED):
308 460b907d Kostas Papadimitriou
                members = members.filter(state=members_status_filter)
309 70e11eaa Sofia Papagiannaki
            members_table = tables.ProjectMembersTable(project,
310 70e11eaa Sofia Papagiannaki
                                                       members,
311 70e11eaa Sofia Papagiannaki
                                                       user=request.user,
312 70e11eaa Sofia Papagiannaki
                                                       prefix="members_")
313 8998f09a Sofia Papagiannaki
            RequestConfig(request, paginate={"per_page": settings.PAGINATE_BY}
314 70e11eaa Sofia Papagiannaki
                          ).configure(members_table)
315 70e11eaa Sofia Papagiannaki
316 70e11eaa Sofia Papagiannaki
        else:
317 70e11eaa Sofia Papagiannaki
            members_table = None
318 70e11eaa Sofia Papagiannaki
319 460b907d Kostas Papadimitriou
    else:
320 460b907d Kostas Papadimitriou
        # is application
321 70e11eaa Sofia Papagiannaki
        application_id = chain_or_app_id
322 70e11eaa Sofia Papagiannaki
        application = get_object_or_404(ProjectApplication, pk=application_id)
323 70e11eaa Sofia Papagiannaki
        members_table = None
324 70e11eaa Sofia Papagiannaki
        addmembers_form = None
325 70e11eaa Sofia Papagiannaki
326 70e11eaa Sofia Papagiannaki
    modifications_table = None
327 70e11eaa Sofia Papagiannaki
328 70e11eaa Sofia Papagiannaki
    user = request.user
329 70e11eaa Sofia Papagiannaki
    is_project_admin = user.is_project_admin(application_id=application.id)
330 70e11eaa Sofia Papagiannaki
    is_owner = user.owns_application(application)
331 70e11eaa Sofia Papagiannaki
    if not (is_owner or is_project_admin) and not project_view:
332 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
333 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
334 70e11eaa Sofia Papagiannaki
335 70e11eaa Sofia Papagiannaki
    if (not (is_owner or is_project_admin) and project_view and
336 70e11eaa Sofia Papagiannaki
        not user.non_owner_can_view(project)):
337 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
338 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
339 70e11eaa Sofia Papagiannaki
340 70e11eaa Sofia Papagiannaki
    following_applications = list(application.pending_modifications())
341 70e11eaa Sofia Papagiannaki
    following_applications.reverse()
342 70e11eaa Sofia Papagiannaki
    modifications_table = (
343 70e11eaa Sofia Papagiannaki
        tables.ProjectModificationApplicationsTable(following_applications,
344 70e11eaa Sofia Papagiannaki
                                                    user=request.user,
345 70e11eaa Sofia Papagiannaki
                                                    prefix="modifications_"))
346 70e11eaa Sofia Papagiannaki
347 70e11eaa Sofia Papagiannaki
    mem_display = user.membership_display(project) if project else None
348 70e11eaa Sofia Papagiannaki
    can_join_req = can_join_request(project, user) if project else False
349 70e11eaa Sofia Papagiannaki
    can_leave_req = can_leave_request(project, user) if project else False
350 70e11eaa Sofia Papagiannaki
351 70e11eaa Sofia Papagiannaki
    return object_detail(
352 70e11eaa Sofia Papagiannaki
        request,
353 70e11eaa Sofia Papagiannaki
        queryset=ProjectApplication.objects.select_related(),
354 70e11eaa Sofia Papagiannaki
        object_id=application.id,
355 460b907d Kostas Papadimitriou
        template_name=template_name,
356 70e11eaa Sofia Papagiannaki
        extra_context={
357 70e11eaa Sofia Papagiannaki
            'project_view': project_view,
358 9b846781 Kostas Papadimitriou
            'chain_id': chain_or_app_id,
359 9b846781 Kostas Papadimitriou
            'application': application,
360 460b907d Kostas Papadimitriou
            'addmembers_form': addmembers_form,
361 460b907d Kostas Papadimitriou
            'approved_members_count': approved_members_count,
362 460b907d Kostas Papadimitriou
            'pending_members_count': pending_members_count,
363 70e11eaa Sofia Papagiannaki
            'members_table': members_table,
364 70e11eaa Sofia Papagiannaki
            'owner_mode': is_owner,
365 70e11eaa Sofia Papagiannaki
            'admin_mode': is_project_admin,
366 70e11eaa Sofia Papagiannaki
            'modifications_table': modifications_table,
367 70e11eaa Sofia Papagiannaki
            'mem_display': mem_display,
368 70e11eaa Sofia Papagiannaki
            'can_join_request': can_join_req,
369 70e11eaa Sofia Papagiannaki
            'can_leave_request': can_leave_req,
370 460b907d Kostas Papadimitriou
            'members_status_filter':members_status_filter,
371 70e11eaa Sofia Papagiannaki
            })
372 70e11eaa Sofia Papagiannaki
373 70e11eaa Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
374 70e11eaa Sofia Papagiannaki
@cookie_fix
375 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
376 70e11eaa Sofia Papagiannaki
def project_search(request):
377 70e11eaa Sofia Papagiannaki
    q = request.GET.get('q', '')
378 70e11eaa Sofia Papagiannaki
    form = ProjectSearchForm()
379 70e11eaa Sofia Papagiannaki
    q = q.strip()
380 70e11eaa Sofia Papagiannaki
381 70e11eaa Sofia Papagiannaki
    if request.method == "POST":
382 70e11eaa Sofia Papagiannaki
        form = ProjectSearchForm(request.POST)
383 70e11eaa Sofia Papagiannaki
        if form.is_valid():
384 70e11eaa Sofia Papagiannaki
            q = form.cleaned_data['q'].strip()
385 70e11eaa Sofia Papagiannaki
        else:
386 70e11eaa Sofia Papagiannaki
            q = None
387 70e11eaa Sofia Papagiannaki
388 70e11eaa Sofia Papagiannaki
    if q is None:
389 70e11eaa Sofia Papagiannaki
        projects = ProjectApplication.objects.none()
390 70e11eaa Sofia Papagiannaki
    else:
391 70e11eaa Sofia Papagiannaki
        accepted_projects = request.user.projectmembership_set.filter(
392 70e11eaa Sofia Papagiannaki
            ~Q(acceptance_date__isnull=True)).values_list('project', flat=True)
393 70e11eaa Sofia Papagiannaki
        projects = ProjectApplication.objects.search_by_name(q)
394 70e11eaa Sofia Papagiannaki
        projects = projects.filter(~Q(project__last_approval_date__isnull=True))
395 70e11eaa Sofia Papagiannaki
        projects = projects.exclude(project__in=accepted_projects)
396 70e11eaa Sofia Papagiannaki
397 70e11eaa Sofia Papagiannaki
    table = tables.UserProjectApplicationsTable(projects, user=request.user,
398 70e11eaa Sofia Papagiannaki
                                                prefix="my_projects_")
399 70e11eaa Sofia Papagiannaki
    if request.method == "POST":
400 70e11eaa Sofia Papagiannaki
        table.caption = _('SEARCH RESULTS')
401 70e11eaa Sofia Papagiannaki
    else:
402 70e11eaa Sofia Papagiannaki
        table.caption = _('ALL PROJECTS')
403 70e11eaa Sofia Papagiannaki
404 8998f09a Sofia Papagiannaki
    RequestConfig(request, paginate={"per_page": settings.PAGINATE_BY}).configure(table)
405 70e11eaa Sofia Papagiannaki
406 70e11eaa Sofia Papagiannaki
    return object_list(
407 70e11eaa Sofia Papagiannaki
        request,
408 70e11eaa Sofia Papagiannaki
        projects,
409 70e11eaa Sofia Papagiannaki
        template_name='im/projects/project_list.html',
410 70e11eaa Sofia Papagiannaki
        extra_context={
411 70e11eaa Sofia Papagiannaki
          'form': form,
412 70e11eaa Sofia Papagiannaki
          'is_search': True,
413 70e11eaa Sofia Papagiannaki
          'q': q,
414 70e11eaa Sofia Papagiannaki
          'table': table
415 70e11eaa Sofia Papagiannaki
        })
416 70e11eaa Sofia Papagiannaki
417 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
418 70e11eaa Sofia Papagiannaki
@cookie_fix
419 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
420 70e11eaa Sofia Papagiannaki
def project_join(request, chain_id):
421 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
422 70e11eaa Sofia Papagiannaki
    if not next:
423 70e11eaa Sofia Papagiannaki
        next = reverse('astakos.im.views.project_detail',
424 70e11eaa Sofia Papagiannaki
                       args=(chain_id,))
425 70e11eaa Sofia Papagiannaki
426 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
427 70e11eaa Sofia Papagiannaki
        _project_join(request, chain_id)
428 70e11eaa Sofia Papagiannaki
429 70e11eaa Sofia Papagiannaki
430 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
431 70e11eaa Sofia Papagiannaki
    return redirect(next)
432 70e11eaa Sofia Papagiannaki
433 70e11eaa Sofia Papagiannaki
434 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
435 70e11eaa Sofia Papagiannaki
def _project_join(request, chain_id):
436 70e11eaa Sofia Papagiannaki
    try:
437 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
438 70e11eaa Sofia Papagiannaki
        auto_accepted = join_project(chain_id, request.user)
439 70e11eaa Sofia Papagiannaki
        if auto_accepted:
440 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_JOINED_PROJECT)
441 70e11eaa Sofia Papagiannaki
        else:
442 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_JOIN_REQUEST_SUBMITTED)
443 70e11eaa Sofia Papagiannaki
        messages.success(request, m)
444 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
445 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
446 70e11eaa Sofia Papagiannaki
447 70e11eaa Sofia Papagiannaki
448 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
449 70e11eaa Sofia Papagiannaki
@cookie_fix
450 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
451 70e11eaa Sofia Papagiannaki
def project_leave(request, chain_id):
452 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
453 70e11eaa Sofia Papagiannaki
    if not next:
454 70e11eaa Sofia Papagiannaki
        next = reverse('astakos.im.views.project_list')
455 70e11eaa Sofia Papagiannaki
456 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
457 70e11eaa Sofia Papagiannaki
        _project_leave(request, chain_id)
458 70e11eaa Sofia Papagiannaki
459 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
460 70e11eaa Sofia Papagiannaki
    return redirect(next)
461 70e11eaa Sofia Papagiannaki
462 70e11eaa Sofia Papagiannaki
463 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
464 70e11eaa Sofia Papagiannaki
def _project_leave(request, chain_id):
465 70e11eaa Sofia Papagiannaki
    try:
466 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
467 70e11eaa Sofia Papagiannaki
        auto_accepted = leave_project(chain_id, request.user)
468 70e11eaa Sofia Papagiannaki
        if auto_accepted:
469 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_LEFT_PROJECT)
470 70e11eaa Sofia Papagiannaki
        else:
471 70e11eaa Sofia Papagiannaki
            m = _(astakos_messages.USER_LEAVE_REQUEST_SUBMITTED)
472 70e11eaa Sofia Papagiannaki
        messages.success(request, m)
473 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
474 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
475 70e11eaa Sofia Papagiannaki
476 70e11eaa Sofia Papagiannaki
477 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
478 70e11eaa Sofia Papagiannaki
@cookie_fix
479 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
480 70e11eaa Sofia Papagiannaki
def project_cancel(request, chain_id):
481 70e11eaa Sofia Papagiannaki
    next = request.GET.get('next')
482 70e11eaa Sofia Papagiannaki
    if not next:
483 70e11eaa Sofia Papagiannaki
        next = reverse('astakos.im.views.project_list')
484 70e11eaa Sofia Papagiannaki
485 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
486 70e11eaa Sofia Papagiannaki
        _project_cancel(request, chain_id)
487 70e11eaa Sofia Papagiannaki
488 8998f09a Sofia Papagiannaki
    next = restrict_next(next, domain=settings.COOKIE_DOMAIN)
489 70e11eaa Sofia Papagiannaki
    return redirect(next)
490 70e11eaa Sofia Papagiannaki
491 70e11eaa Sofia Papagiannaki
492 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
493 70e11eaa Sofia Papagiannaki
def _project_cancel(request, chain_id):
494 70e11eaa Sofia Papagiannaki
    try:
495 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
496 70e11eaa Sofia Papagiannaki
        cancel_membership(chain_id, request.user)
497 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.USER_REQUEST_CANCELLED)
498 70e11eaa Sofia Papagiannaki
        messages.success(request, m)
499 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
500 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
501 70e11eaa Sofia Papagiannaki
502 70e11eaa Sofia Papagiannaki
503 70e11eaa Sofia Papagiannaki
504 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
505 70e11eaa Sofia Papagiannaki
@cookie_fix
506 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
507 70e11eaa Sofia Papagiannaki
def project_accept_member(request, chain_id, memb_id):
508 70e11eaa Sofia Papagiannaki
509 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
510 70e11eaa Sofia Papagiannaki
        _project_accept_member(request, chain_id, memb_id)
511 70e11eaa Sofia Papagiannaki
512 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(chain_id,)))
513 70e11eaa Sofia Papagiannaki
514 70e11eaa Sofia Papagiannaki
515 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
516 70e11eaa Sofia Papagiannaki
def _project_accept_member(request, chain_id, memb_id):
517 70e11eaa Sofia Papagiannaki
    try:
518 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
519 70e11eaa Sofia Papagiannaki
        memb_id = int(memb_id)
520 70e11eaa Sofia Papagiannaki
        m = accept_membership(chain_id, memb_id, request.user)
521 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
522 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
523 70e11eaa Sofia Papagiannaki
524 70e11eaa Sofia Papagiannaki
    else:
525 70e11eaa Sofia Papagiannaki
        email = escape(m.person.email)
526 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.USER_MEMBERSHIP_ACCEPTED) % email
527 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
528 70e11eaa Sofia Papagiannaki
529 70e11eaa Sofia Papagiannaki
530 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
531 70e11eaa Sofia Papagiannaki
@cookie_fix
532 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
533 70e11eaa Sofia Papagiannaki
def project_remove_member(request, chain_id, memb_id):
534 70e11eaa Sofia Papagiannaki
535 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
536 70e11eaa Sofia Papagiannaki
        _project_remove_member(request, chain_id, memb_id)
537 70e11eaa Sofia Papagiannaki
538 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(chain_id,)))
539 70e11eaa Sofia Papagiannaki
540 70e11eaa Sofia Papagiannaki
541 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
542 70e11eaa Sofia Papagiannaki
def _project_remove_member(request, chain_id, memb_id):
543 70e11eaa Sofia Papagiannaki
    try:
544 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
545 70e11eaa Sofia Papagiannaki
        memb_id = int(memb_id)
546 70e11eaa Sofia Papagiannaki
        m = remove_membership(chain_id, memb_id, request.user)
547 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
548 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
549 70e11eaa Sofia Papagiannaki
    else:
550 70e11eaa Sofia Papagiannaki
        email = escape(m.person.email)
551 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.USER_MEMBERSHIP_REMOVED) % email
552 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
553 70e11eaa Sofia Papagiannaki
554 70e11eaa Sofia Papagiannaki
555 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
556 70e11eaa Sofia Papagiannaki
@cookie_fix
557 70e11eaa Sofia Papagiannaki
@valid_astakos_user_required
558 70e11eaa Sofia Papagiannaki
def project_reject_member(request, chain_id, memb_id):
559 70e11eaa Sofia Papagiannaki
560 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
561 70e11eaa Sofia Papagiannaki
        _project_reject_member(request, chain_id, memb_id)
562 70e11eaa Sofia Papagiannaki
563 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(chain_id,)))
564 70e11eaa Sofia Papagiannaki
565 70e11eaa Sofia Papagiannaki
566 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
567 70e11eaa Sofia Papagiannaki
def _project_reject_member(request, chain_id, memb_id):
568 70e11eaa Sofia Papagiannaki
    try:
569 70e11eaa Sofia Papagiannaki
        chain_id = int(chain_id)
570 70e11eaa Sofia Papagiannaki
        memb_id = int(memb_id)
571 70e11eaa Sofia Papagiannaki
        m = reject_membership(chain_id, memb_id, request.user)
572 70e11eaa Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
573 70e11eaa Sofia Papagiannaki
        messages.error(request, e)
574 70e11eaa Sofia Papagiannaki
    else:
575 70e11eaa Sofia Papagiannaki
        email = escape(m.person.email)
576 70e11eaa Sofia Papagiannaki
        msg = _(astakos_messages.USER_MEMBERSHIP_REJECTED) % email
577 70e11eaa Sofia Papagiannaki
        messages.success(request, msg)
578 70e11eaa Sofia Papagiannaki
579 70e11eaa Sofia Papagiannaki
580 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
581 70e11eaa Sofia Papagiannaki
@signed_terms_required
582 70e11eaa Sofia Papagiannaki
@login_required
583 70e11eaa Sofia Papagiannaki
@cookie_fix
584 70e11eaa Sofia Papagiannaki
def project_app_approve(request, application_id):
585 70e11eaa Sofia Papagiannaki
586 70e11eaa Sofia Papagiannaki
    if not request.user.is_project_admin():
587 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
588 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
589 70e11eaa Sofia Papagiannaki
590 70e11eaa Sofia Papagiannaki
    try:
591 70e11eaa Sofia Papagiannaki
        app = ProjectApplication.objects.get(id=application_id)
592 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
593 70e11eaa Sofia Papagiannaki
        raise Http404
594 70e11eaa Sofia Papagiannaki
595 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
596 70e11eaa Sofia Papagiannaki
        _project_app_approve(request, application_id)
597 70e11eaa Sofia Papagiannaki
598 70e11eaa Sofia Papagiannaki
    chain_id = get_related_project_id(application_id)
599 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(chain_id,)))
600 70e11eaa Sofia Papagiannaki
601 70e11eaa Sofia Papagiannaki
602 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
603 70e11eaa Sofia Papagiannaki
def _project_app_approve(request, application_id):
604 70e11eaa Sofia Papagiannaki
    approve_application(application_id)
605 70e11eaa Sofia Papagiannaki
606 70e11eaa Sofia Papagiannaki
607 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
608 70e11eaa Sofia Papagiannaki
@signed_terms_required
609 70e11eaa Sofia Papagiannaki
@login_required
610 70e11eaa Sofia Papagiannaki
@cookie_fix
611 70e11eaa Sofia Papagiannaki
def project_app_deny(request, application_id):
612 70e11eaa Sofia Papagiannaki
613 70e11eaa Sofia Papagiannaki
    reason = request.POST.get('reason', None)
614 70e11eaa Sofia Papagiannaki
    if not reason:
615 70e11eaa Sofia Papagiannaki
        reason = None
616 70e11eaa Sofia Papagiannaki
617 70e11eaa Sofia Papagiannaki
    if not request.user.is_project_admin():
618 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
619 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
620 70e11eaa Sofia Papagiannaki
621 70e11eaa Sofia Papagiannaki
    try:
622 70e11eaa Sofia Papagiannaki
        app = ProjectApplication.objects.get(id=application_id)
623 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
624 70e11eaa Sofia Papagiannaki
        raise Http404
625 70e11eaa Sofia Papagiannaki
626 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
627 70e11eaa Sofia Papagiannaki
        _project_app_deny(request, application_id, reason)
628 70e11eaa Sofia Papagiannaki
629 70e11eaa Sofia Papagiannaki
    return redirect(reverse('project_list'))
630 70e11eaa Sofia Papagiannaki
631 70e11eaa Sofia Papagiannaki
632 70e11eaa Sofia Papagiannaki
@commit_on_success_strict()
633 70e11eaa Sofia Papagiannaki
def _project_app_deny(request, application_id, reason):
634 70e11eaa Sofia Papagiannaki
    deny_application(application_id, reason=reason)
635 70e11eaa Sofia Papagiannaki
636 70e11eaa Sofia Papagiannaki
637 70e11eaa Sofia Papagiannaki
@require_http_methods(["POST"])
638 70e11eaa Sofia Papagiannaki
@signed_terms_required
639 70e11eaa Sofia Papagiannaki
@login_required
640 70e11eaa Sofia Papagiannaki
@cookie_fix
641 70e11eaa Sofia Papagiannaki
def project_app_dismiss(request, application_id):
642 70e11eaa Sofia Papagiannaki
    try:
643 70e11eaa Sofia Papagiannaki
        app = ProjectApplication.objects.get(id=application_id)
644 70e11eaa Sofia Papagiannaki
    except ProjectApplication.DoesNotExist:
645 70e11eaa Sofia Papagiannaki
        raise Http404
646 70e11eaa Sofia Papagiannaki
647 70e11eaa Sofia Papagiannaki
    if not request.user.owns_application(app):
648 70e11eaa Sofia Papagiannaki
        m = _(astakos_messages.NOT_ALLOWED)
649 70e11eaa Sofia Papagiannaki
        raise PermissionDenied(m)
650 70e11eaa Sofia Papagiannaki
651 70e11eaa Sofia Papagiannaki
    with ExceptionHandler(request):
652 70e11eaa Sofia Papagiannaki
        _project_app_dismiss(request, application_id)
653 70e11eaa Sofia Papagiannaki
654 70e11eaa Sofia Papagiannaki
    chain_id = None
655 70e11eaa Sofia Papagiannaki
    chain_id = get_related_project_id(application_id)
656 70e11eaa Sofia Papagiannaki
    if chain_id:
657 70e11eaa Sofia Papagiannaki
        next = reverse('project_detail', args=(chain_id,))
658 70e11eaa Sofia Papagiannaki
    else:
659 70e11eaa Sofia Papagiannaki
        next = reverse('project_list')
660 70e11eaa Sofia Papagiannaki
    return redirect(next)
661 70e11eaa Sofia Papagiannaki
662 70e11eaa Sofia Papagiannaki
663 70e11eaa Sofia Papagiannaki
def _project_app_dismiss(request, application_id):
664 70e11eaa Sofia Papagiannaki
    # XXX: dismiss application also does authorization
665 70e11eaa Sofia Papagiannaki
    dismiss_application(application_id, request_user=request.user)
666 460b907d Kostas Papadimitriou
667 460b907d Kostas Papadimitriou
668 460b907d Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
669 460b907d Kostas Papadimitriou
@valid_astakos_user_required
670 460b907d Kostas Papadimitriou
def project_members(request, chain_id, members_status_filter=None,
671 460b907d Kostas Papadimitriou
                    template_name='im/projects/project_members.html'):
672 7971e5da Kostas Papadimitriou
    project, application = get_by_chain_or_404(chain_id)
673 7971e5da Kostas Papadimitriou
674 7971e5da Kostas Papadimitriou
    user = request.user
675 7971e5da Kostas Papadimitriou
    if not user.owns_project(project) and not user.is_project_admin():
676 7971e5da Kostas Papadimitriou
        return redirect(reverse('index'))
677 7971e5da Kostas Papadimitriou
678 460b907d Kostas Papadimitriou
    return common_detail(request, chain_id,
679 460b907d Kostas Papadimitriou
                         members_status_filter=members_status_filter,
680 460b907d Kostas Papadimitriou
                         template_name=template_name)
681 272ba9b9 Kostas Papadimitriou
682 272ba9b9 Kostas Papadimitriou
683 272ba9b9 Kostas Papadimitriou
@require_http_methods(["POST"])
684 272ba9b9 Kostas Papadimitriou
@valid_astakos_user_required
685 272ba9b9 Kostas Papadimitriou
def project_members_action(request, chain_id, action=None, redirect_to=''):
686 272ba9b9 Kostas Papadimitriou
687 272ba9b9 Kostas Papadimitriou
    actions_map = {
688 272ba9b9 Kostas Papadimitriou
        'remove': _project_remove_member,
689 272ba9b9 Kostas Papadimitriou
        'accept': _project_accept_member,
690 272ba9b9 Kostas Papadimitriou
        'reject': _project_reject_member
691 272ba9b9 Kostas Papadimitriou
    }
692 272ba9b9 Kostas Papadimitriou
693 272ba9b9 Kostas Papadimitriou
    if not action in actions_map.keys():
694 272ba9b9 Kostas Papadimitriou
        raise PermissionDenied
695 272ba9b9 Kostas Papadimitriou
696 272ba9b9 Kostas Papadimitriou
    member_ids = request.POST.getlist('members')
697 272ba9b9 Kostas Papadimitriou
    project, application = get_by_chain_or_404(chain_id)
698 272ba9b9 Kostas Papadimitriou
699 272ba9b9 Kostas Papadimitriou
    user = request.user
700 272ba9b9 Kostas Papadimitriou
    if not user.owns_project(project) and not user.is_project_admin():
701 272ba9b9 Kostas Papadimitriou
        return redirect(reverse('index'))
702 272ba9b9 Kostas Papadimitriou
703 272ba9b9 Kostas Papadimitriou
    logger.info("Batch members action from %s (action: %s, members: %r)",
704 272ba9b9 Kostas Papadimitriou
               user.log_display, action, member_ids)
705 272ba9b9 Kostas Papadimitriou
706 272ba9b9 Kostas Papadimitriou
    action_func = actions_map.get(action)
707 272ba9b9 Kostas Papadimitriou
    for member_id in member_ids:
708 272ba9b9 Kostas Papadimitriou
        member_id = int(member_id)
709 272ba9b9 Kostas Papadimitriou
        with ExceptionHandler(request):
710 272ba9b9 Kostas Papadimitriou
            action_func(request, chain_id, member_id)
711 272ba9b9 Kostas Papadimitriou
712 272ba9b9 Kostas Papadimitriou
    return redirect(reverse('project_members', args=(chain_id,)))