Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ a3c6203c

History | View | Annotate | Download (55.6 kB)

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

228 890b0eaf Sofia Papagiannaki
    **Arguments**
229 176023aa Kostas Papadimitriou

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

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

238 890b0eaf Sofia Papagiannaki
    ``extra_context``
239 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
240 176023aa Kostas Papadimitriou

241 890b0eaf Sofia Papagiannaki
    **Template:**
242 176023aa Kostas Papadimitriou

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

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

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

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

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

291 890b0eaf Sofia Papagiannaki
    **Arguments**
292 176023aa Kostas Papadimitriou

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

297 890b0eaf Sofia Papagiannaki
    ``extra_context``
298 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
299 176023aa Kostas Papadimitriou

300 890b0eaf Sofia Papagiannaki
    **Template:**
301 176023aa Kostas Papadimitriou

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

304 890b0eaf Sofia Papagiannaki
    **Settings:**
305 176023aa Kostas Papadimitriou

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

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

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

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

367 890b0eaf Sofia Papagiannaki
    **Arguments**
368 176023aa Kostas Papadimitriou

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

373 890b0eaf Sofia Papagiannaki
    ``extra_context``
374 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
375 176023aa Kostas Papadimitriou

376 890b0eaf Sofia Papagiannaki
    **Template:**
377 176023aa Kostas Papadimitriou

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

380 92defad4 Sofia Papagiannaki
    **Settings:**
381 176023aa Kostas Papadimitriou

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

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

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

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

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

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

460 890b0eaf Sofia Papagiannaki
    **Arguments**
461 5ce3ce4f Sofia Papagiannaki

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

466 890b0eaf Sofia Papagiannaki
    ``extra_context``
467 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
468 176023aa Kostas Papadimitriou

469 43332a76 Kostas Papadimitriou
    ``on_success``
470 43332a76 Kostas Papadimitriou
        Resolvable view name to redirect on registration success.
471 43332a76 Kostas Papadimitriou

472 890b0eaf Sofia Papagiannaki
    **Template:**
473 5ce3ce4f Sofia Papagiannaki

474 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
475 890b0eaf Sofia Papagiannaki
    """
476 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
477 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
478 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
479 5ce3ce4f Sofia Papagiannaki
480 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
481 279d6e51 Olga Brani
    if not auth_providers.get_provider(provider).is_available_for_create():
482 279d6e51 Olga Brani
        raise PermissionDenied
483 279d6e51 Olga Brani
484 6c8a3f7c Sofia Papagiannaki
    id = get_query(request).get('id')
485 6c8a3f7c Sofia Papagiannaki
    try:
486 6c8a3f7c Sofia Papagiannaki
        instance = AstakosUser.objects.get(id=id) if id else None
487 6c8a3f7c Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
488 6c8a3f7c Sofia Papagiannaki
        instance = None
489 6c8a3f7c Sofia Papagiannaki
490 606dea8d Kostas Papadimitriou
    pending_user = None
491 8ab484ea Kostas Papadimitriou
    third_party_token = request.REQUEST.get('third_party_token', None)
492 c630fee6 Kostas Papadimitriou
    if third_party_token:
493 c630fee6 Kostas Papadimitriou
        pending = get_object_or_404(PendingThirdPartyUser,
494 c630fee6 Kostas Papadimitriou
                                    token=third_party_token)
495 c630fee6 Kostas Papadimitriou
        provider = pending.provider
496 c630fee6 Kostas Papadimitriou
        instance = pending.get_user_instance()
497 606dea8d Kostas Papadimitriou
        if pending.existing_user().count() > 0:
498 606dea8d Kostas Papadimitriou
            pending_user = pending.existing_user().get()
499 606dea8d Kostas Papadimitriou
            if request.method == "GET":
500 606dea8d Kostas Papadimitriou
                messages.warning(request, pending_user.get_inactive_message())
501 606dea8d Kostas Papadimitriou
502 606dea8d Kostas Papadimitriou
503 606dea8d Kostas Papadimitriou
    extra_context['pending_user_exists'] = pending_user
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 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
513 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
514 18ffbee1 Sofia Papagiannaki
            user = form.save(commit=False)
515 43332a76 Kostas Papadimitriou
516 43332a76 Kostas Papadimitriou
            # delete previously unverified accounts
517 43332a76 Kostas Papadimitriou
            if AstakosUser.objects.user_exists(user.email):
518 43332a76 Kostas Papadimitriou
                AstakosUser.objects.get_by_identifier(user.email).delete()
519 43332a76 Kostas Papadimitriou
520 8f5a3a06 Sofia Papagiannaki
            try:
521 8f5a3a06 Sofia Papagiannaki
                result = backend.handle_activation(user)
522 8f5a3a06 Sofia Papagiannaki
                status = messages.SUCCESS
523 18ffbee1 Sofia Papagiannaki
                message = result.message
524 792c2f3b Olga Brani
525 792c2f3b Olga Brani
                form.store_user(user, request)
526 792c2f3b Olga Brani
527 ca828a10 Sofia Papagiannaki
                if 'additional_email' in form.cleaned_data:
528 ca828a10 Sofia Papagiannaki
                    additional_email = form.cleaned_data['additional_email']
529 ca828a10 Sofia Papagiannaki
                    if additional_email != user.email:
530 ca828a10 Sofia Papagiannaki
                        user.additionalmail_set.create(email=additional_email)
531 5ce3ce4f Sofia Papagiannaki
                        msg = 'Additional email: %s saved for user %s.' % (
532 6c8a3f7c Sofia Papagiannaki
                            additional_email,
533 6c8a3f7c Sofia Papagiannaki
                            user.email
534 6c8a3f7c Sofia Papagiannaki
                        )
535 b669d9c0 Sofia Papagiannaki
                        logger._log(LOGGING_LEVEL, msg, [])
536 43332a76 Kostas Papadimitriou
537 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
538 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
539 40a0cd8b Sofia Papagiannaki
                    response = prepare_response(request, user, next=next)
540 c3f6cdf1 root
                    transaction.commit()
541 40a0cd8b Sofia Papagiannaki
                    return response
542 43332a76 Kostas Papadimitriou
543 792c2f3b Olga Brani
                transaction.commit()
544 43332a76 Kostas Papadimitriou
                messages.add_message(request, status, message)
545 43332a76 Kostas Papadimitriou
                return HttpResponseRedirect(reverse(on_success))
546 43332a76 Kostas Papadimitriou
547 18ffbee1 Sofia Papagiannaki
            except SendMailError, e:
548 c44955a6 Sofia Papagiannaki
                logger.exception(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 badcb2a9 Kostas Papadimitriou
@required_auth_methods_assigned(only_warn=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 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
612 8f5a3a06 Sofia Papagiannaki
            else:
613 ae497612 Olga Brani
                message = _(astakos_messages.FEEDBACK_SENT)
614 aab4d540 Sofia Papagiannaki
                messages.success(request, message)
615 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
616 5ce3ce4f Sofia Papagiannaki
                           feedback_form=form,
617 5ce3ce4f Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
618 5ce3ce4f Sofia Papagiannaki
619 15efc749 Sofia Papagiannaki
620 217994f8 Sofia Papagiannaki
@require_http_methods(["GET"])
621 8e45d6fd Sofia Papagiannaki
@signed_terms_required
622 aab4d540 Sofia Papagiannaki
def logout(request, template='registration/logged_out.html', extra_context=None):
623 63ecdd20 Sofia Papagiannaki
    """
