Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 1ac3349d

History | View | Annotate | Download (58.6 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 176023aa Kostas Papadimitriou
#
3 64cd4730 Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 64cd4730 Antony Chazapis
# without modification, are permitted provided that the following
5 64cd4730 Antony Chazapis
# conditions are met:
6 176023aa Kostas Papadimitriou
#
7 64cd4730 Antony Chazapis
#   1. Redistributions of source code must retain the above
8 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
9 64cd4730 Antony Chazapis
#      disclaimer.
10 176023aa Kostas Papadimitriou
#
11 64cd4730 Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
13 64cd4730 Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 64cd4730 Antony Chazapis
#      provided with the distribution.
15 176023aa Kostas Papadimitriou
#
16 64cd4730 Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 64cd4730 Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 64cd4730 Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 64cd4730 Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 64cd4730 Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 64cd4730 Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 64cd4730 Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 64cd4730 Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 64cd4730 Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 64cd4730 Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 64cd4730 Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 64cd4730 Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 176023aa Kostas Papadimitriou
#
29 64cd4730 Antony Chazapis
# The views and conclusions contained in the software and
30 64cd4730 Antony Chazapis
# documentation are those of the authors and should not be
31 64cd4730 Antony Chazapis
# interpreted as representing official policies, either expressed
32 64cd4730 Antony Chazapis
# or implied, of GRNET S.A.
33 64cd4730 Antony Chazapis
34 64cd4730 Antony Chazapis
import logging
35 6e029beb Sofia Papagiannaki
import calendar
36 9a06d96f Olga Brani
import inflect
37 9a06d96f Olga Brani
38 9a06d96f Olga Brani
engine = inflect.engine()
39 64cd4730 Antony Chazapis
40 0905ccd2 Sofia Papagiannaki
from urllib import quote
41 63ecdd20 Sofia Papagiannaki
from functools import wraps
42 c0b26605 Sofia Papagiannaki
from datetime import datetime
43 76ca5ff0 Kostas Papadimitriou
from synnefo.lib.ordereddict import OrderedDict
44 64cd4730 Antony Chazapis
45 a5cef8d0 Kostas Papadimitriou
from django_tables2 import RequestConfig
46 a5cef8d0 Kostas Papadimitriou
47 c630fee6 Kostas Papadimitriou
from django.shortcuts import get_object_or_404
48 890b0eaf Sofia Papagiannaki
from django.contrib import messages
49 01ac12d5 Sofia Papagiannaki
from django.contrib.auth.decorators import login_required
50 01ac12d5 Sofia Papagiannaki
from django.core.urlresolvers import reverse
51 01ac12d5 Sofia Papagiannaki
from django.db import transaction
52 01ac12d5 Sofia Papagiannaki
from django.db.utils import IntegrityError
53 73fbaec4 Sofia Papagiannaki
from django.http import (
54 73fbaec4 Sofia Papagiannaki
    HttpResponse, HttpResponseBadRequest,
55 73fbaec4 Sofia Papagiannaki
    HttpResponseForbidden, HttpResponseRedirect,
56 73fbaec4 Sofia Papagiannaki
    HttpResponseBadRequest, Http404)
57 01ac12d5 Sofia Papagiannaki
from django.shortcuts import redirect
58 661c4479 Sofia Papagiannaki
from django.template import RequestContext, loader as template_loader
59 01ac12d5 Sofia Papagiannaki
from django.utils.http import urlencode
60 efb334ca Sofia Papagiannaki
from django.utils.html import escape
61 564a2292 Kostas Papadimitriou
from django.utils.safestring import mark_safe
62 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
63 e1a80257 Sofia Papagiannaki
from django.views.generic.create_update import (
64 4e748491 Sofia Papagiannaki
    apply_extra_context, lookup_object, delete_object, get_model_and_form_class)
65 f3342849 Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
66 661c4479 Sofia Papagiannaki
from django.core.xheaders import populate_xheaders
67 792c2f3b Olga Brani
from django.core.exceptions import ValidationError, PermissionDenied
68 c0b26605 Sofia Papagiannaki
from django.template.loader import render_to_string
69 9a06d96f Olga Brani
from django.views.decorators.http import require_http_methods
70 29b0ec5a Sofia Papagiannaki
from django.db.models import Q
71 bfe23b13 Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
72 96b44c04 Sofia Papagiannaki
from django.utils import simplejson as json
73 d886c63d Sofia Papagiannaki
from django.contrib.auth.views import redirect_to_login
74 c0b26605 Sofia Papagiannaki
75 c630fee6 Kostas Papadimitriou
import astakos.im.messages as astakos_messages
76 c630fee6 Kostas Papadimitriou
77 e7cb4085 Kostas Papadimitriou
from astakos.im import activation_backends
78 5550bcfb Kostas Papadimitriou
from astakos.im import tables
79 e1a80257 Sofia Papagiannaki
from astakos.im.models import (
80 73fbaec4 Sofia Papagiannaki
    AstakosUser, ApprovalTerms,
81 26551b92 Kostas Papadimitriou
    EmailChange, AstakosUserAuthProvider, PendingThirdPartyUser,
82 b095201e Sofia Papagiannaki
    ProjectApplication, ProjectMembership, Project, Service, Resource)
83 73fbaec4 Sofia Papagiannaki
from astakos.im.util import (
84 b095201e Sofia Papagiannaki
    get_context, prepare_response, get_query, restrict_next, model_to_dict)
85 e1a80257 Sofia Papagiannaki
from astakos.im.forms import (
86 f7400729 Kostas Papadimitriou
    LoginForm, InvitationForm,
87 e1a80257 Sofia Papagiannaki
    FeedbackForm, SignApprovalTermsForm,
88 e1a80257 Sofia Papagiannaki
    EmailChangeForm,
89 bfe23b13 Sofia Papagiannaki
    ProjectApplicationForm, ProjectSortForm,
90 73fbaec4 Sofia Papagiannaki
    AddProjectMembersForm, ProjectSearchForm,
91 73fbaec4 Sofia Papagiannaki
    ProjectMembersSortForm)
92 f7400729 Kostas Papadimitriou
from astakos.im.forms import ExtendedProfileForm as ProfileForm
93 f3342849 Sofia Papagiannaki
from astakos.im.functions import (
94 e7cb4085 Kostas Papadimitriou
    send_feedback,
95 f3342849 Sofia Papagiannaki
    logout as auth_logout,
96 9cdb86fd Sofia Papagiannaki
    invite as invite_func,
97 9770ba6c Giorgos Korfiatis
    qh_add_pending_app,
98 aad0e329 Giorgos Korfiatis
    accept_membership, reject_membership, remove_membership, cancel_membership,
99 e7cb4085 Kostas Papadimitriou
    leave_project, join_project, enroll_member, can_join_request,
100 e7cb4085 Kostas Papadimitriou
    can_leave_request,
101 8e1a5af5 Georgios D. Tsoukalas
    get_related_project_id, get_by_chain_or_404,
102 8e1a5af5 Georgios D. Tsoukalas
    approve_application, deny_application,
103 8e1a5af5 Georgios D. Tsoukalas
    cancel_application, dismiss_application)
104 f3342849 Sofia Papagiannaki
from astakos.im.settings import (
105 f3342849 Sofia Papagiannaki
    COOKIE_DOMAIN, LOGOUT_NEXT,
106 f3342849 Sofia Papagiannaki
    LOGGING_LEVEL, PAGINATE_BY,
107 4161cb70 Giorgos Korfiatis
    PAGINATE_BY_ALL,
108 3f8570dc Kostas Papadimitriou
    ACTIVATION_REDIRECT_URL,
109 a9c7ff8a Sofia Papagiannaki
    MODERATION_ENABLED)
110 75380308 Kostas Papadimitriou
from astakos.im import presentation
111 e7cb4085 Kostas Papadimitriou
from astakos.im import settings
112 9d20fe23 Kostas Papadimitriou
from astakos.im import auth_providers as auth
113 b830f774 Giorgos Korfiatis
from snf_django.lib.db.transaction import commit_on_success_strict
114 39b2cb50 Giorgos Korfiatis
from astakos.im.ctx import ExceptionHandler
115 4e03ba30 Kostas Papadimitriou
from astakos.im import quotas
116 ae497612 Olga Brani
117 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
118 e015e9e6 Sofia Papagiannaki
119 9a06d96f Olga Brani
120 9a06d96f Olga Brani
121 b2ffa772 Sofia Papagiannaki
def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
122 890b0eaf Sofia Papagiannaki
    """
123 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
124 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
125 890b0eaf Sofia Papagiannaki
    specified ``status``.
126 890b0eaf Sofia Papagiannaki
    """
127 64cd4730 Antony Chazapis
    if tab is None:
128 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
129 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
130 661c4479 Sofia Papagiannaki
    html = template_loader.render_to_string(
131 5ce3ce4f Sofia Papagiannaki
        template, kwargs, context_instance=context_instance)
132 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
133 c301698f Sofia Papagiannaki
    return response
134 64cd4730 Antony Chazapis
135 792c2f3b Olga Brani
def requires_auth_provider(provider_id, **perms):
136 792c2f3b Olga Brani
    """
137 792c2f3b Olga Brani
    """
138 792c2f3b Olga Brani
    def decorator(func, *args, **kwargs):
139 792c2f3b Olga Brani
        @wraps(func)
140 792c2f3b Olga Brani
        def wrapper(request, *args, **kwargs):
141 9d20fe23 Kostas Papadimitriou
            provider = auth.get_provider(provider_id)
142 792c2f3b Olga Brani
143 792c2f3b Olga Brani
            if not provider or not provider.is_active():
144 792c2f3b Olga Brani
                raise PermissionDenied
145 792c2f3b Olga Brani
146 9d20fe23 Kostas Papadimitriou
            for pkey, value in perms.iteritems():
147 9d20fe23 Kostas Papadimitriou
                attr = 'get_%s_policy' % pkey.lower()
148 9d20fe23 Kostas Papadimitriou
                if getattr(provider, attr) != value:
149 9d20fe23 Kostas Papadimitriou
                    #TODO: add session message
150 9d20fe23 Kostas Papadimitriou
                    return HttpResponseRedirect(reverse('login'))
151 792c2f3b Olga Brani
            return func(request, *args)
152 792c2f3b Olga Brani
        return wrapper
153 792c2f3b Olga Brani
    return decorator
154 792c2f3b Olga Brani
155 63ecdd20 Sofia Papagiannaki
156 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
157 63ecdd20 Sofia Papagiannaki
    """
158 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
159 7482228b Sofia Papagiannaki
    redirects to `logout`.
160 63ecdd20 Sofia Papagiannaki
    """
161 63ecdd20 Sofia Papagiannaki
    @wraps(func)
162 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
163 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
164 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
165 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
166 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
167 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
168 63ecdd20 Sofia Papagiannaki
    return wrapper
169 63ecdd20 Sofia Papagiannaki
170 5ce3ce4f Sofia Papagiannaki
171 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
172 270dd48d Sofia Papagiannaki
    """
173 badcb2a9 Kostas Papadimitriou
    Decorator checks whether the request.user is Anonymous and in that case
174 270dd48d Sofia Papagiannaki
    redirects to `logout`.
175 270dd48d Sofia Papagiannaki
    """
176 270dd48d Sofia Papagiannaki
    @wraps(func)
177 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
178 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
179 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
180 5ce3ce4f Sofia Papagiannaki
                                'show_form': ''})
181 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
182 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
183 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
184 270dd48d Sofia Papagiannaki
    return wrapper
185 270dd48d Sofia Papagiannaki
186 5ce3ce4f Sofia Papagiannaki
187 9d20fe23 Kostas Papadimitriou
def required_auth_methods_assigned(allow_access=False):
188 badcb2a9 Kostas Papadimitriou
    """
189 badcb2a9 Kostas Papadimitriou
    Decorator that checks whether the request.user has all required auth providers
190 badcb2a9 Kostas Papadimitriou
    assigned.
191 badcb2a9 Kostas Papadimitriou
    """
192 badcb2a9 Kostas Papadimitriou
193 badcb2a9 Kostas Papadimitriou
    def decorator(func):
194 badcb2a9 Kostas Papadimitriou
        @wraps(func)
195 badcb2a9 Kostas Papadimitriou
        def wrapper(request, *args, **kwargs):
196 badcb2a9 Kostas Papadimitriou
            if request.user.is_authenticated():
197 9d20fe23 Kostas Papadimitriou
                missing = request.user.missing_required_providers()
198 9d20fe23 Kostas Papadimitriou
                if missing:
199 9d20fe23 Kostas Papadimitriou
                    for provider in missing:
200 9d20fe23 Kostas Papadimitriou
                        messages.error(request,
201 9d20fe23 Kostas Papadimitriou
                                       provider.get_required_msg)
202 9d20fe23 Kostas Papadimitriou
                    if not allow_access:
203 9d20fe23 Kostas Papadimitriou
                        return HttpResponseRedirect(reverse('edit_profile'))
204 badcb2a9 Kostas Papadimitriou
            return func(request, *args, **kwargs)
205 badcb2a9 Kostas Papadimitriou
        return wrapper
206 badcb2a9 Kostas Papadimitriou
    return decorator
207 badcb2a9 Kostas Papadimitriou
208 badcb2a9 Kostas Papadimitriou
209 badcb2a9 Kostas Papadimitriou
def valid_astakos_user_required(func):
210 badcb2a9 Kostas Papadimitriou
    return signed_terms_required(required_auth_methods_assigned()(login_required(func)))
211 badcb2a9 Kostas Papadimitriou
212 badcb2a9 Kostas Papadimitriou
213 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
214 270dd48d Sofia Papagiannaki
@signed_terms_required
215 1f3b4b39 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context=None):
216 890b0eaf Sofia Papagiannaki
    """
217 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
218 176023aa Kostas Papadimitriou

219 890b0eaf Sofia Papagiannaki
    **Arguments**
220 176023aa Kostas Papadimitriou

221 dcf55476 Sofia Papagiannaki
    ``login_template_name``
222 dcf55476 Sofia Papagiannaki
        A custom login template to use. This is optional; if not specified,
223 1e685275 Sofia Papagiannaki
        this will default to ``im/login.html``.
224 176023aa Kostas Papadimitriou

225 dcf55476 Sofia Papagiannaki
    ``profile_template_name``
226 dcf55476 Sofia Papagiannaki
        A custom profile template to use. This is optional; if not specified,
227 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
228 176023aa Kostas Papadimitriou

229 890b0eaf Sofia Papagiannaki
    ``extra_context``
230 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
231 176023aa Kostas Papadimitriou

232 890b0eaf Sofia Papagiannaki
    **Template:**
233 176023aa Kostas Papadimitriou

234 1e685275 Sofia Papagiannaki
    im/profile.html or im/login.html or ``template_name`` keyword argument.
235 176023aa Kostas Papadimitriou

236 890b0eaf Sofia Papagiannaki
    """
