Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 85c46d85

History | View | Annotate | Download (52.3 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 564a2292 Kostas Papadimitriou
from django.utils.safestring import mark_safe
61 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
62 e1a80257 Sofia Papagiannaki
from django.views.generic.create_update import (
63 4e748491 Sofia Papagiannaki
    apply_extra_context, lookup_object, delete_object, get_model_and_form_class)
64 f3342849 Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
65 661c4479 Sofia Papagiannaki
from django.core.xheaders import populate_xheaders
66 792c2f3b Olga Brani
from django.core.exceptions import ValidationError, PermissionDenied
67 c0b26605 Sofia Papagiannaki
from django.template.loader import render_to_string
68 9a06d96f Olga Brani
from django.views.decorators.http import require_http_methods
69 29b0ec5a Sofia Papagiannaki
from django.db.models import Q
70 bfe23b13 Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
71 96b44c04 Sofia Papagiannaki
from django.utils import simplejson as json
72 c0b26605 Sofia Papagiannaki
73 c630fee6 Kostas Papadimitriou
import astakos.im.messages as astakos_messages
74 c630fee6 Kostas Papadimitriou
75 29b0ec5a Sofia Papagiannaki
from astakos.im.activation_backends import get_backend, SimpleBackend
76 5550bcfb Kostas Papadimitriou
from astakos.im import tables
77 e1a80257 Sofia Papagiannaki
from astakos.im.models import (
78 73fbaec4 Sofia Papagiannaki
    AstakosUser, ApprovalTerms,
79 fcc1e93f Sofia Papagiannaki
    EmailChange, RESOURCE_SEPARATOR,
80 fcc1e93f Sofia Papagiannaki
    AstakosUserAuthProvider, PendingThirdPartyUser,
81 73fbaec4 Sofia Papagiannaki
    ProjectApplication, ProjectMembership, Project)
82 73fbaec4 Sofia Papagiannaki
from astakos.im.util import (
83 73fbaec4 Sofia Papagiannaki
    get_context, prepare_response, get_query, restrict_next)
84 e1a80257 Sofia Papagiannaki
from astakos.im.forms import (
85 f7400729 Kostas Papadimitriou
    LoginForm, InvitationForm,
86 e1a80257 Sofia Papagiannaki
    FeedbackForm, SignApprovalTermsForm,
87 e1a80257 Sofia Papagiannaki
    EmailChangeForm,
88 bfe23b13 Sofia Papagiannaki
    ProjectApplicationForm, ProjectSortForm,
89 73fbaec4 Sofia Papagiannaki
    AddProjectMembersForm, ProjectSearchForm,
90 73fbaec4 Sofia Papagiannaki
    ProjectMembersSortForm)
91 f7400729 Kostas Papadimitriou
from astakos.im.forms import ExtendedProfileForm as ProfileForm
92 f3342849 Sofia Papagiannaki
from astakos.im.functions import (
93 f3342849 Sofia Papagiannaki
    send_feedback, SendMailError,
94 f3342849 Sofia Papagiannaki
    logout as auth_logout,
95 f3342849 Sofia Papagiannaki
    activate as activate_func,
96 73fbaec4 Sofia Papagiannaki
    invite,
97 f3342849 Sofia Papagiannaki
    send_activation as send_activation_func,
98 73fbaec4 Sofia Papagiannaki
    SendNotificationError,
99 aad0e329 Giorgos Korfiatis
    accept_membership, reject_membership, remove_membership, cancel_membership,
100 d4660e00 Giorgos Korfiatis
    leave_project, join_project, enroll_member, can_join_request, can_leave_request,
101 a75dbd7b Giorgos Korfiatis
    cancel_application, get_related_project_id,
102 ff67242a Giorgos Korfiatis
    get_by_chain_or_404)
103 f3342849 Sofia Papagiannaki
from astakos.im.settings import (
104 f3342849 Sofia Papagiannaki
    COOKIE_DOMAIN, LOGOUT_NEXT,
105 f3342849 Sofia Papagiannaki
    LOGGING_LEVEL, PAGINATE_BY,
106 a9c7ff8a Sofia Papagiannaki
    RESOURCES_PRESENTATION_DATA, PAGINATE_BY_ALL,
107 3f8570dc Kostas Papadimitriou
    ACTIVATION_REDIRECT_URL,
108 a9c7ff8a Sofia Papagiannaki
    MODERATION_ENABLED)
109 1ebea3d3 Kostas Papadimitriou
from astakos.im.api import get_services_dict
110 48421603 Kostas Papadimitriou
from astakos.im import settings as astakos_settings
111 820b18e0 Sofia Papagiannaki
from astakos.im.api.callpoint import AstakosCallpoint
112 792c2f3b Olga Brani
from astakos.im import auth_providers
113 8cf9b2dd Giorgos Korfiatis
from astakos.im.project_xctx import project_transaction_context
114 ae497612 Olga Brani
115 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
116 e015e9e6 Sofia Papagiannaki
117 820b18e0 Sofia Papagiannaki
callpoint = AstakosCallpoint()
118 9a06d96f Olga Brani
119 b2ffa772 Sofia Papagiannaki
def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
120 890b0eaf Sofia Papagiannaki
    """
121 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
122 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
123 890b0eaf Sofia Papagiannaki
    specified ``status``.
124 890b0eaf Sofia Papagiannaki
    """
125 64cd4730 Antony Chazapis
    if tab is None:
126 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
127 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
128 661c4479 Sofia Papagiannaki
    html = template_loader.render_to_string(
129 5ce3ce4f Sofia Papagiannaki
        template, kwargs, context_instance=context_instance)
130 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
131 c301698f Sofia Papagiannaki
    return response
132 64cd4730 Antony Chazapis
133 792c2f3b Olga Brani
def requires_auth_provider(provider_id, **perms):
134 792c2f3b Olga Brani
    """
135 792c2f3b Olga Brani
    """
136 792c2f3b Olga Brani
    def decorator(func, *args, **kwargs):
137 792c2f3b Olga Brani
        @wraps(func)
138 792c2f3b Olga Brani
        def wrapper(request, *args, **kwargs):
139 792c2f3b Olga Brani
            provider = auth_providers.get_provider(provider_id)
140 792c2f3b Olga Brani
141 792c2f3b Olga Brani
            if not provider or not provider.is_active():
142 792c2f3b Olga Brani
                raise PermissionDenied
143 792c2f3b Olga Brani
144 792c2f3b Olga Brani
            if provider:
145 792c2f3b Olga Brani
                for pkey, value in perms.iteritems():
146 792c2f3b Olga Brani
                    attr = 'is_available_for_%s' % pkey.lower()
147 792c2f3b Olga Brani
                    if getattr(provider, attr)() != value:
148 279d6e51 Olga Brani
                        #TODO: add session message
149 c630fee6 Kostas Papadimitriou
                        return HttpResponseRedirect(reverse('login'))
150 792c2f3b Olga Brani
            return func(request, *args)
151 792c2f3b Olga Brani
        return wrapper
152 792c2f3b Olga Brani
    return decorator
153 792c2f3b Olga Brani
154 63ecdd20 Sofia Papagiannaki
155 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
156 63ecdd20 Sofia Papagiannaki
    """
157 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
158 7482228b Sofia Papagiannaki
    redirects to `logout`.
159 63ecdd20 Sofia Papagiannaki
    """
160 63ecdd20 Sofia Papagiannaki
    @wraps(func)
161 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
162 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
163 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
164 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
165 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
166 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
167 63ecdd20 Sofia Papagiannaki
    return wrapper
168 63ecdd20 Sofia Papagiannaki
169 5ce3ce4f Sofia Papagiannaki
170 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
171 270dd48d Sofia Papagiannaki
    """
172 badcb2a9 Kostas Papadimitriou
    Decorator checks whether the request.user is Anonymous and in that case
173 270dd48d Sofia Papagiannaki
    redirects to `logout`.
174 270dd48d Sofia Papagiannaki
    """
175 270dd48d Sofia Papagiannaki
    @wraps(func)
176 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
177 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
178 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
179 5ce3ce4f Sofia Papagiannaki
                                'show_form': ''})
