Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 764d99c4

History | View | Annotate | Download (58.8 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 29b0ec5a Sofia Papagiannaki
from astakos.im.activation_backends import get_backend, SimpleBackend
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 f3342849 Sofia Papagiannaki
    send_feedback, SendMailError,
95 f3342849 Sofia Papagiannaki
    logout as auth_logout,
96 f3342849 Sofia Papagiannaki
    activate as activate_func,
97 9cdb86fd Sofia Papagiannaki
    invite as invite_func,
98 f3342849 Sofia Papagiannaki
    send_activation as send_activation_func,
99 73fbaec4 Sofia Papagiannaki
    SendNotificationError,
100 9770ba6c Giorgos Korfiatis
    qh_add_pending_app,
101 aad0e329 Giorgos Korfiatis
    accept_membership, reject_membership, remove_membership, cancel_membership,
102 d4660e00 Giorgos Korfiatis
    leave_project, join_project, enroll_member, can_join_request, can_leave_request,
103 8e1a5af5 Georgios D. Tsoukalas
    get_related_project_id, get_by_chain_or_404,
104 8e1a5af5 Georgios D. Tsoukalas
    approve_application, deny_application,
105 8e1a5af5 Georgios D. Tsoukalas
    cancel_application, dismiss_application)
106 f3342849 Sofia Papagiannaki
from astakos.im.settings import (
107 f3342849 Sofia Papagiannaki
    COOKIE_DOMAIN, LOGOUT_NEXT,
108 f3342849 Sofia Papagiannaki
    LOGGING_LEVEL, PAGINATE_BY,
109 4161cb70 Giorgos Korfiatis
    PAGINATE_BY_ALL,
110 3f8570dc Kostas Papadimitriou
    ACTIVATION_REDIRECT_URL,
111 a9c7ff8a Sofia Papagiannaki
    MODERATION_ENABLED)
112 75380308 Kostas Papadimitriou
from astakos.im import presentation
113 48421603 Kostas Papadimitriou
from astakos.im import settings as astakos_settings
114 9d20fe23 Kostas Papadimitriou
from astakos.im import auth_providers as auth
115 b830f774 Giorgos Korfiatis
from snf_django.lib.db.transaction import commit_on_success_strict
116 39b2cb50 Giorgos Korfiatis
from astakos.im.ctx import ExceptionHandler
117 4e03ba30 Kostas Papadimitriou
from astakos.im import quotas
118 ae497612 Olga Brani
119 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
120 e015e9e6 Sofia Papagiannaki
121 9a06d96f Olga Brani
122 b2ffa772 Sofia Papagiannaki
def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
123 890b0eaf Sofia Papagiannaki
    """
124 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
125 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
126 890b0eaf Sofia Papagiannaki
    specified ``status``.
127 890b0eaf Sofia Papagiannaki
    """
128 64cd4730 Antony Chazapis
    if tab is None:
129 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
130 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
131 661c4479 Sofia Papagiannaki
    html = template_loader.render_to_string(
132 5ce3ce4f Sofia Papagiannaki
        template, kwargs, context_instance=context_instance)
133 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
134 c301698f Sofia Papagiannaki
    return response
135 64cd4730 Antony Chazapis
136 792c2f3b Olga Brani
def requires_auth_provider(provider_id, **perms):
137 792c2f3b Olga Brani
    """
138 792c2f3b Olga Brani
    """
139 792c2f3b Olga Brani
    def decorator(func, *args, **kwargs):
140 792c2f3b Olga Brani
        @wraps(func)
141 792c2f3b Olga Brani
        def wrapper(request, *args, **kwargs):
142 9d20fe23 Kostas Papadimitriou
            provider = auth.get_provider(provider_id)
143 792c2f3b Olga Brani
144 792c2f3b Olga Brani
            if not provider or not provider.is_active():
145 792c2f3b Olga Brani
                raise PermissionDenied
146 792c2f3b Olga Brani
147 9d20fe23 Kostas Papadimitriou
            for pkey, value in perms.iteritems():
148 9d20fe23 Kostas Papadimitriou
                attr = 'get_%s_policy' % pkey.lower()
149 9d20fe23 Kostas Papadimitriou
                if getattr(provider, attr) != value:
150 9d20fe23 Kostas Papadimitriou
                    #TODO: add session message
151 9d20fe23 Kostas Papadimitriou
                    return HttpResponseRedirect(reverse('login'))