237 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
238 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
239 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
240 f534fb96 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.edit_profile'))
241 792c2f3b Olga Brani
242 f7cf5257 Kostas Papadimitriou
    third_party_token = request.GET.get('key', False)
243 f7cf5257 Kostas Papadimitriou
    if third_party_token:
244 f7cf5257 Kostas Papadimitriou
        messages.info(request, astakos_messages.AUTH_PROVIDER_LOGIN_TO_ADD)
245 f7cf5257 Kostas Papadimitriou
246 ef20ea07 Sofia Papagiannaki
    return render_response(
247 ef20ea07 Sofia Papagiannaki
        template_name,
248 ef20ea07 Sofia Papagiannaki
        login_form = LoginForm(request=request),
249 ef20ea07 Sofia Papagiannaki
        context_instance = get_context(request, extra_context)
250 ef20ea07 Sofia Papagiannaki
    )
251 5ce3ce4f Sofia Papagiannaki
252 64cd4730 Antony Chazapis
253 0504f010 Kostas Papadimitriou
@require_http_methods(["POST"])
254 0504f010 Kostas Papadimitriou
@valid_astakos_user_required
255 0504f010 Kostas Papadimitriou
def update_token(request):
256 0504f010 Kostas Papadimitriou
    """
257 0504f010 Kostas Papadimitriou
    Update api token view.
258 0504f010 Kostas Papadimitriou
    """
259 0504f010 Kostas Papadimitriou
    user = request.user
260 0504f010 Kostas Papadimitriou
    user.renew_token()
261 0504f010 Kostas Papadimitriou
    user.save()
262 0504f010 Kostas Papadimitriou
    messages.success(request, astakos_messages.TOKEN_UPDATED)
263 0504f010 Kostas Papadimitriou
    return HttpResponseRedirect(reverse('edit_profile'))
264 0504f010 Kostas Papadimitriou
265 0504f010 Kostas Papadimitriou
266 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
267 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
268 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
269 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
270 890b0eaf Sofia Papagiannaki
    """
271 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
272 176023aa Kostas Papadimitriou

273 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the invitee information.
274 890b0eaf Sofia Papagiannaki
    In case of POST checks whether the user has not run out of invitations and then
275 890b0eaf Sofia Papagiannaki
    sends an invitation email to singup to the service.
276 176023aa Kostas Papadimitriou

277 890b0eaf Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the number of the
278 890b0eaf Sofia Papagiannaki
    user invitations is going to be updated only if the email has been successfully sent.
279 176023aa Kostas Papadimitriou

280 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
281 176023aa Kostas Papadimitriou

282 890b0eaf Sofia Papagiannaki
    **Arguments**
283 176023aa Kostas Papadimitriou

284 890b0eaf Sofia Papagiannaki
    ``template_name``
285 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
286 1e685275 Sofia Papagiannaki
        this will default to ``im/invitations.html``.
287 176023aa Kostas Papadimitriou

288 890b0eaf Sofia Papagiannaki
    ``extra_context``
289 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
290 176023aa Kostas Papadimitriou

291 890b0eaf Sofia Papagiannaki
    **Template:**
292 176023aa Kostas Papadimitriou

293 1e685275 Sofia Papagiannaki
    im/invitations.html or ``template_name`` keyword argument.
294 176023aa Kostas Papadimitriou

295 890b0eaf Sofia Papagiannaki
    **Settings:**
296 176023aa Kostas Papadimitriou

297 890b0eaf Sofia Papagiannaki
    The view expectes the following settings are defined:
298 176023aa Kostas Papadimitriou

299 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
300 890b0eaf Sofia Papagiannaki
    """
301 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
302 64cd4730 Antony Chazapis
    status = None
303 64cd4730 Antony Chazapis
    message = None
304 8f5a3a06 Sofia Papagiannaki
    form = InvitationForm()
305 5ce3ce4f Sofia Papagiannaki
306 18ffbee1 Sofia Papagiannaki
    inviter = request.user
307 64cd4730 Antony Chazapis
    if request.method == 'POST':
308 8f5a3a06 Sofia Papagiannaki
        form = InvitationForm(request.POST)
309 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
310 8f5a3a06 Sofia Papagiannaki
            if form.is_valid():
311 8f5a3a06 Sofia Papagiannaki
                try:
312 9a06d96f Olga Brani
                    email = form.cleaned_data.get('username')
313 9a06d96f Olga Brani
                    realname = form.cleaned_data.get('realname')
314 9cdb86fd Sofia Papagiannaki
                    invite_func(inviter, email, realname)
315 ae497612 Olga Brani
                    message = _(astakos_messages.INVITATION_SENT) % locals()
316 24406ae3 Sofia Papagiannaki
                    messages.success(request, message)
317 e7cb4085 Kostas Papadimitriou
                except Exception, e:
318 18ffbee1 Sofia Papagiannaki
                    transaction.rollback()
319 e7cb4085 Kostas Papadimitriou
                    raise
320 18ffbee1 Sofia Papagiannaki
                else:
321 18ffbee1 Sofia Papagiannaki
                    transaction.commit()
322 64cd4730 Antony Chazapis
        else:
323 ae497612 Olga Brani
            message = _(astakos_messages.MAX_INVITATION_NUMBER_REACHED)
324 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
325 176023aa Kostas Papadimitriou
326 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
327 d6ae71a2 root
             'realname': inv.realname,
328 d6ae71a2 root
             'is_consumed': inv.is_consumed}
329 5ce3ce4f Sofia Papagiannaki
            for inv in request.user.invitations_sent.all()]
330 77e2ad52 root
    kwargs = {'inviter': inviter,
331 5ce3ce4f Sofia Papagiannaki
              'sent': sent}
332 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
333 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
334 5ce3ce4f Sofia Papagiannaki
                           invitation_form=form,
335 5ce3ce4f Sofia Papagiannaki
                           context_instance=context)
336 5ce3ce4f Sofia Papagiannaki
337 64cd4730 Antony Chazapis
338 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
339 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
340 890b0eaf Sofia Papagiannaki
@login_required
341 270dd48d Sofia Papagiannaki
@signed_terms_required
342 aab4d540 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context=None):
343 890b0eaf Sofia Papagiannaki
    """
344 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
345 176023aa Kostas Papadimitriou

346 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for displaying the user information.
347 ce86cd44 Sofia Papagiannaki
    In case of POST updates the user informantion and redirects to ``next``
348 ce86cd44 Sofia Papagiannaki
    url parameter if exists.
349 176023aa Kostas Papadimitriou

350 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
351 176023aa Kostas Papadimitriou

352 890b0eaf Sofia Papagiannaki
    **Arguments**
353 176023aa Kostas Papadimitriou

354 890b0eaf Sofia Papagiannaki
    ``template_name``
355 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
356 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
357 176023aa Kostas Papadimitriou

358 890b0eaf Sofia Papagiannaki
    ``extra_context``
359 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
360 176023aa Kostas Papadimitriou

361 890b0eaf Sofia Papagiannaki
    **Template:**
362 176023aa Kostas Papadimitriou

363 1e685275 Sofia Papagiannaki
    im/profile.html or ``template_name`` keyword argument.
364 176023aa Kostas Papadimitriou

365 92defad4 Sofia Papagiannaki
    **Settings:**
366 176023aa Kostas Papadimitriou

367 92defad4 Sofia Papagiannaki
    The view expectes the following settings are defined:
368 176023aa Kostas Papadimitriou

369 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
370 890b0eaf Sofia Papagiannaki
    """
371 aab4d540 Sofia Papagiannaki
    extra_context = extra_context or {}
372 bf0c6de5 Sofia Papagiannaki
    form = ProfileForm(
373 bf0c6de5 Sofia Papagiannaki
        instance=request.user,
374 bf0c6de5 Sofia Papagiannaki
        session_key=request.session.session_key
375 bf0c6de5 Sofia Papagiannaki
    )
376 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
377 64cd4730 Antony Chazapis
    if request.method == 'POST':
378 bf0c6de5 Sofia Papagiannaki
        form = ProfileForm(
379 bf0c6de5 Sofia Papagiannaki
            request.POST,
380 bf0c6de5 Sofia Papagiannaki
            instance=request.user,
381 bf0c6de5 Sofia Papagiannaki
            session_key=request.session.session_key
382 bf0c6de5 Sofia Papagiannaki
        )
383 890b0eaf Sofia Papagiannaki
        if form.is_valid():
384 64cd4730 Antony Chazapis
            try:
385 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
386 3fbf7863 Kostas Papadimitriou
                user = form.save(request=request)
387 217994f8 Sofia Papagiannaki
                next = restrict_next(
388 217994f8 Sofia Papagiannaki
                    request.POST.get('next'),
389 217994f8 Sofia Papagiannaki
                    domain=COOKIE_DOMAIN
390 217994f8 Sofia Papagiannaki
                )
391 ae497612 Olga Brani
                msg = _(astakos_messages.PROFILE_UPDATED)
392 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
393 2da6f56b Kostas Papadimitriou
394 2da6f56b Kostas Papadimitriou
                if form.email_changed:
395 2da6f56b Kostas Papadimitriou
                    msg = _(astakos_messages.EMAIL_CHANGE_REGISTERED)
396 2da6f56b Kostas Papadimitriou
                    messages.success(request, msg)
397 2da6f56b Kostas Papadimitriou
                if form.password_changed:
398 2da6f56b Kostas Papadimitriou
                    msg = _(astakos_messages.PASSWORD_CHANGED)
399 2da6f56b Kostas Papadimitriou
                    messages.success(request, msg)
400 2da6f56b Kostas Papadimitriou
401 f7400729 Kostas Papadimitriou
                if next:
402 f7400729 Kostas Papadimitriou
                    return redirect(next)
403 f7400729 Kostas Papadimitriou
                else:
404 f7400729 Kostas Papadimitriou
                    return redirect(reverse('edit_profile'))
405 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
406 24406ae3 Sofia Papagiannaki
                messages.success(request, ve)
407 23447441 Sofia Papagiannaki
    elif request.method == "GET":
408 792c2f3b Olga Brani
        request.user.is_verified = True
409 792c2f3b Olga Brani
        request.user.save()
410 792c2f3b Olga Brani
411 792c2f3b Olga Brani
    # existing providers
412 9d20fe23 Kostas Papadimitriou
    user_providers = request.user.get_enabled_auth_providers()
413 9d20fe23 Kostas Papadimitriou
    user_disabled_providers = request.user.get_disabled_auth_providers()
414 792c2f3b Olga Brani
415 792c2f3b Olga Brani
    # providers that user can add
416 792c2f3b Olga Brani
    user_available_providers = request.user.get_available_auth_providers()
417 792c2f3b Olga Brani
418 79b5d61b Sofia Papagiannaki
    extra_context['services'] = Service.catalog().values()
419 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
420 e7cb4085 Kostas Papadimitriou
                           profile_form=form,
421 e7cb4085 Kostas Papadimitriou
                           user_providers=user_providers,
422 e7cb4085 Kostas Papadimitriou
                           user_disabled_providers=user_disabled_providers,
423 e7cb4085 Kostas Papadimitriou
                           user_available_providers=user_available_providers,
424 e7cb4085 Kostas Papadimitriou
                           context_instance=get_context(request,
425 c301698f Sofia Papagiannaki
                                                          extra_context))
426 5ce3ce4f Sofia Papagiannaki
427 64cd4730 Antony Chazapis
428 10ed0073 Sofia Papagiannaki
@transaction.commit_manually
429 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
430 e7cb4085 Kostas Papadimitriou
def signup(request, template_name='im/signup.html', on_success='index',
431 e7cb4085 Kostas Papadimitriou
           extra_context=None, activation_backend=None):
432 890b0eaf Sofia Papagiannaki
    """
433 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
434 176023aa Kostas Papadimitriou

435 b669d9c0 Sofia Papagiannaki
    In case of GET request renders a form for entering the user information.
436 890b0eaf Sofia Papagiannaki
    In case of POST handles the signup.
437 176023aa Kostas Papadimitriou

438 e7cb4085 Kostas Papadimitriou
    The user activation will be delegated to the backend specified by the
439 e7cb4085 Kostas Papadimitriou
    ``activation_backend`` keyword argument if present, otherwise to the
440 e7cb4085 Kostas Papadimitriou
    ``astakos.im.activation_backends.InvitationBackend`` if
441 e7cb4085 Kostas Papadimitriou
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
442 e7cb4085 Kostas Papadimitriou
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
443 e7cb4085 Kostas Papadimitriou
    activation_backends);
444 5ce3ce4f Sofia Papagiannaki

445 e7cb4085 Kostas Papadimitriou
    Upon successful user creation, if ``next`` url parameter is present the
446 e7cb4085 Kostas Papadimitriou
    user is redirected there otherwise renders the same page with a success
447 e7cb4085 Kostas Papadimitriou
    message.
448 5ce3ce4f Sofia Papagiannaki

449 8f5a3a06 Sofia Papagiannaki
    On unsuccessful creation, renders ``template_name`` with an error message.
450 5ce3ce4f Sofia Papagiannaki

451 890b0eaf Sofia Papagiannaki
    **Arguments**
452 5ce3ce4f Sofia Papagiannaki

453 8f5a3a06 Sofia Papagiannaki
    ``template_name``
454 8f5a3a06 Sofia Papagiannaki
        A custom template to render. This is optional;
455 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup.html``.
456 176023aa Kostas Papadimitriou

457 890b0eaf Sofia Papagiannaki
    ``extra_context``
458 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
459 176023aa Kostas Papadimitriou

460 43332a76 Kostas Papadimitriou
    ``on_success``
461 43332a76 Kostas Papadimitriou
        Resolvable view name to redirect on registration success.
462 43332a76 Kostas Papadimitriou

463 890b0eaf Sofia Papagiannaki
    **Template:**
464 5ce3ce4f Sofia Papagiannaki

465 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
466 890b0eaf Sofia Papagiannaki
    """
467 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
468 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
469 e7cb4085 Kostas Papadimitriou
        logger.info("%s already signed in, redirect to index",
470 e7cb4085 Kostas Papadimitriou
                    request.user.log_display)
