Statistics
| Branch: | Tag: | Revision:

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

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