152 792c2f3b Olga Brani
            return func(request, *args)
153 792c2f3b Olga Brani
        return wrapper
154 792c2f3b Olga Brani
    return decorator
155 792c2f3b Olga Brani
156 63ecdd20 Sofia Papagiannaki
157 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
158 63ecdd20 Sofia Papagiannaki
    """
159 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
160 7482228b Sofia Papagiannaki
    redirects to `logout`.
161 63ecdd20 Sofia Papagiannaki
    """
162 63ecdd20 Sofia Papagiannaki
    @wraps(func)
163 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
164 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
165 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
166 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
167 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
168 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
169 63ecdd20 Sofia Papagiannaki
    return wrapper
170 63ecdd20 Sofia Papagiannaki
171 5ce3ce4f Sofia Papagiannaki
172 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
173 270dd48d Sofia Papagiannaki
    """
174 badcb2a9 Kostas Papadimitriou
    Decorator checks whether the request.user is Anonymous and in that case
175 270dd48d Sofia Papagiannaki
    redirects to `logout`.
176 270dd48d Sofia Papagiannaki
    """
177 270dd48d Sofia Papagiannaki
    @wraps(func)
178 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
179 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
180 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
181 5ce3ce4f Sofia Papagiannaki
                                'show_form': ''})
182 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
183 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
184 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
185 270dd48d Sofia Papagiannaki
    return wrapper
186 270dd48d Sofia Papagiannaki
187 5ce3ce4f Sofia Papagiannaki
188 9d20fe23 Kostas Papadimitriou
def required_auth_methods_assigned(allow_access=False):
189 badcb2a9 Kostas Papadimitriou
    """
190 badcb2a9 Kostas Papadimitriou
    Decorator that checks whether the request.user has all required auth providers
191 badcb2a9 Kostas Papadimitriou
    assigned.
192 badcb2a9 Kostas Papadimitriou
    """
193 badcb2a9 Kostas Papadimitriou
194 badcb2a9 Kostas Papadimitriou
    def decorator(func):
195 badcb2a9 Kostas Papadimitriou
        @wraps(func)
196 badcb2a9 Kostas Papadimitriou
        def wrapper(request, *args, **kwargs):
197 badcb2a9 Kostas Papadimitriou
            if request.user.is_authenticated():
198 9d20fe23 Kostas Papadimitriou
                missing = request.user.missing_required_providers()
199 9d20fe23 Kostas Papadimitriou
                if missing:
200 9d20fe23 Kostas Papadimitriou
                    for provider in missing:
201 9d20fe23 Kostas Papadimitriou
                        messages.error(request,
202 9d20fe23 Kostas Papadimitriou
                                       provider.get_required_msg)
203 9d20fe23 Kostas Papadimitriou
                    if not allow_access:
204 9d20fe23 Kostas Papadimitriou
                        return HttpResponseRedirect(reverse('edit_profile'))
205 badcb2a9 Kostas Papadimitriou
            return func(request, *args, **kwargs)
206 badcb2a9 Kostas Papadimitriou
        return wrapper
207 badcb2a9 Kostas Papadimitriou
    return decorator
208 badcb2a9 Kostas Papadimitriou
209 badcb2a9 Kostas Papadimitriou
210 badcb2a9 Kostas Papadimitriou
def valid_astakos_user_required(func):
211 badcb2a9 Kostas Papadimitriou
    return signed_terms_required(required_auth_methods_assigned()(login_required(func)))