471 e7cb4085 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
472 5ce3ce4f Sofia Papagiannaki
473 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
474 9d20fe23 Kostas Papadimitriou
    if not auth.get_provider(provider).get_create_policy:
475 e7cb4085 Kostas Papadimitriou
        logger.error("%s provider not available for signup", provider)
476 279d6e51 Olga Brani
        raise PermissionDenied
477 279d6e51 Olga Brani
478 e7cb4085 Kostas Papadimitriou
    instance = None
479 6c8a3f7c Sofia Papagiannaki
480 e7cb4085 Kostas Papadimitriou
    # user registered using third party provider
481 8ab484ea Kostas Papadimitriou
    third_party_token = request.REQUEST.get('third_party_token', None)
482 9d20fe23 Kostas Papadimitriou
    unverified = None
483 c630fee6 Kostas Papadimitriou
    if third_party_token:
484 e7cb4085 Kostas Papadimitriou
        # retreive third party entry. This was created right after the initial
485 e7cb4085 Kostas Papadimitriou
        # third party provider handshake.
486 c630fee6 Kostas Papadimitriou
        pending = get_object_or_404(PendingThirdPartyUser,
487 c630fee6 Kostas Papadimitriou
                                    token=third_party_token)
488 9d20fe23 Kostas Papadimitriou
489 c630fee6 Kostas Papadimitriou
        provider = pending.provider
490 e7cb4085 Kostas Papadimitriou
491 e7cb4085 Kostas Papadimitriou
        # clone third party instance into the corresponding AstakosUser
492 c630fee6 Kostas Papadimitriou
        instance = pending.get_user_instance()
493 9d20fe23 Kostas Papadimitriou
        get_unverified = AstakosUserAuthProvider.objects.unverified
494 e7cb4085 Kostas Papadimitriou
495 e7cb4085 Kostas Papadimitriou
        # check existing unverified entries
496 9d20fe23 Kostas Papadimitriou
        unverified = get_unverified(pending.provider,
497 9d20fe23 Kostas Papadimitriou
                                    identifier=pending.third_party_identifier)
498 9d20fe23 Kostas Papadimitriou
499 9d20fe23 Kostas Papadimitriou
        if unverified and request.method == 'GET':
500 9d20fe23 Kostas Papadimitriou
            messages.warning(request, unverified.get_pending_registration_msg)
501 e7cb4085 Kostas Papadimitriou
            if unverified.user.moderated:
502 9d20fe23 Kostas Papadimitriou
                messages.warning(request,
503 9d20fe23 Kostas Papadimitriou
                                 unverified.get_pending_resend_activation_msg)
504 9d20fe23 Kostas Papadimitriou
            else:
505 9d20fe23 Kostas Papadimitriou
                messages.warning(request,
506 9d20fe23 Kostas Papadimitriou
                                 unverified.get_pending_moderation_msg)
507 8ab484ea Kostas Papadimitriou
508 e7cb4085 Kostas Papadimitriou
    # prepare activation backend based on current request
509 e7cb4085 Kostas Papadimitriou
    if not activation_backend:
510 e7cb4085 Kostas Papadimitriou
        activation_backend = activation_backends.get_backend()
511 e7cb4085 Kostas Papadimitriou
512 e7cb4085 Kostas Papadimitriou
    form_kwargs = {'instance': instance}
513 e7cb4085 Kostas Papadimitriou
    if third_party_token:
514 e7cb4085 Kostas Papadimitriou
        form_kwargs['third_party_token'] = third_party_token
515 e7cb4085 Kostas Papadimitriou
516 e7cb4085 Kostas Papadimitriou
    form = activation_backend.get_signup_form(
517 e7cb4085 Kostas Papadimitriou
        provider, None, **form_kwargs)
518 9d20fe23 Kostas Papadimitriou
519 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
520 e7cb4085 Kostas Papadimitriou
        form = activation_backend.get_signup_form(
521 e7cb4085 Kostas Papadimitriou
            provider,
522 e7cb4085 Kostas Papadimitriou
            request.POST,
523 e7cb4085 Kostas Papadimitriou
            **form_kwargs)
524 e7cb4085 Kostas Papadimitriou
525 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
526 e7cb4085 Kostas Papadimitriou
            commited = False
527 e7cb4085 Kostas Papadimitriou
            try:
528 e7cb4085 Kostas Papadimitriou
                user = form.save(commit=False)
529 43332a76 Kostas Papadimitriou
530 e7cb4085 Kostas Papadimitriou
                # delete previously unverified accounts
531 e7cb4085 Kostas Papadimitriou
                if AstakosUser.objects.user_exists(user.email):
532 e7cb4085 Kostas Papadimitriou
                    AstakosUser.objects.get_by_identifier(user.email).delete()
533 43332a76 Kostas Papadimitriou
534 e7cb4085 Kostas Papadimitriou
                # store_user so that user auth providers get initialized
535 9d20fe23 Kostas Papadimitriou
                form.store_user(user, request)
536 e7cb4085 Kostas Papadimitriou
                result = activation_backend.handle_registration(user)
537 e7cb4085 Kostas Papadimitriou
                if result.status == \
538 e7cb4085 Kostas Papadimitriou
                        activation_backend.Result.PENDING_MODERATION:
539 e7cb4085 Kostas Papadimitriou
                    # user should be warned that his account is not active yet
540 e7cb4085 Kostas Papadimitriou
                    status = messages.WARNING
541 e7cb4085 Kostas Papadimitriou
                else:
542 e7cb4085 Kostas Papadimitriou
                    status = messages.SUCCESS
543 18ffbee1 Sofia Papagiannaki
                message = result.message
544 e7cb4085 Kostas Papadimitriou
                activation_backend.send_result_notifications(result, user)
545 792c2f3b Olga Brani
546 e7cb4085 Kostas Papadimitriou
                # commit user entry
547 e7cb4085 Kostas Papadimitriou
                transaction.commit()
548 e7cb4085 Kostas Papadimitriou
                # commited flag
549 e7cb4085 Kostas Papadimitriou
                # in case an exception get raised from this point
550 e7cb4085 Kostas Papadimitriou
                commited = True
551 43332a76 Kostas Papadimitriou
552 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
553 e7cb4085 Kostas Papadimitriou
                    # activation backend directly activated the user
554 e7cb4085 Kostas Papadimitriou
                    # log him in
555 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
556 40a0cd8b Sofia Papagiannaki
                    response = prepare_response(request, user, next=next)
557 40a0cd8b Sofia Papagiannaki
                    return response
558 43332a76 Kostas Papadimitriou
559 43332a76 Kostas Papadimitriou
                messages.add_message(request, status, message)
560 43332a76 Kostas Papadimitriou
                return HttpResponseRedirect(reverse(on_success))
561 e7cb4085 Kostas Papadimitriou
            except Exception, e:
562 e7cb4085 Kostas Papadimitriou
                if not commited:
563 e7cb4085 Kostas Papadimitriou
                    transaction.rollback()
564 e7cb4085 Kostas Papadimitriou
                raise
565 43332a76 Kostas Papadimitriou
566 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
567 5ce3ce4f Sofia Papagiannaki
                           signup_form=form,
568 8ab484ea Kostas Papadimitriou
                           third_party_token=third_party_token,
569 5ce3ce4f Sofia Papagiannaki
                           provider=provider,
570 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
571 64cd4730 Antony Chazapis
572 5ce3ce4f Sofia Papagiannaki
573 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
574 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
575 890b0eaf Sofia Papagiannaki
@login_required
576 270dd48d Sofia Papagiannaki
@signed_terms_required
577 aab4d540 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context=None):
578 890b0eaf Sofia Papagiannaki
    """
579 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
580 176023aa Kostas Papadimitriou

581 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the feedback information.
582 890b0eaf Sofia Papagiannaki
    In case of POST sends an email to support team.
583 176023aa Kostas Papadimitriou

584 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
585 176023aa Kostas Papadimitriou

586 890b0eaf Sofia Papagiannaki
    **Arguments**
587 176023aa Kostas Papadimitriou

588 890b0eaf Sofia Papagiannaki
    ``template_name``
589 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
590 1e685275 Sofia Papagiannaki
        this will default to ``im/feedback.html``.
591 176023aa Kostas Papadimitriou

592 890b0eaf Sofia Papagiannaki
    ``extra_context``
593 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
594 176023aa Kostas Papadimitriou

595 890b0eaf Sofia Papagiannaki
    **Template:**
596 176023aa Kostas Papadimitriou

597 1e685275 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
598 176023aa Kostas Papadimitriou

599 890b0eaf Sofia Papagiannaki
    **Settings:**
600 176023aa Kostas Papadimitriou

601 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
602 890b0eaf Sofia Papagiannaki
    """
603 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
604 64cd4730 Antony Chazapis
    if request.method == 'GET':
605 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
606 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
607 890b0eaf Sofia Papagiannaki
        if not request.user:
608 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
609 176023aa Kostas Papadimitriou
610 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
611 890b0eaf Sofia Papagiannaki
        if form.is_valid():
612 e9083112 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg']
613 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
614 e7cb4085 Kostas Papadimitriou
            send_feedback(msg, data, request.user, email_template_name)
615 e7cb4085 Kostas Papadimitriou
            message = _(astakos_messages.FEEDBACK_SENT)
616 e7cb4085 Kostas Papadimitriou
            messages.success(request, message)
617 b9f8f48a Kostas Papadimitriou
            return HttpResponseRedirect(reverse('feedback'))
618 e7cb4085 Kostas Papadimitriou
619 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
620 5ce3ce4f Sofia Papagiannaki
                           feedback_form=form,
621 e7cb4085 Kostas Papadimitriou
                           context_instance=get_context(request,
622 e7cb4085 Kostas Papadimitriou
                                                        extra_context))
623 5ce3ce4f Sofia Papagiannaki
624 15efc749 Sofia Papagiannaki
625 217994f8 Sofia Papagiannaki
@require_http_methods(["GET"])
626 e7cb4085 Kostas Papadimitriou
def logout(request, template='registration/logged_out.html',
627 e7cb4085 Kostas Papadimitriou
           extra_context=None):
628 63ecdd20 Sofia Papagiannaki
    """
629 b2ffa772 Sofia Papagiannaki
    Wraps `django.contrib.auth.logout`.
630 63ecdd20 Sofia Papagiannaki
    """
631 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
632 7482228b Sofia Papagiannaki
    response = HttpResponse()
633 8e45d6fd Sofia Papagiannaki
    if request.user.is_authenticated():
634 8e45d6fd Sofia Papagiannaki
        email = request.user.email
635 8e45d6fd Sofia Papagiannaki
        auth_logout(request)
636 c630fee6 Kostas Papadimitriou
    else:
637 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
638 c630fee6 Kostas Papadimitriou
        response.status_code = 301
639 c630fee6 Kostas Papadimitriou
        return response
640 c630fee6 Kostas Papadimitriou
641 217994f8 Sofia Papagiannaki
    next = restrict_next(
642 217994f8 Sofia Papagiannaki
        request.GET.get('next'),
643 217994f8 Sofia Papagiannaki
        domain=COOKIE_DOMAIN
644 217994f8 Sofia Papagiannaki
    )
645 c630fee6 Kostas Papadimitriou
646 63ecdd20 Sofia Papagiannaki
    if next:
647 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
648 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
649 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
650 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
651 0d02a287 Sofia Papagiannaki
        response.status_code = 301
652 b2ffa772 Sofia Papagiannaki
    else:
653 9d20fe23 Kostas Papadimitriou
        last_provider = request.COOKIES.get('astakos_last_login_method', 'local')
654 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(last_provider)
655 9d20fe23 Kostas Papadimitriou
        message = provider.get_logout_success_msg
656 9d20fe23 Kostas Papadimitriou
        extra = provider.get_logout_success_extra_msg
657 9d20fe23 Kostas Papadimitriou
        if extra:
658 9d20fe23 Kostas Papadimitriou
            message += "<br />"  + extra
659 d21d422a Kostas Papadimitriou
        messages.success(request, message)
660 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
661 c630fee6 Kostas Papadimitriou
        response.status_code = 301
662 49df775e Sofia Papagiannaki
    return response
663 2126d85d Sofia Papagiannaki
664 5ce3ce4f Sofia Papagiannaki
665 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
666 683cf244 Sofia Papagiannaki
@transaction.commit_manually
667 3bb604eb Sofia Papagiannaki
def activate(request, greeting_email_template_name='im/welcome_email.txt',
668 3bb604eb Sofia Papagiannaki
             helpdesk_email_template_name='im/helpdesk_notification.txt'):
669 2126d85d Sofia Papagiannaki
    """
670 e7cb4085 Kostas Papadimitriou
    Activates the user identified by the ``auth`` request parameter, sends a
671 e7cb4085 Kostas Papadimitriou
    welcome email and renews the user token.
672 176023aa Kostas Papadimitriou

673 e7cb4085 Kostas Papadimitriou
    The view uses commit_manually decorator in order to ensure the user state
674 e7cb4085 Kostas Papadimitriou
    will be updated only if the email will be send successfully.
675 2126d85d Sofia Papagiannaki
    """
676 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
677 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
678 5ce3ce4f Sofia Papagiannaki
679 e7cb4085 Kostas Papadimitriou
    if request.user.is_authenticated():
680 e7cb4085 Kostas Papadimitriou
        message = _(astakos_messages.LOGGED_IN_WARNING)
681 24406ae3 Sofia Papagiannaki
        messages.error(request, message)
682 92a8abc9 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
683 5ce3ce4f Sofia Papagiannaki
684 e7cb4085 Kostas Papadimitriou
    try:
685 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(verification_code=token)
686 e7cb4085 Kostas Papadimitriou
    except AstakosUser.DoesNotExist:
687 e7cb4085 Kostas Papadimitriou
        raise Http404
688 e7cb4085 Kostas Papadimitriou
689 e7cb4085 Kostas Papadimitriou
    if user.email_verified:
690 e7cb4085 Kostas Papadimitriou
        message = _(astakos_messages.ACCOUNT_ALREADY_VERIFIED)
691 89d959c9 Kostas Papadimitriou
        messages.error(request, message)
692 89d959c9 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
693 89d959c9 Kostas Papadimitriou
694 0a569195 Sofia Papagiannaki
    try:
695 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
696 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, token)
697 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
698 3f8570dc Kostas Papadimitriou
        next = ACTIVATION_REDIRECT_URL or next
699 e7cb4085 Kostas Papadimitriou
        response = HttpResponseRedirect(reverse('index'))
700 e7cb4085 Kostas Papadimitriou
        if user.is_active:
