Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (55.7 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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