180 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
181 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
182 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
183 270dd48d Sofia Papagiannaki
    return wrapper
184 270dd48d Sofia Papagiannaki
185 5ce3ce4f Sofia Papagiannaki
186 badcb2a9 Kostas Papadimitriou
def required_auth_methods_assigned(only_warn=False):
187 badcb2a9 Kostas Papadimitriou
    """
188 badcb2a9 Kostas Papadimitriou
    Decorator that checks whether the request.user has all required auth providers
189 badcb2a9 Kostas Papadimitriou
    assigned.
190 badcb2a9 Kostas Papadimitriou
    """
191 badcb2a9 Kostas Papadimitriou
    required_providers = auth_providers.REQUIRED_PROVIDERS.keys()
192 badcb2a9 Kostas Papadimitriou
193 badcb2a9 Kostas Papadimitriou
    def decorator(func):
194 badcb2a9 Kostas Papadimitriou
        if not required_providers:
195 badcb2a9 Kostas Papadimitriou
            return func
196 badcb2a9 Kostas Papadimitriou
197 badcb2a9 Kostas Papadimitriou
        @wraps(func)
198 badcb2a9 Kostas Papadimitriou
        def wrapper(request, *args, **kwargs):
199 badcb2a9 Kostas Papadimitriou
            if request.user.is_authenticated():