701 e7cb4085 Kostas Papadimitriou
            response = prepare_response(request, user, next, renew=True)
702 e7cb4085 Kostas Papadimitriou
            messages.success(request, _(result.message))
703 e7cb4085 Kostas Papadimitriou
        else:
704 e7cb4085 Kostas Papadimitriou
            messages.warning(request, _(result.message))
705 e7cb4085 Kostas Papadimitriou
    except Exception:
706 e7cb4085 Kostas Papadimitriou
        transaction.rollback()
707 e7cb4085 Kostas Papadimitriou
        raise
708 e7cb4085 Kostas Papadimitriou
    else:
709 ef20ea07 Sofia Papagiannaki
        transaction.commit()
710 279d6e51 Olga Brani
        return response
711 270dd48d Sofia Papagiannaki
712 5ce3ce4f Sofia Papagiannaki
713 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
714 e7cb4085 Kostas Papadimitriou
def approval_terms(request, term_id=None,
715 e7cb4085 Kostas Papadimitriou
                   template_name='im/approval_terms.html', extra_context=None):
716 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
717 270dd48d Sofia Papagiannaki
    term = None
718 270dd48d Sofia Papagiannaki
    terms = None
719 270dd48d Sofia Papagiannaki
    if not term_id:
720 270dd48d Sofia Papagiannaki
        try:
721 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
722 270dd48d Sofia Papagiannaki
        except IndexError:
723 270dd48d Sofia Papagiannaki
            pass
724 270dd48d Sofia Papagiannaki
    else:
725 270dd48d Sofia Papagiannaki
        try:
726 aab4d540 Sofia Papagiannaki
            term = ApprovalTerms.objects.get(id=term_id)
727 aab4d540 Sofia Papagiannaki
        except ApprovalTerms.DoesNotExist, e:
728 270dd48d Sofia Papagiannaki
            pass
729 176023aa Kostas Papadimitriou
730 270dd48d Sofia Papagiannaki
    if not term:
731 ae497612 Olga Brani
        messages.error(request, _(astakos_messages.NO_APPROVAL_TERMS))
732 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('index'))
733 64b5136c Sofia Papagiannaki
    try:
734 64b5136c Sofia Papagiannaki
        f = open(term.location, 'r')
735 64b5136c Sofia Papagiannaki
    except IOError:
736 64b5136c Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
737 64b5136c Sofia Papagiannaki
        return render_response(
738 e7cb4085 Kostas Papadimitriou
            template_name, context_instance=get_context(request,
739 e7cb4085 Kostas Papadimitriou
                                                        extra_context))
740 64b5136c Sofia Papagiannaki
741 270dd48d Sofia Papagiannaki
    terms = f.read()
742 176023aa Kostas Papadimitriou
743 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
744 217994f8 Sofia Papagiannaki
        next = restrict_next(
745 217994f8 Sofia Papagiannaki
            request.POST.get('next'),
746 217994f8 Sofia Papagiannaki
            domain=COOKIE_DOMAIN
747 217994f8 Sofia Papagiannaki
        )
748 270dd48d Sofia Papagiannaki
        if not next:
749 6ff7a7ca Sofia Papagiannaki
            next = reverse('index')
750 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
751 270dd48d Sofia Papagiannaki
        if not form.is_valid():
752 270dd48d Sofia Papagiannaki
            return render_response(template_name,
753 5ce3ce4f Sofia Papagiannaki
                                   terms=terms,
754 5ce3ce4f Sofia Papagiannaki
                                   approval_terms_form=form,
755 e7cb4085 Kostas Papadimitriou
                                   context_instance=get_context(request,
756 e7cb4085 Kostas Papadimitriou
                                                                extra_context))
757 270dd48d Sofia Papagiannaki
        user = form.save()
758 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
759 270dd48d Sofia Papagiannaki
    else:
760 586967c0 Sofia Papagiannaki
        form = None
761 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
762 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
763 270dd48d Sofia Papagiannaki
        return render_response(template_name,
764 5ce3ce4f Sofia Papagiannaki
                               terms=terms,
765 5ce3ce4f Sofia Papagiannaki
                               approval_terms_form=form,
766 e7cb4085 Kostas Papadimitriou
                               context_instance=get_context(request,
767 e7cb4085 Kostas Papadimitriou
                                                            extra_context))
768 5ce3ce4f Sofia Papagiannaki
769 270dd48d Sofia Papagiannaki
770 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
771 49790d9d Sofia Papagiannaki
@transaction.commit_manually
772 49790d9d Sofia Papagiannaki
def change_email(request, activation_key=None,
773 49790d9d Sofia Papagiannaki
                 email_template_name='registration/email_change_email.txt',
774 49790d9d Sofia Papagiannaki
                 form_template_name='registration/email_change_form.html',
775 49790d9d Sofia Papagiannaki
                 confirm_template_name='registration/email_change_done.html',
776 aab4d540 Sofia Papagiannaki
                 extra_context=None):
777 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
778 53e0b8fe Kostas Papadimitriou
779 e7cb4085 Kostas Papadimitriou
    if not settings.EMAILCHANGE_ENABLED:
780 17ad5d37 Kostas Papadimitriou
        raise PermissionDenied
781 17ad5d37 Kostas Papadimitriou
782 49790d9d Sofia Papagiannaki
    if activation_key:
783 49790d9d Sofia Papagiannaki
        try:
784 49790d9d Sofia Papagiannaki
            user = EmailChange.objects.change_email(activation_key)
785 e7cb4085 Kostas Papadimitriou
            if request.user.is_authenticated() and \
786 e7cb4085 Kostas Papadimitriou
                request.user == user or not \
787 10a870d5 Kostas Papadimitriou
                    request.user.is_authenticated():
788 ae497612 Olga Brani
                msg = _(astakos_messages.EMAIL_CHANGED)
789 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
790 49790d9d Sofia Papagiannaki
                transaction.commit()
791 53e0b8fe Kostas Papadimitriou
                return HttpResponseRedirect(reverse('edit_profile'))
792 49790d9d Sofia Papagiannaki
        except ValueError, e:
793 24406ae3 Sofia Papagiannaki
            messages.error(request, e)
794 53e0b8fe Kostas Papadimitriou
            transaction.rollback()
795 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('index'))
796 53e0b8fe Kostas Papadimitriou
797 49790d9d Sofia Papagiannaki
        return render_response(confirm_template_name,
798 e7cb4085 Kostas Papadimitriou
                               modified_user=user if 'user' in locals()
799 53e0b8fe Kostas Papadimitriou
                               else None, context_instance=get_context(request,
800 e7cb4085 Kostas Papadimitriou
                               extra_context))
801 5ce3ce4f Sofia Papagiannaki
802 49790d9d Sofia Papagiannaki
    if not request.user.is_authenticated():
803 49790d9d Sofia Papagiannaki
        path = quote(request.get_full_path())
804 6ff7a7ca Sofia Papagiannaki
        url = request.build_absolute_uri(reverse('index'))
805 49790d9d Sofia Papagiannaki
        return HttpResponseRedirect(url + '?next=' + path)
806 53e0b8fe Kostas Papadimitriou
807 53e0b8fe Kostas Papadimitriou
    # clean up expired email changes
808 53e0b8fe Kostas Papadimitriou
    if request.user.email_change_is_pending():
809 53e0b8fe Kostas Papadimitriou
        change = request.user.emailchanges.get()
810 53e0b8fe Kostas Papadimitriou
        if change.activation_key_expired():
811 53e0b8fe Kostas Papadimitriou
            change.delete()
812 53e0b8fe Kostas Papadimitriou
            transaction.commit()
813 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('email_change'))
814 53e0b8fe Kostas Papadimitriou
815 49790d9d Sofia Papagiannaki
    form = EmailChangeForm(request.POST or None)
816 49790d9d Sofia Papagiannaki
    if request.method == 'POST' and form.is_valid():
817 49790d9d Sofia Papagiannaki
        try:
818 9d20fe23 Kostas Papadimitriou
            ec = form.save(request, email_template_name, request)
819 e7cb4085 Kostas Papadimitriou
        except Exception, e:
820 49790d9d Sofia Papagiannaki
            transaction.rollback()
821 e7cb4085 Kostas Papadimitriou
            raise
822 49790d9d Sofia Papagiannaki
        else:
823 ae497612 Olga Brani
            msg = _(astakos_messages.EMAIL_CHANGE_REGISTERED)
824 24406ae3 Sofia Papagiannaki
            messages.success(request, msg)
825 49790d9d Sofia Papagiannaki
            transaction.commit()
826 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
827 53e0b8fe Kostas Papadimitriou
828 53e0b8fe Kostas Papadimitriou
    if request.user.email_change_is_pending():
829 53e0b8fe Kostas Papadimitriou
        messages.warning(request, astakos_messages.PENDING_EMAIL_CHANGE_REQUEST)
830 53e0b8fe Kostas Papadimitriou
831 c0b26605 Sofia Papagiannaki
    return render_response(
832 c0b26605 Sofia Papagiannaki
        form_template_name,
833 c0b26605 Sofia Papagiannaki
        form=form,
834 c0b26605 Sofia Papagiannaki
        context_instance=get_context(request, extra_context)
835 c0b26605 Sofia Papagiannaki
    )
836 1f3b4b39 Sofia Papagiannaki
837 1f3b4b39 Sofia Papagiannaki
838 e7cb4085 Kostas Papadimitriou
def send_activation(request, user_id, template_name='im/login.html',
839 e7cb4085 Kostas Papadimitriou
                    extra_context=None):
840 792c2f3b Olga Brani
841 badcb2a9 Kostas Papadimitriou
    if request.user.is_authenticated():
842 e7cb4085 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
843 badcb2a9 Kostas Papadimitriou
844 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
845 1f3b4b39 Sofia Papagiannaki
    try:
846 1f3b4b39 Sofia Papagiannaki
        u = AstakosUser.objects.get(id=user_id)
847 1f3b4b39 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
848 c0b26605 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.ACCOUNT_UNKNOWN))
849 1f3b4b39 Sofia Papagiannaki
    else:
850 e7cb4085 Kostas Papadimitriou
        if u.email_verified:
851 e7cb4085 Kostas Papadimitriou
            logger.warning("[resend activation] Account already verified: %s",
852 e7cb4085 Kostas Papadimitriou
                           u.log_display)
853 e7cb4085 Kostas Papadimitriou
854 e7cb4085 Kostas Papadimitriou
            messages.error(request,
855 e7cb4085 Kostas Papadimitriou
                           _(astakos_messages.ACCOUNT_ALREADY_VERIFIED))
856 e7cb4085 Kostas Papadimitriou
        else:
857 e7cb4085 Kostas Papadimitriou
            activation_backend = activation_backends.get_backend()
858 e7cb4085 Kostas Papadimitriou
            activation_backend.send_user_verification_email(u)
859 e7cb4085 Kostas Papadimitriou
            messages.success(request, astakos_messages.ACTIVATION_SENT)
860 ff81d0d9 Kostas Papadimitriou
861 ff81d0d9 Kostas Papadimitriou
    return HttpResponseRedirect(reverse('index'))
862 5ce3ce4f Sofia Papagiannaki
863 73fbaec4 Sofia Papagiannaki
864 73fbaec4 Sofia Papagiannaki
@require_http_methods(["GET"])
865 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
866 666c7490 Sofia Papagiannaki
def resource_usage(request):
867 e9ef5009 Kostas Papadimitriou
868 37d59b27 Kostas Papadimitriou
    resources_meta = presentation.RESOURCES
869 37d59b27 Kostas Papadimitriou
870 4e03ba30 Kostas Papadimitriou
    current_usage = quotas.get_user_quotas(request.user)
871 4e03ba30 Kostas Papadimitriou
    current_usage = json.dumps(current_usage['system'])
872 37d59b27 Kostas Papadimitriou
    resource_catalog, resource_groups = _resources_catalog(for_usage=True)
873 37d59b27 Kostas Papadimitriou
    if resource_catalog is False:
874 37d59b27 Kostas Papadimitriou
        # on fail resource_groups contains the result object
875 37d59b27 Kostas Papadimitriou
        result = resource_groups
876 37d59b27 Kostas Papadimitriou
        messages.error(request, 'Unable to retrieve system resources: %s' %
877 37d59b27 Kostas Papadimitriou
                       result.reason)
878 37d59b27 Kostas Papadimitriou
879 4e03ba30 Kostas Papadimitriou
    resource_catalog = json.dumps(resource_catalog)
880 4e03ba30 Kostas Papadimitriou
    resource_groups = json.dumps(resource_groups)
881 37d59b27 Kostas Papadimitriou
    resources_order = json.dumps(resources_meta.get('resources_order'))
882 401089d8 Kostas Papadimitriou
883 666c7490 Sofia Papagiannaki
    return render_response('im/resource_usage.html',
884 3cbd5e47 Olga Brani
                           context_instance=get_context(request),
885 4e03ba30 Kostas Papadimitriou
                           resource_catalog=resource_catalog,
886 4e03ba30 Kostas Papadimitriou
                           resource_groups=resource_groups,
887 4e03ba30 Kostas Papadimitriou
                           resources_order=resources_order,
888 4e03ba30 Kostas Papadimitriou
                           current_usage=current_usage,
889 e7cb4085 Kostas Papadimitriou
                           token_cookie_name=settings.COOKIE_NAME,
890 4e03ba30 Kostas Papadimitriou
                           usage_update_interval=
891 e7cb4085 Kostas Papadimitriou
                           settings.USAGE_UPDATE_INTERVAL)
892 4e03ba30 Kostas Papadimitriou
893 9a06d96f Olga Brani
894 f432088a Kostas Papadimitriou
# TODO: action only on POST and user should confirm the removal
895 d2633501 Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
896 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
897 d2633501 Kostas Papadimitriou
def remove_auth_provider(request, pk):
898 f432088a Kostas Papadimitriou
    try:
899 9d20fe23 Kostas Papadimitriou
        provider = request.user.auth_providers.get(pk=int(pk)).settings
900 f432088a Kostas Papadimitriou
    except AstakosUserAuthProvider.DoesNotExist:
901 f432088a Kostas Papadimitriou
        raise Http404
902 f432088a Kostas Papadimitriou
903 9d20fe23 Kostas Papadimitriou
    if provider.get_remove_policy:
904 9d20fe23 Kostas Papadimitriou
        messages.success(request, provider.get_removed_msg)
905 9d20fe23 Kostas Papadimitriou
        provider.remove_from_user()