212 badcb2a9 Kostas Papadimitriou
213 badcb2a9 Kostas Papadimitriou
214 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
215 270dd48d Sofia Papagiannaki
@signed_terms_required
216 1f3b4b39 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context=None):
217 890b0eaf Sofia Papagiannaki
    """
218 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
219 176023aa Kostas Papadimitriou

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

359 890b0eaf Sofia Papagiannaki
    **Arguments**
360 176023aa Kostas Papadimitriou

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

365 890b0eaf Sofia Papagiannaki
    ``extra_context``
366 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
367 176023aa Kostas Papadimitriou

368 890b0eaf Sofia Papagiannaki
    **Template:**
369 176023aa Kostas Papadimitriou

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

372 92defad4 Sofia Papagiannaki
    **Settings:**
373 176023aa Kostas Papadimitriou

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

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

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

444 890b0eaf Sofia Papagiannaki
    The user activation will be delegated to the backend specified by the ``backend`` keyword argument
445 8f5a3a06 Sofia Papagiannaki
    if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend``
446 8f5a3a06 Sofia Papagiannaki
    if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not
447 8f5a3a06 Sofia Papagiannaki
    (see activation_backends);
448 5ce3ce4f Sofia Papagiannaki

449 b669d9c0 Sofia Papagiannaki
    Upon successful user creation, if ``next`` url parameter is present the user is redirected there
450 890b0eaf Sofia Papagiannaki
    otherwise renders the same page with a success message.
451 5ce3ce4f Sofia Papagiannaki

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

454 890b0eaf Sofia Papagiannaki
    **Arguments**
455 5ce3ce4f Sofia Papagiannaki

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

460 890b0eaf Sofia Papagiannaki
    ``extra_context``
461 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
462 176023aa Kostas Papadimitriou

463 43332a76 Kostas Papadimitriou
    ``on_success``
464 43332a76 Kostas Papadimitriou
        Resolvable view name to redirect on registration success.
465 43332a76 Kostas Papadimitriou

466 890b0eaf Sofia Papagiannaki
    **Template:**
467 5ce3ce4f Sofia Papagiannaki

468 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
469 890b0eaf Sofia Papagiannaki
    """
470 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
471 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
472 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
473 5ce3ce4f Sofia Papagiannaki
474 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
475 9d20fe23 Kostas Papadimitriou
    if not auth.get_provider(provider).get_create_policy:
476 279d6e51 Olga Brani
        raise PermissionDenied
477 279d6e51 Olga Brani
478 6c8a3f7c Sofia Papagiannaki
    id = get_query(request).get('id')
479 6c8a3f7c Sofia Papagiannaki
    try:
480 6c8a3f7c Sofia Papagiannaki
        instance = AstakosUser.objects.get(id=id) if id else None
481 6c8a3f7c Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
482 6c8a3f7c Sofia Papagiannaki
        instance = None
483 6c8a3f7c Sofia Papagiannaki
484 8ab484ea Kostas Papadimitriou
    third_party_token = request.REQUEST.get('third_party_token', None)
485 9d20fe23 Kostas Papadimitriou
    unverified = None
486 c630fee6 Kostas Papadimitriou
    if third_party_token:
487 c630fee6 Kostas Papadimitriou
        pending = get_object_or_404(PendingThirdPartyUser,
488 c630fee6 Kostas Papadimitriou
                                    token=third_party_token)
489 9d20fe23 Kostas Papadimitriou
490 c630fee6 Kostas Papadimitriou
        provider = pending.provider
491 c630fee6 Kostas Papadimitriou
        instance = pending.get_user_instance()
492 9d20fe23 Kostas Papadimitriou
        get_unverified = AstakosUserAuthProvider.objects.unverified
493 9d20fe23 Kostas Papadimitriou
        unverified = get_unverified(pending.provider,
494 9d20fe23 Kostas Papadimitriou
                                    identifier=pending.third_party_identifier)
495 9d20fe23 Kostas Papadimitriou
496 9d20fe23 Kostas Papadimitriou
        if unverified and request.method == 'GET':
497 9d20fe23 Kostas Papadimitriou
            messages.warning(request, unverified.get_pending_registration_msg)
498 9d20fe23 Kostas Papadimitriou
            if unverified.user.activation_sent:
499 9d20fe23 Kostas Papadimitriou
                messages.warning(request,
500 9d20fe23 Kostas Papadimitriou
                                 unverified.get_pending_resend_activation_msg)
501 9d20fe23 Kostas Papadimitriou
            else:
502 9d20fe23 Kostas Papadimitriou
                messages.warning(request,
503 9d20fe23 Kostas Papadimitriou
                                 unverified.get_pending_moderation_msg)
504 8ab484ea Kostas Papadimitriou
505 890b0eaf Sofia Papagiannaki
    try:
506 18ffbee1 Sofia Papagiannaki
        if not backend:
507 18ffbee1 Sofia Papagiannaki
            backend = get_backend(request)
508 6c8a3f7c Sofia Papagiannaki
        form = backend.get_signup_form(provider, instance)
509 0a569195 Sofia Papagiannaki
    except Exception, e:
510 4e30244e Sofia Papagiannaki
        form = SimpleBackend(request).get_signup_form(provider)
511 24406ae3 Sofia Papagiannaki
        messages.error(request, e)