200 badcb2a9 Kostas Papadimitriou
                for required in required_providers:
201 badcb2a9 Kostas Papadimitriou
                    if not request.user.has_auth_provider(required):
202 badcb2a9 Kostas Papadimitriou
                        provider = auth_providers.get_provider(required)
203 badcb2a9 Kostas Papadimitriou
                        if only_warn:
204 badcb2a9 Kostas Papadimitriou
                            messages.error(request,
205 badcb2a9 Kostas Papadimitriou
                                           _(astakos_messages.AUTH_PROVIDER_REQUIRED  % {
206 badcb2a9 Kostas Papadimitriou
                                               'provider': provider.get_title_display}))
207 badcb2a9 Kostas Papadimitriou
                        else:
208 badcb2a9 Kostas Papadimitriou
                            return HttpResponseRedirect(reverse('edit_profile'))
209 badcb2a9 Kostas Papadimitriou
            return func(request, *args, **kwargs)
210 badcb2a9 Kostas Papadimitriou
        return wrapper
211 badcb2a9 Kostas Papadimitriou
    return decorator
212 badcb2a9 Kostas Papadimitriou
213 badcb2a9 Kostas Papadimitriou
214 badcb2a9 Kostas Papadimitriou
def valid_astakos_user_required(func):
215 badcb2a9 Kostas Papadimitriou
    return signed_terms_required(required_auth_methods_assigned()(login_required(func)))
216 badcb2a9 Kostas Papadimitriou
217 badcb2a9 Kostas Papadimitriou
218 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
219 270dd48d Sofia Papagiannaki
@signed_terms_required
220 1f3b4b39 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context=None):
221 890b0eaf Sofia Papagiannaki
    """
222 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
223 176023aa Kostas Papadimitriou

224 890b0eaf Sofia Papagiannaki
    **Arguments**
225 176023aa Kostas Papadimitriou

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

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

234 890b0eaf Sofia Papagiannaki
    ``extra_context``
235 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
236 176023aa Kostas Papadimitriou

237 890b0eaf Sofia Papagiannaki
    **Template:**
238 176023aa Kostas Papadimitriou

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

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

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

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

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

287 890b0eaf Sofia Papagiannaki
    **Arguments**
288 176023aa Kostas Papadimitriou

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

293 890b0eaf Sofia Papagiannaki
    ``extra_context``
294 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
295 176023aa Kostas Papadimitriou

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

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

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

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

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

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

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

363 890b0eaf Sofia Papagiannaki
    **Arguments**
364 176023aa Kostas Papadimitriou

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

369 890b0eaf Sofia Papagiannaki
    ``extra_context``
370 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
371 176023aa Kostas Papadimitriou

372 890b0eaf Sofia Papagiannaki
    **Template:**
373 176023aa Kostas Papadimitriou

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

376 92defad4 Sofia Papagiannaki
    **Settings:**
377 176023aa Kostas Papadimitriou

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

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

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

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

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

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

456 890b0eaf Sofia Papagiannaki
    **Arguments**
457 5ce3ce4f Sofia Papagiannaki

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

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

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

468 890b0eaf Sofia Papagiannaki
    **Template:**
469 5ce3ce4f Sofia Papagiannaki

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

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

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

568 890b0eaf Sofia Papagiannaki
    **Arguments**
569 176023aa Kostas Papadimitriou

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

574 890b0eaf Sofia Papagiannaki
    ``extra_context``
575 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
576 176023aa Kostas Papadimitriou

577 890b0eaf Sofia Papagiannaki
    **Template:**
578 176023aa Kostas Papadimitriou

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

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

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

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