906 d2633501 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
907 d2633501 Kostas Papadimitriou
    else:
908 f432088a Kostas Papadimitriou
        raise PermissionDenied
909 5ebebb20 Olga Brani
910 792c2f3b Olga Brani
911 5ebebb20 Olga Brani
def how_it_works(request):
912 5ebebb20 Olga Brani
    return render_response(
913 ccab6eb5 Sofia Papagiannaki
        'im/how_it_works.html',
914 ccab6eb5 Sofia Papagiannaki
        context_instance=get_context(request))
915 e1a80257 Sofia Papagiannaki
916 39b2cb50 Giorgos Korfiatis
917 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
918 172ce682 Sofia Papagiannaki
def _create_object(request, model=None, template_name=None,
919 172ce682 Sofia Papagiannaki
        template_loader=template_loader, extra_context=None, post_save_redirect=None,
920 6556e514 Sofia Papagiannaki
        login_required=False, context_processors=None, form_class=None,
921 39b2cb50 Giorgos Korfiatis
        msg=None):
922 172ce682 Sofia Papagiannaki
    """
923 4e748491 Sofia Papagiannaki
    Based of django.views.generic.create_update.create_object which displays a
924 172ce682 Sofia Papagiannaki
    summary page before creating the object.
925 172ce682 Sofia Papagiannaki
    """
926 172ce682 Sofia Papagiannaki
    response = None
927 4e748491 Sofia Papagiannaki
928 4e748491 Sofia Papagiannaki
    if extra_context is None: extra_context = {}
929 4e748491 Sofia Papagiannaki
    if login_required and not request.user.is_authenticated():
930 4e748491 Sofia Papagiannaki
        return redirect_to_login(request.path)
931 ccab6eb5 Sofia Papagiannaki
    try:
932 f7cf5257 Kostas Papadimitriou
933 172ce682 Sofia Papagiannaki
        model, form_class = get_model_and_form_class(model, form_class)
934 172ce682 Sofia Papagiannaki
        extra_context['edit'] = 0
935 172ce682 Sofia Papagiannaki
        if request.method == 'POST':
936 172ce682 Sofia Papagiannaki
            form = form_class(request.POST, request.FILES)
937 172ce682 Sofia Papagiannaki
            if form.is_valid():
938 172ce682 Sofia Papagiannaki
                verify = request.GET.get('verify')
939 172ce682 Sofia Papagiannaki
                edit = request.GET.get('edit')
940 172ce682 Sofia Papagiannaki
                if verify == '1':
941 172ce682 Sofia Papagiannaki
                    extra_context['show_form'] = False
942 172ce682 Sofia Papagiannaki
                    extra_context['form_data'] = form.cleaned_data
943 172ce682 Sofia Papagiannaki
                elif edit == '1':
944 172ce682 Sofia Papagiannaki
                    extra_context['show_form'] = True
945 172ce682 Sofia Papagiannaki
                else:
946 172ce682 Sofia Papagiannaki
                    new_object = form.save()
947 6556e514 Sofia Papagiannaki
                    if not msg:
948 6556e514 Sofia Papagiannaki
                        msg = _("The %(verbose_name)s was created successfully.")
949 6556e514 Sofia Papagiannaki
                    msg = msg % model._meta.__dict__
950 172ce682 Sofia Papagiannaki
                    messages.success(request, msg, fail_silently=True)
951 172ce682 Sofia Papagiannaki
                    response = redirect(post_save_redirect, new_object)
952 172ce682 Sofia Papagiannaki
        else:
953 172ce682 Sofia Papagiannaki
            form = form_class()
954 39b2cb50 Giorgos Korfiatis
    except (IOError, PermissionDenied), e:
955 39b2cb50 Giorgos Korfiatis
        messages.error(request, e)
956 39b2cb50 Giorgos Korfiatis
        return None
957 39b2cb50 Giorgos Korfiatis
    else:
958 172ce682 Sofia Papagiannaki
        if response == None:
959 172ce682 Sofia Papagiannaki
            # Create the template, context, response
960 172ce682 Sofia Papagiannaki
            if not template_name:
961 172ce682 Sofia Papagiannaki
                template_name = "%s/%s_form.html" %\
962 172ce682 Sofia Papagiannaki
                     (model._meta.app_label, model._meta.object_name.lower())
963 172ce682 Sofia Papagiannaki
            t = template_loader.get_template(template_name)
964 172ce682 Sofia Papagiannaki
            c = RequestContext(request, {
965 172ce682 Sofia Papagiannaki
                'form': form
966 172ce682 Sofia Papagiannaki
            }, context_processors)
967 172ce682 Sofia Papagiannaki
            apply_extra_context(extra_context, c)
968 172ce682 Sofia Papagiannaki
            response = HttpResponse(t.render(c))
969 172ce682 Sofia Papagiannaki
        return response
970 172ce682 Sofia Papagiannaki
971 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
972 4e748491 Sofia Papagiannaki
def _update_object(request, model=None, object_id=None, slug=None,
973 4e748491 Sofia Papagiannaki
        slug_field='slug', template_name=None, template_loader=template_loader,
974 4e748491 Sofia Papagiannaki
        extra_context=None, post_save_redirect=None, login_required=False,
975 4e748491 Sofia Papagiannaki
        context_processors=None, template_object_name='object',
976 39b2cb50 Giorgos Korfiatis
        form_class=None, msg=None):
977 4e748491 Sofia Papagiannaki
    """
978 4e748491 Sofia Papagiannaki
    Based of django.views.generic.create_update.update_object which displays a
979 4e748491 Sofia Papagiannaki
    summary page before updating the object.
980 4e748491 Sofia Papagiannaki
    """
981 4e748491 Sofia Papagiannaki
    response = None
982 4e748491 Sofia Papagiannaki
983 4e748491 Sofia Papagiannaki
    if extra_context is None: extra_context = {}
984 4e748491 Sofia Papagiannaki
    if login_required and not request.user.is_authenticated():
985 4e748491 Sofia Papagiannaki
        return redirect_to_login(request.path)
986 f7cf5257 Kostas Papadimitriou
987 4e748491 Sofia Papagiannaki
    try:
988 4e748491 Sofia Papagiannaki
        model, form_class = get_model_and_form_class(model, form_class)
989 4e748491 Sofia Papagiannaki
        obj = lookup_object(model, object_id, slug, slug_field)
990 f7cf5257 Kostas Papadimitriou
991 4e748491 Sofia Papagiannaki
        if request.method == 'POST':
992 4e748491 Sofia Papagiannaki
            form = form_class(request.POST, request.FILES, instance=obj)
993 4e748491 Sofia Papagiannaki
            if form.is_valid():
994 4e748491 Sofia Papagiannaki
                verify = request.GET.get('verify')
995 4e748491 Sofia Papagiannaki
                edit = request.GET.get('edit')
996 4e748491 Sofia Papagiannaki
                if verify == '1':
997 4e748491 Sofia Papagiannaki
                    extra_context['show_form'] = False
998 4e748491 Sofia Papagiannaki
                    extra_context['form_data'] = form.cleaned_data
999 4e748491 Sofia Papagiannaki
                elif edit == '1':
1000 4e748491 Sofia Papagiannaki
                    extra_context['show_form'] = True
1001 f7cf5257 Kostas Papadimitriou
                else:
1002 4e748491 Sofia Papagiannaki
                    obj = form.save()
1003 6556e514 Sofia Papagiannaki
                    if not msg:
1004 6556e514 Sofia Papagiannaki
                        msg = _("The %(verbose_name)s was created successfully.")
1005 6556e514 Sofia Papagiannaki
                    msg = msg % model._meta.__dict__
1006 6556e514 Sofia Papagiannaki
                    messages.success(request, msg, fail_silently=True)
1007 4e748491 Sofia Papagiannaki
                    response = redirect(post_save_redirect, obj)
1008 4e748491 Sofia Papagiannaki
        else:
1009 4e748491 Sofia Papagiannaki
            form = form_class(instance=obj)
1010 39b2cb50 Giorgos Korfiatis
    except (IOError, PermissionDenied), e:
1011 39b2cb50 Giorgos Korfiatis
        messages.error(request, e)
1012 39b2cb50 Giorgos Korfiatis
        return None
1013 39b2cb50 Giorgos Korfiatis
    else:
1014 4e748491 Sofia Papagiannaki
        if response == None:
1015 4e748491 Sofia Papagiannaki
            if not template_name:
1016 4e748491 Sofia Papagiannaki
                template_name = "%s/%s_form.html" %\
1017 4e748491 Sofia Papagiannaki
                    (model._meta.app_label, model._meta.object_name.lower())
1018 4e748491 Sofia Papagiannaki
            t = template_loader.get_template(template_name)
1019 4e748491 Sofia Papagiannaki
            c = RequestContext(request, {
1020 4e748491 Sofia Papagiannaki
                'form': form,
1021 4e748491 Sofia Papagiannaki
                template_object_name: obj,
1022 4e748491 Sofia Papagiannaki
            }, context_processors)
1023 4e748491 Sofia Papagiannaki
            apply_extra_context(extra_context, c)
1024 4e748491 Sofia Papagiannaki
            response = HttpResponse(t.render(c))
1025 4e748491 Sofia Papagiannaki
            populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname))
1026 4e748491 Sofia Papagiannaki
        return response
1027 4e748491 Sofia Papagiannaki
1028 75380308 Kostas Papadimitriou
1029 c7c0ec58 Giorgos Korfiatis
1030 37d59b27 Kostas Papadimitriou
def _resources_catalog(for_project=False, for_usage=False):
1031 75380308 Kostas Papadimitriou
    """
1032 75380308 Kostas Papadimitriou
    `resource_catalog` contains a list of tuples. Each tuple contains the group
1033 75380308 Kostas Papadimitriou
    key the resource is assigned to and resources list of dicts that contain
1034 75380308 Kostas Papadimitriou
    resource information.
1035 75380308 Kostas Papadimitriou
    `resource_groups` contains information about the groups
1036 75380308 Kostas Papadimitriou
    """
1037 75380308 Kostas Papadimitriou
    # presentation data
1038 37d59b27 Kostas Papadimitriou
    resources_meta = presentation.RESOURCES
1039 37d59b27 Kostas Papadimitriou
    resource_groups = resources_meta.get('groups', {})
1040 75380308 Kostas Papadimitriou
    resource_catalog = ()
1041 0156e40c Kostas Papadimitriou
    resource_keys = []
1042 75380308 Kostas Papadimitriou
1043 75380308 Kostas Papadimitriou
    # resources in database
1044 b095201e Sofia Papagiannaki
    resource_details = map(lambda obj: model_to_dict(obj, exclude=[]),
1045 b095201e Sofia Papagiannaki
                           Resource.objects.all())
1046 b095201e Sofia Papagiannaki
    # initialize resource_catalog to contain all group/resource information
1047 b095201e Sofia Papagiannaki
    for r in resource_details:
1048 b095201e Sofia Papagiannaki
        if not r.get('group') in resource_groups:
1049 b095201e Sofia Papagiannaki
            resource_groups[r.get('group')] = {'icon': 'unknown'}
1050 b095201e Sofia Papagiannaki
1051 b095201e Sofia Papagiannaki
    resource_keys = [r.get('str_repr') for r in resource_details]
1052 b095201e Sofia Papagiannaki
    resource_catalog = [[g, filter(lambda r: r.get('group', '') == g,
1053 b095201e Sofia Papagiannaki
                                   resource_details)] for g in resource_groups]
1054 75380308 Kostas Papadimitriou
1055 75380308 Kostas Papadimitriou
    # order groups, also include unknown groups
1056 37d59b27 Kostas Papadimitriou
    groups_order = resources_meta.get('groups_order')
1057 75380308 Kostas Papadimitriou
    for g in resource_groups.keys():
1058 75380308 Kostas Papadimitriou
        if not g in groups_order:
1059 75380308 Kostas Papadimitriou
            groups_order.append(g)
1060 75380308 Kostas Papadimitriou
1061 75380308 Kostas Papadimitriou
    # order resources, also include unknown resources
1062 37d59b27 Kostas Papadimitriou
    resources_order = resources_meta.get('resources_order')
1063 75380308 Kostas Papadimitriou
    for r in resource_keys:
1064 75380308 Kostas Papadimitriou
        if not r in resources_order:
1065 75380308 Kostas Papadimitriou
            resources_order.append(r)
1066 75380308 Kostas Papadimitriou
1067 75380308 Kostas Papadimitriou
    # sort catalog groups
1068 75380308 Kostas Papadimitriou
    resource_catalog = sorted(resource_catalog,
1069 75380308 Kostas Papadimitriou
                              key=lambda g: groups_order.index(g[0]))
1070 75380308 Kostas Papadimitriou
1071 75380308 Kostas Papadimitriou
    # sort groups
1072 75380308 Kostas Papadimitriou
    def groupindex(g):
1073 75380308 Kostas Papadimitriou
        return groups_order.index(g[0])
1074 75380308 Kostas Papadimitriou
    resource_groups_list = sorted([(k, v) for k, v in resource_groups.items()],
1075 75380308 Kostas Papadimitriou
                                  key=groupindex)
1076 75380308 Kostas Papadimitriou
    resource_groups = OrderedDict(resource_groups_list)
1077 75380308 Kostas Papadimitriou
1078 75380308 Kostas Papadimitriou
    # sort resources
1079 75380308 Kostas Papadimitriou
    def resourceindex(r):
1080 75380308 Kostas Papadimitriou
        return resources_order.index(r['str_repr'])
1081 37d59b27 Kostas Papadimitriou
1082 75380308 Kostas Papadimitriou
    for index, group in enumerate(resource_catalog):
1083 75380308 Kostas Papadimitriou
        resource_catalog[index][1] = sorted(resource_catalog[index][1],
1084 75380308 Kostas Papadimitriou
                                            key=resourceindex)
1085 75380308 Kostas Papadimitriou
        if len(resource_catalog[index][1]) == 0:
1086 75380308 Kostas Papadimitriou
            resource_catalog.pop(index)
1087 75380308 Kostas Papadimitriou
            for gindex, g in enumerate(resource_groups):
1088 75380308 Kostas Papadimitriou
                if g[0] == group[0]:
1089 75380308 Kostas Papadimitriou
                    resource_groups.pop(gindex)
1090 75380308 Kostas Papadimitriou
1091 37d59b27 Kostas Papadimitriou
    # filter out resources which user cannot request in a project application
1092 37d59b27 Kostas Papadimitriou
    exclude = resources_meta.get('exclude_from_usage', [])