624 b2ffa772 Sofia Papagiannaki
    Wraps `django.contrib.auth.logout`.
625 63ecdd20 Sofia Papagiannaki
    """
626 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
627 7482228b Sofia Papagiannaki
    response = HttpResponse()
628 8e45d6fd Sofia Papagiannaki
    if request.user.is_authenticated():
629 8e45d6fd Sofia Papagiannaki
        email = request.user.email
630 8e45d6fd Sofia Papagiannaki
        auth_logout(request)
631 c630fee6 Kostas Papadimitriou
    else:
632 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
633 c630fee6 Kostas Papadimitriou
        response.status_code = 301
634 c630fee6 Kostas Papadimitriou
        return response
635 c630fee6 Kostas Papadimitriou
636 217994f8 Sofia Papagiannaki
    next = restrict_next(
637 217994f8 Sofia Papagiannaki
        request.GET.get('next'),
638 217994f8 Sofia Papagiannaki
        domain=COOKIE_DOMAIN
639 217994f8 Sofia Papagiannaki
    )
640 c630fee6 Kostas Papadimitriou
641 63ecdd20 Sofia Papagiannaki
    if next:
642 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
643 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
644 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
645 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
646 0d02a287 Sofia Papagiannaki
        response.status_code = 301
647 b2ffa772 Sofia Papagiannaki
    else:
648 564a2292 Kostas Papadimitriou
        message = _(astakos_messages.LOGOUT_SUCCESS)
649 564a2292 Kostas Papadimitriou
        last_provider = request.COOKIES.get('astakos_last_login_method', None)
650 564a2292 Kostas Papadimitriou
        if last_provider:
651 564a2292 Kostas Papadimitriou
            provider = auth_providers.get_provider(last_provider)
652 564a2292 Kostas Papadimitriou
            extra_message = provider.get_logout_message_display
653 564a2292 Kostas Papadimitriou
            if extra_message:
654 564a2292 Kostas Papadimitriou
                message += '<br />' + extra_message
655 d21d422a Kostas Papadimitriou
        messages.success(request, message)
656 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
657 c630fee6 Kostas Papadimitriou
        response.status_code = 301
658 49df775e Sofia Papagiannaki
    return response
659 2126d85d Sofia Papagiannaki
660 5ce3ce4f Sofia Papagiannaki
661 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
662 683cf244 Sofia Papagiannaki
@transaction.commit_manually
663 3bb604eb Sofia Papagiannaki
def activate(request, greeting_email_template_name='im/welcome_email.txt',
664 3bb604eb Sofia Papagiannaki
             helpdesk_email_template_name='im/helpdesk_notification.txt'):
665 2126d85d Sofia Papagiannaki
    """
666 683cf244 Sofia Papagiannaki
    Activates the user identified by the ``auth`` request parameter, sends a welcome email
667 683cf244 Sofia Papagiannaki
    and renews the user token.
668 176023aa Kostas Papadimitriou

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