Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 022cc8e2

History | View | Annotate | Download (55.1 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

572 890b0eaf Sofia Papagiannaki
    **Arguments**
573 176023aa Kostas Papadimitriou

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

578 890b0eaf Sofia Papagiannaki
    ``extra_context``
579 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
580 176023aa Kostas Papadimitriou

581 890b0eaf Sofia Papagiannaki
    **Template:**
582 176023aa Kostas Papadimitriou

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

585 890b0eaf Sofia Papagiannaki
    **Settings:**
586 176023aa Kostas Papadimitriou

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

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