1093 37d59b27 Kostas Papadimitriou
    for group_index, group_resources in enumerate(list(resource_catalog)):
1094 37d59b27 Kostas Papadimitriou
        group, resources = group_resources
1095 37d59b27 Kostas Papadimitriou
        for index, resource in list(enumerate(resources)):
1096 37d59b27 Kostas Papadimitriou
            if for_project and not resource.get('allow_in_projects'):
1097 37d59b27 Kostas Papadimitriou
                resources.remove(resource)
1098 37d59b27 Kostas Papadimitriou
            if resource.get('str_repr') in exclude and for_usage:
1099 37d59b27 Kostas Papadimitriou
                resources.remove(resource)
1100 37d59b27 Kostas Papadimitriou
1101 37d59b27 Kostas Papadimitriou
    # cleanup empty groups
1102 37d59b27 Kostas Papadimitriou
    for group_index, group_resources in enumerate(list(resource_catalog)):
1103 37d59b27 Kostas Papadimitriou
        group, resources = group_resources
1104 37d59b27 Kostas Papadimitriou
        if len(resources) == 0:
1105 37d59b27 Kostas Papadimitriou
            resource_catalog.pop(group_index)
1106 37d59b27 Kostas Papadimitriou
            resource_groups.pop(group)
1107 37d59b27 Kostas Papadimitriou
1108 37d59b27 Kostas Papadimitriou
1109 75380308 Kostas Papadimitriou
    return resource_catalog, resource_groups
1110 75380308 Kostas Papadimitriou
1111 75380308 Kostas Papadimitriou
1112 172ce682 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1113 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1114 172ce682 Sofia Papagiannaki
def project_add(request):
1115 c7c0ec58 Giorgos Korfiatis
    user = request.user
1116 9770ba6c Giorgos Korfiatis
    if not user.is_project_admin():
1117 9770ba6c Giorgos Korfiatis
        ok, limit = qh_add_pending_app(user, dry_run=True)
1118 9770ba6c Giorgos Korfiatis
        if not ok:
1119 9770ba6c Giorgos Korfiatis
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_ADD) % limit
1120 9770ba6c Giorgos Korfiatis
            messages.error(request, m)
1121 9770ba6c Giorgos Korfiatis
            next = reverse('astakos.im.views.project_list')
1122 9770ba6c Giorgos Korfiatis
            next = restrict_next(next, domain=COOKIE_DOMAIN)
1123 9770ba6c Giorgos Korfiatis
            return redirect(next)
1124 c7c0ec58 Giorgos Korfiatis
1125 75380308 Kostas Papadimitriou
    details_fields = ["name", "homepage", "description", "start_date",
1126 75380308 Kostas Papadimitriou
                      "end_date", "comments"]
1127 75380308 Kostas Papadimitriou
    membership_fields = ["member_join_policy", "member_leave_policy",
1128 75380308 Kostas Papadimitriou
                         "limit_on_members_number"]
1129 37d59b27 Kostas Papadimitriou
    resource_catalog, resource_groups = _resources_catalog(for_project=True)
1130 37d59b27 Kostas Papadimitriou
    if resource_catalog is False:
1131 37d59b27 Kostas Papadimitriou
        # on fail resource_groups contains the result object
1132 37d59b27 Kostas Papadimitriou
        result = resource_groups
1133 37d59b27 Kostas Papadimitriou
        messages.error(request, 'Unable to retrieve system resources: %s' %
1134 37d59b27 Kostas Papadimitriou
                       result.reason)
1135 6556e514 Sofia Papagiannaki
    extra_context = {
1136 75380308 Kostas Papadimitriou
        'resource_catalog': resource_catalog,
1137 75380308 Kostas Papadimitriou
        'resource_groups': resource_groups,
1138 75380308 Kostas Papadimitriou
        'show_form': True,
1139 75380308 Kostas Papadimitriou
        'details_fields': details_fields,
1140 75380308 Kostas Papadimitriou
        'membership_fields': membership_fields}
1141 39b2cb50 Giorgos Korfiatis
1142 39b2cb50 Giorgos Korfiatis
    response = None
1143 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1144 39b2cb50 Giorgos Korfiatis
        response = _create_object(
1145 39b2cb50 Giorgos Korfiatis
            request,
1146 39b2cb50 Giorgos Korfiatis
            template_name='im/projects/projectapplication_form.html',
1147 39b2cb50 Giorgos Korfiatis
            extra_context=extra_context,
1148 39b2cb50 Giorgos Korfiatis
            post_save_redirect=reverse('project_list'),
1149 39b2cb50 Giorgos Korfiatis
            form_class=ProjectApplicationForm,
1150 39b2cb50 Giorgos Korfiatis
            msg=_("The %(verbose_name)s has been received and "
1151 39b2cb50 Giorgos Korfiatis
                  "is under consideration."),
1152 39b2cb50 Giorgos Korfiatis
            )
1153 39b2cb50 Giorgos Korfiatis
1154 39b2cb50 Giorgos Korfiatis
    if response is not None:
1155 39b2cb50 Giorgos Korfiatis
        return response
1156 39b2cb50 Giorgos Korfiatis
1157 39b2cb50 Giorgos Korfiatis
    next = reverse('astakos.im.views.project_list')
1158 39b2cb50 Giorgos Korfiatis
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1159 39b2cb50 Giorgos Korfiatis
    return redirect(next)
1160 ccab6eb5 Sofia Papagiannaki
1161 e1a80257 Sofia Papagiannaki
1162 e1a80257 Sofia Papagiannaki
@require_http_methods(["GET"])
1163 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1164 f3342849 Sofia Papagiannaki
def project_list(request):
1165 05617ab9 Kostas Papadimitriou
    projects = ProjectApplication.objects.user_accessible_projects(request.user).select_related()
1166 2743e261 Kostas Papadimitriou
    table = tables.UserProjectApplicationsTable(projects, user=request.user,
1167 2743e261 Kostas Papadimitriou
                                                prefix="my_projects_")
1168 e6d284ef Olga Brani
    RequestConfig(request, paginate={"per_page": PAGINATE_BY}).configure(table)
1169 f7cf5257 Kostas Papadimitriou
1170 e1a80257 Sofia Papagiannaki
    return object_list(
1171 e1a80257 Sofia Papagiannaki
        request,
1172 5550bcfb Kostas Papadimitriou
        projects,
1173 71a38edf Sofia Papagiannaki
        template_name='im/projects/project_list.html',
1174 71a38edf Sofia Papagiannaki
        extra_context={
1175 71a38edf Sofia Papagiannaki
            'is_search':False,
1176 5550bcfb Kostas Papadimitriou
            'table': table,
1177 3f0d6293 Kostas Papadimitriou
        })
1178 3f0d6293 Kostas Papadimitriou
1179 e1a80257 Sofia Papagiannaki
1180 d12e522d Kostas Papadimitriou
@require_http_methods(["POST"])
1181 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1182 39b2cb50 Giorgos Korfiatis
def project_app_cancel(request, application_id):
1183 39b2cb50 Giorgos Korfiatis
    next = request.GET.get('next')
1184 a75dbd7b Giorgos Korfiatis
    chain_id = None
1185 a75dbd7b Giorgos Korfiatis
1186 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1187 39b2cb50 Giorgos Korfiatis
        chain_id = _project_app_cancel(request, application_id)
1188 39b2cb50 Giorgos Korfiatis
1189 a75dbd7b Giorgos Korfiatis
    if not next:
1190 a75dbd7b Giorgos Korfiatis
        if chain_id:
1191 a75dbd7b Giorgos Korfiatis
            next = reverse('astakos.im.views.project_detail', args=(chain_id,))
1192 a75dbd7b Giorgos Korfiatis
        else:
1193 a75dbd7b Giorgos Korfiatis
            next = reverse('astakos.im.views.project_list')
1194 a75dbd7b Giorgos Korfiatis
1195 a75dbd7b Giorgos Korfiatis
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1196 a75dbd7b Giorgos Korfiatis
    return redirect(next)
1197 a75dbd7b Giorgos Korfiatis
1198 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1199 39b2cb50 Giorgos Korfiatis
def _project_app_cancel(request, application_id):
1200 39b2cb50 Giorgos Korfiatis
    chain_id = None
1201 39b2cb50 Giorgos Korfiatis
    try:
1202 39b2cb50 Giorgos Korfiatis
        application_id = int(application_id)
1203 39b2cb50 Giorgos Korfiatis
        chain_id = get_related_project_id(application_id)
1204 39b2cb50 Giorgos Korfiatis
        cancel_application(application_id, request.user)
1205 39b2cb50 Giorgos Korfiatis
    except (IOError, PermissionDenied), e:
1206 39b2cb50 Giorgos Korfiatis
        messages.error(request, e)
1207 5aa83766 Kostas Papadimitriou
1208 39b2cb50 Giorgos Korfiatis
    else:
1209 39b2cb50 Giorgos Korfiatis
        msg = _(astakos_messages.APPLICATION_CANCELLED)
1210 39b2cb50 Giorgos Korfiatis
        messages.success(request, msg)
1211 39b2cb50 Giorgos Korfiatis
        return chain_id
1212 39b2cb50 Giorgos Korfiatis
1213 a75dbd7b Giorgos Korfiatis
1214 a75dbd7b Giorgos Korfiatis
@require_http_methods(["GET", "POST"])
1215 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1216 3e3743f2 Giorgos Korfiatis
def project_modify(request, application_id):
1217 d4660e00 Giorgos Korfiatis
1218 d4660e00 Giorgos Korfiatis
    try:
1219 d4660e00 Giorgos Korfiatis
        app = ProjectApplication.objects.get(id=application_id)
1220 d4660e00 Giorgos Korfiatis
    except ProjectApplication.DoesNotExist:
1221 d4660e00 Giorgos Korfiatis
        raise Http404
1222 d4660e00 Giorgos Korfiatis
1223 beda5f0f Georgios D. Tsoukalas
    user = request.user
1224 beda5f0f Georgios D. Tsoukalas
    if not (user.owns_application(app) or user.is_project_admin(app.id)):
1225 d4660e00 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ALLOWED)
1226 d4660e00 Giorgos Korfiatis
        raise PermissionDenied(m)
1227 d4660e00 Giorgos Korfiatis
1228 9770ba6c Giorgos Korfiatis
    if not user.is_project_admin():
1229 9770ba6c Giorgos Korfiatis
        owner = app.owner
1230 9770ba6c Giorgos Korfiatis
        ok, limit = qh_add_pending_app(owner, precursor=app, dry_run=True)
1231 9770ba6c Giorgos Korfiatis
        if not ok:
1232 9770ba6c Giorgos Korfiatis
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_MODIFY) % limit
1233 9770ba6c Giorgos Korfiatis
            messages.error(request, m)
1234 9770ba6c Giorgos Korfiatis
            next = reverse('astakos.im.views.project_list')
1235 9770ba6c Giorgos Korfiatis
            next = restrict_next(next, domain=COOKIE_DOMAIN)
1236 9770ba6c Giorgos Korfiatis
            return redirect(next)
1237 c7c0ec58 Giorgos Korfiatis
1238 75380308 Kostas Papadimitriou
    details_fields = ["name", "homepage", "description", "start_date",
1239 75380308 Kostas Papadimitriou
                      "end_date", "comments"]
1240 75380308 Kostas Papadimitriou
    membership_fields = ["member_join_policy", "member_leave_policy",
1241 75380308 Kostas Papadimitriou
                         "limit_on_members_number"]
1242 37d59b27 Kostas Papadimitriou
    resource_catalog, resource_groups = _resources_catalog(for_project=True)
1243 37d59b27 Kostas Papadimitriou
    if resource_catalog is False:
1244 37d59b27 Kostas Papadimitriou
        # on fail resource_groups contains the result object
1245 37d59b27 Kostas Papadimitriou
        result = resource_groups
1246 37d59b27 Kostas Papadimitriou
        messages.error(request, 'Unable to retrieve system resources: %s' %
1247 37d59b27 Kostas Papadimitriou
                       result.reason)
1248 6556e514 Sofia Papagiannaki
    extra_context = {
1249 75380308 Kostas Papadimitriou
        'resource_catalog': resource_catalog,
1250 75380308 Kostas Papadimitriou
        'resource_groups': resource_groups,
1251 75380308 Kostas Papadimitriou
        'show_form': True,
1252 75380308 Kostas Papadimitriou
        'details_fields': details_fields,
1253 6003d0a8 Kostas Papadimitriou
        'update_form': True,
1254 75380308 Kostas Papadimitriou
        'membership_fields': membership_fields
1255 75380308 Kostas Papadimitriou
    }
1256 17a2f450 Sofia Papagiannaki
1257 39b2cb50 Giorgos Korfiatis
    response = None
1258 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1259 75380308 Kostas Papadimitriou
        response = _update_object(
1260 39b2cb50 Giorgos Korfiatis
            request,
1261 39b2cb50 Giorgos Korfiatis
            object_id=application_id,
1262 39b2cb50 Giorgos Korfiatis
            template_name='im/projects/projectapplication_form.html',
1263 75380308 Kostas Papadimitriou
            extra_context=extra_context,
1264 75380308 Kostas Papadimitriou
            post_save_redirect=reverse('project_list'),
1265 39b2cb50 Giorgos Korfiatis
            form_class=ProjectApplicationForm,
1266 75380308 Kostas Papadimitriou
            msg=_("The %(verbose_name)s has been received and is under "
1267 75380308 Kostas Papadimitriou
                  "consideration."))
1268 39b2cb50 Giorgos Korfiatis
1269 39b2cb50 Giorgos Korfiatis
    if response is not None:
1270 39b2cb50 Giorgos Korfiatis
        return response
1271 39b2cb50 Giorgos Korfiatis
1272 39b2cb50 Giorgos Korfiatis
    next = reverse('astakos.im.views.project_list')
1273 39b2cb50 Giorgos Korfiatis
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1274 39b2cb50 Giorgos Korfiatis
    return redirect(next)
1275 e1a80257 Sofia Papagiannaki
1276 e1a80257 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1277 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1278 3e3743f2 Giorgos Korfiatis
def project_app(request, application_id):
1279 d4660e00 Giorgos Korfiatis
    return common_detail(request, application_id, project_view=False)
1280 3e3743f2 Giorgos Korfiatis
1281 3e3743f2 Giorgos Korfiatis
@require_http_methods(["GET", "POST"])
1282 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1283 ff67242a Giorgos Korfiatis
def project_detail(request, chain_id):
1284 3e3743f2 Giorgos Korfiatis
    return common_detail(request, chain_id)