512 9d20fe23 Kostas Papadimitriou
513 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
514 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
515 18ffbee1 Sofia Papagiannaki
            user = form.save(commit=False)
516 43332a76 Kostas Papadimitriou
517 43332a76 Kostas Papadimitriou
            # delete previously unverified accounts
518 43332a76 Kostas Papadimitriou
            if AstakosUser.objects.user_exists(user.email):
519 43332a76 Kostas Papadimitriou
                AstakosUser.objects.get_by_identifier(user.email).delete()
520 43332a76 Kostas Papadimitriou
521 8f5a3a06 Sofia Papagiannaki
            try:
522 9d20fe23 Kostas Papadimitriou
                form.store_user(user, request)
523 9d20fe23 Kostas Papadimitriou
524 8f5a3a06 Sofia Papagiannaki
                result = backend.handle_activation(user)
525 8f5a3a06 Sofia Papagiannaki
                status = messages.SUCCESS
526 18ffbee1 Sofia Papagiannaki
                message = result.message
527 792c2f3b Olga Brani
528 ca828a10 Sofia Papagiannaki
                if 'additional_email' in form.cleaned_data:
529 ca828a10 Sofia Papagiannaki
                    additional_email = form.cleaned_data['additional_email']
530 ca828a10 Sofia Papagiannaki
                    if additional_email != user.email:
531 ca828a10 Sofia Papagiannaki
                        user.additionalmail_set.create(email=additional_email)
532 5ce3ce4f Sofia Papagiannaki
                        msg = 'Additional email: %s saved for user %s.' % (
533 6c8a3f7c Sofia Papagiannaki
                            additional_email,
534 6c8a3f7c Sofia Papagiannaki
                            user.email
535 6c8a3f7c Sofia Papagiannaki
                        )
536 b669d9c0 Sofia Papagiannaki
                        logger._log(LOGGING_LEVEL, msg, [])
537 43332a76 Kostas Papadimitriou
538 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
539 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
540 40a0cd8b Sofia Papagiannaki
                    response = prepare_response(request, user, next=next)
541 c3f6cdf1 root
                    transaction.commit()
542 40a0cd8b Sofia Papagiannaki
                    return response
543 43332a76 Kostas Papadimitriou
544 792c2f3b Olga Brani
                transaction.commit()
545 43332a76 Kostas Papadimitriou
                messages.add_message(request, status, message)
546 43332a76 Kostas Papadimitriou
                return HttpResponseRedirect(reverse(on_success))
547 43332a76 Kostas Papadimitriou
548 18ffbee1 Sofia Papagiannaki
            except SendMailError, e:
549 18ffbee1 Sofia Papagiannaki
                status = messages.ERROR
550 18ffbee1 Sofia Papagiannaki
                message = e.message
551 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
552 10ed0073 Sofia Papagiannaki
                transaction.rollback()
553 18ffbee1 Sofia Papagiannaki
            except BaseException, e:
554 678b2236 Sofia Papagiannaki
                logger.exception(e)
555 ae497612 Olga Brani
                message = _(astakos_messages.GENERIC_ERROR)
556 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
557 0a569195 Sofia Papagiannaki
                logger.exception(e)
558 10ed0073 Sofia Papagiannaki
                transaction.rollback()
559 43332a76 Kostas Papadimitriou
560 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
561 5ce3ce4f Sofia Papagiannaki
                           signup_form=form,
562 8ab484ea Kostas Papadimitriou
                           third_party_token=third_party_token,
563 5ce3ce4f Sofia Papagiannaki
                           provider=provider,
564 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
565 64cd4730 Antony Chazapis
566 5ce3ce4f Sofia Papagiannaki
567 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
568 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
569 890b0eaf Sofia Papagiannaki
@login_required
570 270dd48d Sofia Papagiannaki
@signed_terms_required
571 aab4d540 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context=None):
572 890b0eaf Sofia Papagiannaki
    """
573 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
574 176023aa Kostas Papadimitriou

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

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

580 890b0eaf Sofia Papagiannaki
    **Arguments**
581 176023aa Kostas Papadimitriou

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

586 890b0eaf Sofia Papagiannaki
    ``extra_context``
587 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
588 176023aa Kostas Papadimitriou

589 890b0eaf Sofia Papagiannaki
    **Template:**
590 176023aa Kostas Papadimitriou

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

593 890b0eaf Sofia Papagiannaki
    **Settings:**
594 176023aa Kostas Papadimitriou

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

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