1285 3e3743f2 Giorgos Korfiatis
1286 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1287 39b2cb50 Giorgos Korfiatis
def addmembers(request, chain_id, addmembers_form):
1288 3e3743f2 Giorgos Korfiatis
    if addmembers_form.is_valid():
1289 3e3743f2 Giorgos Korfiatis
        try:
1290 3e3743f2 Giorgos Korfiatis
            chain_id = int(chain_id)
1291 3e3743f2 Giorgos Korfiatis
            map(lambda u: enroll_member(
1292 3e3743f2 Giorgos Korfiatis
                    chain_id,
1293 3e3743f2 Giorgos Korfiatis
                    u,
1294 3e3743f2 Giorgos Korfiatis
                    request_user=request.user),
1295 3e3743f2 Giorgos Korfiatis
                addmembers_form.valid_users)
1296 3e3743f2 Giorgos Korfiatis
        except (IOError, PermissionDenied), e:
1297 3e3743f2 Giorgos Korfiatis
            messages.error(request, e)
1298 f7cf5257 Kostas Papadimitriou
1299 d4660e00 Giorgos Korfiatis
def common_detail(request, chain_or_app_id, project_view=True):
1300 d4660e00 Giorgos Korfiatis
    project = None
1301 d4660e00 Giorgos Korfiatis
    if project_view:
1302 f7e8a6af Giorgos Korfiatis
        chain_id = chain_or_app_id
1303 3e3743f2 Giorgos Korfiatis
        if request.method == 'POST':
1304 27900ab0 Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm(
1305 27900ab0 Sofia Papagiannaki
                request.POST,
1306 27900ab0 Sofia Papagiannaki
                chain_id=int(chain_id),
1307 27900ab0 Sofia Papagiannaki
                request_user=request.user)
1308 39b2cb50 Giorgos Korfiatis
            with ExceptionHandler(request):
1309 39b2cb50 Giorgos Korfiatis
                addmembers(request, chain_id, addmembers_form)
1310 39b2cb50 Giorgos Korfiatis
1311 efb334ca Sofia Papagiannaki
            if addmembers_form.is_valid():
1312 efb334ca Sofia Papagiannaki
                addmembers_form = AddProjectMembersForm()  # clear form data
1313 27900ab0 Sofia Papagiannaki
        else:
1314 efb334ca Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm()  # initialize form
1315 3e3743f2 Giorgos Korfiatis
1316 f7e8a6af Giorgos Korfiatis
        project, application = get_by_chain_or_404(chain_id)
1317 3e3743f2 Giorgos Korfiatis
        if project:
1318 3e3743f2 Giorgos Korfiatis
            members = project.projectmembership_set.select_related()
1319 3e3743f2 Giorgos Korfiatis
            members_table = tables.ProjectMembersTable(project,
1320 3e3743f2 Giorgos Korfiatis
                                                       members,
1321 3e3743f2 Giorgos Korfiatis
                                                       user=request.user,
1322 3e3743f2 Giorgos Korfiatis
                                                       prefix="members_")
1323 3e3743f2 Giorgos Korfiatis
            RequestConfig(request, paginate={"per_page": PAGINATE_BY}
1324 3e3743f2 Giorgos Korfiatis
                          ).configure(members_table)
1325 3e3743f2 Giorgos Korfiatis
1326 3e3743f2 Giorgos Korfiatis
        else:
1327 3e3743f2 Giorgos Korfiatis
            members_table = None
1328 3f0d6293 Kostas Papadimitriou
1329 3e3743f2 Giorgos Korfiatis
    else: # is application
1330 f7e8a6af Giorgos Korfiatis
        application_id = chain_or_app_id
1331 f7e8a6af Giorgos Korfiatis
        application = get_object_or_404(ProjectApplication, pk=application_id)
1332 3e3743f2 Giorgos Korfiatis
        members_table = None
1333 3e3743f2 Giorgos Korfiatis
        addmembers_form = None
1334 2743e261 Kostas Papadimitriou
1335 9b32e2fb Kostas Papadimitriou
    modifications_table = None
1336 7184f408 Giorgos Korfiatis
1337 d4660e00 Giorgos Korfiatis
    user = request.user
1338 8e1a5af5 Georgios D. Tsoukalas
    is_project_admin = user.is_project_admin(application_id=application.id)
1339 d4660e00 Giorgos Korfiatis
    is_owner = user.owns_application(application)
1340 beda5f0f Georgios D. Tsoukalas
    if not (is_owner or is_project_admin) and not project_view:
1341 d4660e00 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ALLOWED)
1342 d4660e00 Giorgos Korfiatis
        raise PermissionDenied(m)
1343 d4660e00 Giorgos Korfiatis
1344 beda5f0f Georgios D. Tsoukalas
    if (not (is_owner or is_project_admin) and project_view and
1345 7f31a7a3 Giorgos Korfiatis
        not user.non_owner_can_view(project)):
1346 d4660e00 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ALLOWED)
1347 d4660e00 Giorgos Korfiatis
        raise PermissionDenied(m)
1348 d4660e00 Giorgos Korfiatis
1349 3e3743f2 Giorgos Korfiatis
    following_applications = list(application.pending_modifications())
1350 7184f408 Giorgos Korfiatis
    following_applications.reverse()
1351 3e3743f2 Giorgos Korfiatis
    modifications_table = (
1352 7184f408 Giorgos Korfiatis
        tables.ProjectModificationApplicationsTable(following_applications,
1353 7184f408 Giorgos Korfiatis
                                                    user=request.user,
1354 3e3743f2 Giorgos Korfiatis
                                                    prefix="modifications_"))
1355 9b32e2fb Kostas Papadimitriou
1356 d4660e00 Giorgos Korfiatis
    mem_display = user.membership_display(project) if project else None
1357 d4660e00 Giorgos Korfiatis
    can_join_req = can_join_request(project, user) if project else False
1358 d4660e00 Giorgos Korfiatis
    can_leave_req = can_leave_request(project, user) if project else False
1359 d4660e00 Giorgos Korfiatis
1360 c55e840a Sofia Papagiannaki
    return object_detail(
1361 c55e840a Sofia Papagiannaki
        request,
1362 c55e840a Sofia Papagiannaki
        queryset=ProjectApplication.objects.select_related(),
1363 ff67242a Giorgos Korfiatis
        object_id=application.id,
1364 c55e840a Sofia Papagiannaki
        template_name='im/projects/project_detail.html',
1365 c55e840a Sofia Papagiannaki
        extra_context={
1366 d4660e00 Giorgos Korfiatis
            'project_view': project_view,
1367 c55e840a Sofia Papagiannaki
            'addmembers_form':addmembers_form,
1368 624f5625 Kostas Papadimitriou
            'members_table': members_table,
1369 d4660e00 Giorgos Korfiatis
            'owner_mode': is_owner,
1370 8e1a5af5 Georgios D. Tsoukalas
            'admin_mode': is_project_admin,
1371 db9a498c Kostas Papadimitriou
            'modifications_table': modifications_table,
1372 d4660e00 Giorgos Korfiatis
            'mem_display': mem_display,
1373 d4660e00 Giorgos Korfiatis
            'can_join_request': can_join_req,
1374 d4660e00 Giorgos Korfiatis
            'can_leave_request': can_leave_req,
1375 2743e261 Kostas Papadimitriou
            })
1376 5550bcfb Kostas Papadimitriou
1377 e1a80257 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1378 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1379 e1a80257 Sofia Papagiannaki
def project_search(request):
1380 5550bcfb Kostas Papadimitriou
    q = request.GET.get('q', '')
1381 a5cef8d0 Kostas Papadimitriou
    form = ProjectSearchForm()
1382 a5cef8d0 Kostas Papadimitriou
    q = q.strip()
1383 48421603 Kostas Papadimitriou
1384 a5cef8d0 Kostas Papadimitriou
    if request.method == "POST":
1385 48421603 Kostas Papadimitriou
        form = ProjectSearchForm(request.POST)
1386 48421603 Kostas Papadimitriou
        if form.is_valid():
1387 48421603 Kostas Papadimitriou
            q = form.cleaned_data['q'].strip()
1388 48421603 Kostas Papadimitriou
        else:
1389 a5cef8d0 Kostas Papadimitriou
            q = None
1390 a5cef8d0 Kostas Papadimitriou
1391 a5cef8d0 Kostas Papadimitriou
    if q is None:
1392 a5cef8d0 Kostas Papadimitriou
        projects = ProjectApplication.objects.none()
1393 a5cef8d0 Kostas Papadimitriou
    else:
1394 324fb588 Sofia Papagiannaki
        accepted_projects = request.user.projectmembership_set.filter(
1395 324fb588 Sofia Papagiannaki
            ~Q(acceptance_date__isnull=True)).values_list('project', flat=True)
1396 a5cef8d0 Kostas Papadimitriou
        projects = ProjectApplication.objects.search_by_name(q)
1397 a5cef8d0 Kostas Papadimitriou
        projects = projects.filter(~Q(project__last_approval_date__isnull=True))
1398 324fb588 Sofia Papagiannaki
        projects = projects.exclude(project__in=accepted_projects)
1399 ca5148f2 Kostas Papadimitriou
1400 2743e261 Kostas Papadimitriou
    table = tables.UserProjectApplicationsTable(projects, user=request.user,
1401 2743e261 Kostas Papadimitriou
                                                prefix="my_projects_")
1402 b87429e1 Olga Brani
    if request.method == "POST":
1403 b87429e1 Olga Brani
        table.caption = _('SEARCH RESULTS')
1404 b87429e1 Olga Brani
    else:
1405 b87429e1 Olga Brani
        table.caption = _('ALL PROJECTS')
1406 ca5148f2 Kostas Papadimitriou
1407 e6d284ef Olga Brani
    RequestConfig(request, paginate={"per_page": PAGINATE_BY}).configure(table)
1408 48421603 Kostas Papadimitriou
1409 bfe23b13 Sofia Papagiannaki
    return object_list(
1410 bfe23b13 Sofia Papagiannaki
        request,
1411 a5cef8d0 Kostas Papadimitriou
        projects,
1412 6dadd24a Sofia Papagiannaki
        template_name='im/projects/project_list.html',
1413 a5cef8d0 Kostas Papadimitriou
        extra_context={
1414 a5cef8d0 Kostas Papadimitriou
          'form': form,
1415 a5cef8d0 Kostas Papadimitriou
          'is_search': True,
1416 a5cef8d0 Kostas Papadimitriou
          'q': q,
1417 a5cef8d0 Kostas Papadimitriou
          'table': table
1418 a5cef8d0 Kostas Papadimitriou
        })
1419 bfe23b13 Sofia Papagiannaki
1420 44f2d10d Kostas Papadimitriou
@require_http_methods(["POST"])
1421 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1422 39b2cb50 Giorgos Korfiatis
def project_join(request, chain_id):
1423 974ee6a6 Sofia Papagiannaki
    next = request.GET.get('next')
1424 73fbaec4 Sofia Papagiannaki
    if not next:
1425 f807da72 Kostas Papadimitriou
        next = reverse('astakos.im.views.project_detail',
1426 ff67242a Giorgos Korfiatis
                       args=(chain_id,))
1427 73fbaec4 Sofia Papagiannaki
1428 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1429 39b2cb50 Giorgos Korfiatis
        _project_join(request, chain_id)
1430 39b2cb50 Giorgos Korfiatis
1431 39b2cb50 Giorgos Korfiatis
1432 39b2cb50 Giorgos Korfiatis
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1433 39b2cb50 Giorgos Korfiatis
    return redirect(next)
1434 39b2cb50 Giorgos Korfiatis
1435 39b2cb50 Giorgos Korfiatis
1436 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1437 39b2cb50 Giorgos Korfiatis
def _project_join(request, chain_id):
1438 bfe23b13 Sofia Papagiannaki
    try:
1439 ff67242a Giorgos Korfiatis
        chain_id = int(chain_id)
1440 d07ce657 Giorgos Korfiatis
        auto_accepted = join_project(chain_id, request.user)
1441 bb6a4465 Giorgos Korfiatis
        if auto_accepted:
1442 bb6a4465 Giorgos Korfiatis
            m = _(astakos_messages.USER_JOINED_PROJECT)
1443 bb6a4465 Giorgos Korfiatis
        else:
1444 bb6a4465 Giorgos Korfiatis
            m = _(astakos_messages.USER_JOIN_REQUEST_SUBMITTED)
1445 bb6a4465 Giorgos Korfiatis
        messages.success(request, m)
1446 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1447 bfe23b13 Sofia Papagiannaki
        messages.error(request, e)
1448 39b2cb50 Giorgos Korfiatis
1449 bfe23b13 Sofia Papagiannaki
1450 44f2d10d Kostas Papadimitriou
@require_http_methods(["POST"])
1451 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1452 39b2cb50 Giorgos Korfiatis
def project_leave(request, chain_id):
1453 974ee6a6 Sofia Papagiannaki
    next = request.GET.get('next')
1454 73fbaec4 Sofia Papagiannaki
    if not next:
1455 ed1999ad Kostas Papadimitriou
        next = reverse('astakos.im.views.project_list')
1456 e1a80257 Sofia Papagiannaki
1457 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1458 39b2cb50 Giorgos Korfiatis
        _project_leave(request, chain_id)
1459 39b2cb50 Giorgos Korfiatis
1460 39b2cb50 Giorgos Korfiatis
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1461 39b2cb50 Giorgos Korfiatis
    return redirect(next)
1462 39b2cb50 Giorgos Korfiatis
1463 39b2cb50 Giorgos Korfiatis
1464 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1465 39b2cb50 Giorgos Korfiatis
def _project_leave(request, chain_id):
1466 73fbaec4 Sofia Papagiannaki
    try:
1467 ff67242a Giorgos Korfiatis
        chain_id = int(chain_id)
1468 d07ce657 Giorgos Korfiatis
        auto_accepted = leave_project(chain_id, request.user)
1469 bb6a4465 Giorgos Korfiatis
        if auto_accepted:
1470 bb6a4465 Giorgos Korfiatis
            m = _(astakos_messages.USER_LEFT_PROJECT)
1471 bb6a4465 Giorgos Korfiatis
        else:
1472 bb6a4465 Giorgos Korfiatis
            m = _(astakos_messages.USER_LEAVE_REQUEST_SUBMITTED)
1473 bb6a4465 Giorgos Korfiatis
        messages.success(request, m)
1474 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1475 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1476 39b2cb50 Giorgos Korfiatis
1477 aad0e329 Giorgos Korfiatis
1478 aad0e329 Giorgos Korfiatis
@require_http_methods(["POST"])
1479 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1480 39b2cb50 Giorgos Korfiatis
def project_cancel(request, chain_id):
1481 aad0e329 Giorgos Korfiatis
    next = request.GET.get('next')
1482 aad0e329 Giorgos Korfiatis
    if not next:
1483 aad0e329 Giorgos Korfiatis
        next = reverse('astakos.im.views.project_list')
1484 aad0e329 Giorgos Korfiatis
1485 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1486 39b2cb50 Giorgos Korfiatis
        _project_cancel(request, chain_id)
1487 39b2cb50 Giorgos Korfiatis
1488 39b2cb50 Giorgos Korfiatis
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1489 39b2cb50 Giorgos Korfiatis
    return redirect(next)
1490 39b2cb50 Giorgos Korfiatis
1491 39b2cb50 Giorgos Korfiatis
1492 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1493 39b2cb50 Giorgos Korfiatis
def _project_cancel(request, chain_id):
1494 aad0e329 Giorgos Korfiatis
    try:
1495 aad0e329 Giorgos Korfiatis
        chain_id = int(chain_id)
1496 aad0e329 Giorgos Korfiatis
        cancel_membership(chain_id, request.user)
1497 bb6a4465 Giorgos Korfiatis
        m = _(astakos_messages.USER_REQUEST_CANCELLED)
1498 bb6a4465 Giorgos Korfiatis
        messages.success(request, m)
1499 aad0e329 Giorgos Korfiatis
    except (IOError, PermissionDenied), e:
1500 aad0e329 Giorgos Korfiatis
        messages.error(request, e)
1501 f7cf5257 Kostas Papadimitriou
1502 bfe23b13 Sofia Papagiannaki
1503 bfe23b13 Sofia Papagiannaki
1504 16b22352 Kostas Papadimitriou
@require_http_methods(["POST"])
1505 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1506 7f3c4920 Giorgos Korfiatis
def project_accept_member(request, chain_id, memb_id):
1507 39b2cb50 Giorgos Korfiatis
1508 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1509 7f3c4920 Giorgos Korfiatis
        _project_accept_member(request, chain_id, memb_id)
1510 39b2cb50 Giorgos Korfiatis
1511 39b2cb50 Giorgos Korfiatis
    return redirect(reverse('project_detail', args=(chain_id,)))
1512 39b2cb50 Giorgos Korfiatis
1513 39b2cb50 Giorgos Korfiatis
1514 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1515 7f3c4920 Giorgos Korfiatis
def _project_accept_member(request, chain_id, memb_id):
1516 73fbaec4 Sofia Papagiannaki
    try:
1517 ff67242a Giorgos Korfiatis
        chain_id = int(chain_id)
1518 7f3c4920 Giorgos Korfiatis
        memb_id = int(memb_id)
1519 7f3c4920 Giorgos Korfiatis
        m = accept_membership(chain_id, memb_id, request.user)
1520 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1521 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1522 5aa83766 Kostas Papadimitriou
1523 73fbaec4 Sofia Papagiannaki
    else:
1524 5cc7d5b3 Giorgos Korfiatis
        email = escape(m.person.email)
1525 5cc7d5b3 Giorgos Korfiatis
        msg = _(astakos_messages.USER_MEMBERSHIP_ACCEPTED) % email
1526 73fbaec4 Sofia Papagiannaki
        messages.success(request, msg)
1527 39b2cb50 Giorgos Korfiatis
1528 bfe23b13 Sofia Papagiannaki
1529 f3a45fc6 Kostas Papadimitriou
@require_http_methods(["POST"])
1530 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1531 7f3c4920 Giorgos Korfiatis
def project_remove_member(request, chain_id, memb_id):
1532 39b2cb50 Giorgos Korfiatis
1533 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1534 7f3c4920 Giorgos Korfiatis
        _project_remove_member(request, chain_id, memb_id)
1535 39b2cb50 Giorgos Korfiatis
1536 39b2cb50 Giorgos Korfiatis
    return redirect(reverse('project_detail', args=(chain_id,)))
1537 39b2cb50 Giorgos Korfiatis
1538 39b2cb50 Giorgos Korfiatis
1539 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1540 7f3c4920 Giorgos Korfiatis
def _project_remove_member(request, chain_id, memb_id):
1541 73fbaec4 Sofia Papagiannaki
    try:
1542 ff67242a Giorgos Korfiatis
        chain_id = int(chain_id)
1543 7f3c4920 Giorgos Korfiatis
        memb_id = int(memb_id)
1544 7f3c4920 Giorgos Korfiatis
        m = remove_membership(chain_id, memb_id, request.user)
1545 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1546 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1547 73fbaec4 Sofia Papagiannaki
    else:
1548 5cc7d5b3 Giorgos Korfiatis
        email = escape(m.person.email)
1549 5cc7d5b3 Giorgos Korfiatis
        msg = _(astakos_messages.USER_MEMBERSHIP_REMOVED) % email
1550 73fbaec4 Sofia Papagiannaki
        messages.success(request, msg)
1551 39b2cb50 Giorgos Korfiatis
1552 bfe23b13 Sofia Papagiannaki
1553 f3a45fc6 Kostas Papadimitriou
@require_http_methods(["POST"])
1554 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
1555 7f3c4920 Giorgos Korfiatis
def project_reject_member(request, chain_id, memb_id):
1556 39b2cb50 Giorgos Korfiatis
1557 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1558 7f3c4920 Giorgos Korfiatis
        _project_reject_member(request, chain_id, memb_id)
1559 39b2cb50 Giorgos Korfiatis
1560 39b2cb50 Giorgos Korfiatis
    return redirect(reverse('project_detail', args=(chain_id,)))
1561 39b2cb50 Giorgos Korfiatis
1562 39b2cb50 Giorgos Korfiatis
1563 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1564 7f3c4920 Giorgos Korfiatis
def _project_reject_member(request, chain_id, memb_id):
1565 73fbaec4 Sofia Papagiannaki
    try:
1566 ff67242a Giorgos Korfiatis
        chain_id = int(chain_id)
1567 7f3c4920 Giorgos Korfiatis
        memb_id = int(memb_id)
1568 7f3c4920 Giorgos Korfiatis
        m = reject_membership(chain_id, memb_id, request.user)
1569 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1570 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1571 73fbaec4 Sofia Papagiannaki
    else:
1572 5cc7d5b3 Giorgos Korfiatis
        email = escape(m.person.email)
1573 5cc7d5b3 Giorgos Korfiatis
        msg = _(astakos_messages.USER_MEMBERSHIP_REJECTED) % email
1574 73fbaec4 Sofia Papagiannaki
        messages.success(request, msg)
1575 39b2cb50 Giorgos Korfiatis
1576 c630fee6 Kostas Papadimitriou
1577 d12e522d Kostas Papadimitriou
@require_http_methods(["POST"])
1578 8e1a5af5 Georgios D. Tsoukalas
@signed_terms_required
1579 8e1a5af5 Georgios D. Tsoukalas
@login_required
1580 39b2cb50 Giorgos Korfiatis
def project_app_approve(request, application_id):
1581 8e1a5af5 Georgios D. Tsoukalas
1582 8e1a5af5 Georgios D. Tsoukalas
    if not request.user.is_project_admin():
1583 8e1a5af5 Georgios D. Tsoukalas
        m = _(astakos_messages.NOT_ALLOWED)
1584 8e1a5af5 Georgios D. Tsoukalas
        raise PermissionDenied(m)
1585 8e1a5af5 Georgios D. Tsoukalas
1586 8e1a5af5 Georgios D. Tsoukalas
    try:
1587 8e1a5af5 Georgios D. Tsoukalas
        app = ProjectApplication.objects.get(id=application_id)
1588 8e1a5af5 Georgios D. Tsoukalas
    except ProjectApplication.DoesNotExist:
1589 8e1a5af5 Georgios D. Tsoukalas
        raise Http404
1590 8e1a5af5 Georgios D. Tsoukalas
1591 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1592 39b2cb50 Giorgos Korfiatis
        _project_app_approve(request, application_id)
1593 39b2cb50 Giorgos Korfiatis
1594 8e1a5af5 Georgios D. Tsoukalas
    chain_id = get_related_project_id(application_id)
1595 8e1a5af5 Georgios D. Tsoukalas
    return redirect(reverse('project_detail', args=(chain_id,)))
1596 8e1a5af5 Georgios D. Tsoukalas
1597 39b2cb50 Giorgos Korfiatis
1598 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1599 39b2cb50 Giorgos Korfiatis
def _project_app_approve(request, application_id):
1600 39b2cb50 Giorgos Korfiatis
    approve_application(application_id)
1601 39b2cb50 Giorgos Korfiatis
1602 39b2cb50 Giorgos Korfiatis
1603 d12e522d Kostas Papadimitriou
@require_http_methods(["POST"])
1604 8e1a5af5 Georgios D. Tsoukalas
@signed_terms_required
1605 8e1a5af5 Georgios D. Tsoukalas
@login_required
1606 39b2cb50 Giorgos Korfiatis
def project_app_deny(request, application_id):
1607 8e1a5af5 Georgios D. Tsoukalas
1608 249026ef Kostas Papadimitriou
    reason = request.POST.get('reason', None)
1609 249026ef Kostas Papadimitriou
    if not reason:
1610 249026ef Kostas Papadimitriou
        reason = None
1611 249026ef Kostas Papadimitriou
1612 8e1a5af5 Georgios D. Tsoukalas
    if not request.user.is_project_admin():
1613 8e1a5af5 Georgios D. Tsoukalas
        m = _(astakos_messages.NOT_ALLOWED)
1614 8e1a5af5 Georgios D. Tsoukalas
        raise PermissionDenied(m)
1615 8e1a5af5 Georgios D. Tsoukalas
1616 8e1a5af5 Georgios D. Tsoukalas
    try:
1617 8e1a5af5 Georgios D. Tsoukalas
        app = ProjectApplication.objects.get(id=application_id)
1618 8e1a5af5 Georgios D. Tsoukalas
    except ProjectApplication.DoesNotExist:
1619 8e1a5af5 Georgios D. Tsoukalas
        raise Http404
1620 8e1a5af5 Georgios D. Tsoukalas
1621 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1622 39b2cb50 Giorgos Korfiatis
        _project_app_deny(request, application_id, reason)
1623 39b2cb50 Giorgos Korfiatis
1624 8e1a5af5 Georgios D. Tsoukalas
    return redirect(reverse('project_list'))
1625 8e1a5af5 Georgios D. Tsoukalas
1626 39b2cb50 Giorgos Korfiatis
1627 39b2cb50 Giorgos Korfiatis
@commit_on_success_strict()
1628 39b2cb50 Giorgos Korfiatis
def _project_app_deny(request, application_id, reason):
1629 39b2cb50 Giorgos Korfiatis
    deny_application(application_id, reason=reason)
1630 39b2cb50 Giorgos Korfiatis
1631 39b2cb50 Giorgos Korfiatis
1632 d12e522d Kostas Papadimitriou
@require_http_methods(["POST"])
1633 8e1a5af5 Georgios D. Tsoukalas
@signed_terms_required
1634 8e1a5af5 Georgios D. Tsoukalas
@login_required
1635 39b2cb50 Giorgos Korfiatis
def project_app_dismiss(request, application_id):
1636 8e1a5af5 Georgios D. Tsoukalas
    try:
1637 8e1a5af5 Georgios D. Tsoukalas
        app = ProjectApplication.objects.get(id=application_id)
1638 8e1a5af5 Georgios D. Tsoukalas
    except ProjectApplication.DoesNotExist:
1639 8e1a5af5 Georgios D. Tsoukalas
        raise Http404
1640 8e1a5af5 Georgios D. Tsoukalas
1641 8e1a5af5 Georgios D. Tsoukalas
    if not request.user.owns_application(app):
1642 8e1a5af5 Georgios D. Tsoukalas
        m = _(astakos_messages.NOT_ALLOWED)
1643 8e1a5af5 Georgios D. Tsoukalas
        raise PermissionDenied(m)
1644 8e1a5af5 Georgios D. Tsoukalas
1645 39b2cb50 Giorgos Korfiatis
    with ExceptionHandler(request):
1646 39b2cb50 Giorgos Korfiatis
        _project_app_dismiss(request, application_id)
1647 022cc8e2 Giorgos Korfiatis
1648 022cc8e2 Giorgos Korfiatis
    chain_id = None
1649 022cc8e2 Giorgos Korfiatis
    chain_id = get_related_project_id(application_id)
1650 022cc8e2 Giorgos Korfiatis
    if chain_id:
1651 022cc8e2 Giorgos Korfiatis
        next = reverse('project_detail', args=(chain_id,))
1652 022cc8e2 Giorgos Korfiatis
    else:
1653 022cc8e2 Giorgos Korfiatis
        next = reverse('project_list')
1654 022cc8e2 Giorgos Korfiatis
    return redirect(next)
1655 022cc8e2 Giorgos Korfiatis
1656 39b2cb50 Giorgos Korfiatis
1657 39b2cb50 Giorgos Korfiatis
def _project_app_dismiss(request, application_id):
1658 39b2cb50 Giorgos Korfiatis
    # XXX: dismiss application also does authorization
1659 39b2cb50 Giorgos Korfiatis
    dismiss_application(application_id, request_user=request.user)
1660 39b2cb50 Giorgos Korfiatis
1661 39b2cb50 Giorgos Korfiatis
1662 9d20fe23 Kostas Papadimitriou
@require_http_methods(["GET"])
1663 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
1664 9d20fe23 Kostas Papadimitriou
@login_required
1665 9d20fe23 Kostas Papadimitriou
@signed_terms_required
1666 003d8fcf Olga Brani
def landing(request):
1667 0156e40c Kostas Papadimitriou
    context = {'services': Service.catalog(orderfor='dashboard')}
1668 003d8fcf Olga Brani
    return render_response(
1669 003d8fcf Olga Brani
        'im/landing.html',
1670 0156e40c Kostas Papadimitriou
        context_instance=get_context(request), **context)
1671 b87429e1 Olga Brani
1672 ca5148f2 Kostas Papadimitriou
1673 b87429e1 Olga Brani
def api_access(request):
1674 b87429e1 Olga Brani
    return render_response(
1675 b87429e1 Olga Brani
        'im/api_access.html',
1676 ca5148f2 Kostas Papadimitriou
        context_instance=get_context(request))