user.py 12.4 KB
Newer Older
Skia's avatar
Skia committed
1
2
# This file contains all the views that concern the user model
from django.shortcuts import render, redirect, get_object_or_404
Skia's avatar
Skia committed
3
from django.contrib.auth import logout as auth_logout, views
4
from django.utils.translation import ugettext as _
5
from django.core.urlresolvers import reverse
6
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist, ValidationError
Skia's avatar
Skia committed
7
from django.http import Http404
Skia's avatar
Skia committed
8
from django.views.generic.edit import UpdateView
9
from django.views.generic import ListView, DetailView, TemplateView
10
11
from django.forms.models import modelform_factory
from django.forms import CheckboxSelectMultiple
Skia's avatar
Skia committed
12
from django.template.response import TemplateResponse
Skia's avatar
Skia committed
13
from django.conf import settings
14
15

from datetime import timedelta
Skia's avatar
Skia committed
16
17
import logging

18
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin
Skia's avatar
Skia committed
19
from core.views.forms import RegisteringForm, UserPropForm, UserProfileForm, LoginForm
20
from core.models import User, SithFile
Skia's avatar
Skia committed
21

Skia's avatar
Skia committed
22
23
24
25
26
27
def login(request):
    """
    The login view

    Needs to be improve with correct handling of form exceptions
    """
Skia's avatar
Skia committed
28
    return views.login(request, template_name="core/login.jinja", authentication_form=LoginForm)
Skia's avatar
Skia committed
29
30
31
32
33
34
35
36
37
38
39

def logout(request):
    """
    The logout view
    """
    return views.logout_then_login(request)

def password_change(request):
    """
    Allows a user to change its password
    """
Skia's avatar
Skia committed
40
    return views.password_change(request, template_name="core/password_change.jinja", post_change_redirect=reverse("core:password_change_done"))
Skia's avatar
Skia committed
41
42
43
44
45

def password_change_done(request):
    """
    Allows a user to change its password
    """
Skia's avatar
Skia committed
46
    return views.password_change_done(request, template_name="core/password_change_done.jinja")
Skia's avatar
Skia committed
47

Skia's avatar
Skia committed
48
49
50
51
def password_root_change(request, user_id):
    """
    Allows a root user to change someone's password
    """
Skia's avatar
Skia committed
52
    if not request.user.is_root:
Skia's avatar
Skia committed
53
54
55
56
57
58
59
60
61
62
63
64
65
        raise PermissionDenied
    user = User.objects.filter(id=user_id).first()
    if not user:
        raise Http404("User not found")
    if request.method == "POST":
        form = views.SetPasswordForm(user=user, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect("core:password_change_done")
    else:
        form = views.SetPasswordForm(user=user)
    return TemplateResponse(request, "core/password_change.jinja", {'form': form, 'target': user})

Skia's avatar
Skia committed
66
def password_reset(request):
Skia's avatar
Skia committed
67
68
69
    """
    Allows someone to enter an email adresse for resetting password
    """
Skia's avatar
Skia committed
70
    return views.password_reset(request,
Skia's avatar
Skia committed
71
72
                                template_name="core/password_reset.jinja",
                                email_template_name="core/password_reset_email.jinja",
Skia's avatar
Skia committed
73
                                post_reset_redirect="core:password_reset_done",
Skia's avatar
Skia committed
74
                               )
Skia's avatar
Skia committed
75
76

def password_reset_done(request):
Skia's avatar
Skia committed
77
78
79
    """
    Confirm that the reset email has been sent
    """
Skia's avatar
Skia committed
80
    return views.password_reset_done(request, template_name="core/password_reset_done.jinja")
Skia's avatar
Skia committed
81

Skia's avatar
Skia committed
82
def password_reset_confirm(request, uidb64=None, token=None):
Skia's avatar
Skia committed
83
84
85
    """
    Provide a reset password formular
    """
Skia's avatar
Skia committed
86
87
    return views.password_reset_confirm(request, uidb64=uidb64, token=token,
                                        post_reset_redirect="core:password_reset_complete",
Skia's avatar
Skia committed
88
                                        template_name="core/password_reset_confirm.jinja",
Skia's avatar
Skia committed
89
90
91
                                       )

def password_reset_complete(request):
Skia's avatar
Skia committed
92
93
94
    """
    Confirm the password has sucessfully been reset
    """
Skia's avatar
Skia committed
95
    return views.password_reset_complete(request,
Skia's avatar
Skia committed
96
                                         template_name="core/password_reset_complete.jinja",
Skia's avatar
Skia committed
97
                                        )
Skia's avatar
Skia committed
98

Skia's avatar
Skia committed
99
def register(request):
Skia's avatar
Skia committed
100
    context = {}
Skia's avatar
Skia committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
    if request.method == 'POST':
        form = RegisteringForm(request.POST)
        if form.is_valid():
            logging.debug("Registering "+form.cleaned_data['first_name']+form.cleaned_data['last_name'])
            u = form.save()
            context['user_registered'] = u
            context['tests'] = 'TEST_REGISTER_USER_FORM_OK'
            form = RegisteringForm()
        else:
            context['error'] = 'Erreur'
            context['tests'] = 'TEST_REGISTER_USER_FORM_FAIL'
    else:
        form = RegisteringForm()
    context['form'] = form.as_p()
Skia's avatar
Skia committed
115
    return render(request, "core/register.jinja", context)
Skia's avatar
Skia committed
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
class UserTabsMixin(TabedViewMixin):
    def get_tabs_title(self):
        return self.object.get_display_name()

    def get_list_of_tabs(self):
        tab_list = []
        tab_list.append({
                    'url': reverse('core:user_profile', kwargs={'user_id': self.object.id}),
                    'slug': 'infos',
                    'name': _("Infos"),
                    })
        if self.request.user == self.object:
            tab_list.append({
                        'url': reverse('core:user_tools'),
                        'slug': 'tools',
                        'name': _("Tools"),
                        })
        tab_list.append({
                    'url': reverse('core:user_stats', kwargs={'user_id': self.object.id}),
                    'slug': 'stats',
                    'name': _("Stats"),
                    })
        if self.request.user.can_edit(self.object):
            tab_list.append({
                        'url': reverse('core:user_edit', kwargs={'user_id': self.object.id}),
                        'slug': 'edit',
                        'name': _("Edit"),
                        })
        if self.request.user.is_owner(self.object):
            tab_list.append({
                        'url': reverse('core:user_groups', kwargs={'user_id': self.object.id}),
                        'slug': 'groups',
                        'name': _("Groups"),
                        })
        try:
            if (self.object.customer and (self.object == self.request.user
                or self.request.user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name'])
                or self.request.user.is_root)):
                tab_list.append({
                            'url': reverse('core:user_account', kwargs={'user_id': self.object.id}),
                            'slug': 'account',
                            'name': _("Account")+" (%s €)" % self.object.customer.amount,
                            })
        except: pass
        return tab_list

class UserView(UserTabsMixin, CanViewMixin, DetailView):
Skia's avatar
Skia committed
164
165
166
    """
    Display a user's profile
    """
Skia's avatar
Skia committed
167
168
169
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
Skia's avatar
Skia committed
170
    template_name = "core/user_detail.jinja"
171
    current_tab = 'infos'
Skia's avatar
Skia committed
172

173
class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
174
175
176
177
178
179
180
    """
    Display a user's stats
    """
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
    template_name = "core/user_stats.jinja"
181
    current_tab = 'stats'
182
183
184

    def get_context_data(self, **kwargs):
        kwargs = super(UserStatsView, self).get_context_data(**kwargs)
Skia's avatar
Skia committed
185
186
187
188
189
190
191
192
        from counter.models import Counter
        foyer = Counter.objects.filter(name="Foyer").first()
        mde = Counter.objects.filter(name="MDE").first()
        gommette = Counter.objects.filter(name="La Gommette").first()
        kwargs['total_perm_time'] = sum([p.end-p.start for p in self.object.permanencies.all()], timedelta())
        kwargs['total_foyer_time'] = sum([p.end-p.start for p in self.object.permanencies.filter(counter=foyer)], timedelta())
        kwargs['total_mde_time'] = sum([p.end-p.start for p in self.object.permanencies.filter(counter=mde)], timedelta())
        kwargs['total_gommette_time'] = sum([p.end-p.start for p in self.object.permanencies.filter(counter=gommette)], timedelta())
193
194
        return kwargs

Skia's avatar
Skia committed
195
196
197
198
199
200
201
202
203
class UserMiniView(CanViewMixin, DetailView):
    """
    Display a user's profile
    """
    model = User
    pk_url_kwarg = "user_id"
    context_object_name = "profile"
    template_name = "core/user_mini.jinja"

Skia's avatar
Skia committed
204
205
206
207
208
class UserListView(ListView):
    """
    Displays the user list
    """
    model = User
Skia's avatar
Skia committed
209
    template_name = "core/user_list.jinja"
Skia's avatar
Skia committed
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
class UserUploadProfilePictView(CanEditMixin, DetailView):
    """
    Handle the upload of the profile picture taken with webcam in navigator
    """
    model = User
    pk_url_kwarg = "user_id"
    template_name = "core/user_edit.jinja"

    def post(self, request, *args, **kwargs):
        from core.utils import resize_image
        from io import BytesIO
        from PIL import Image
        self.object = self.get_object()
        if self.object.profile_pict:
            raise ValidationError(_("User already has a profile picture"))
        print(request.FILES['new_profile_pict'])
        f = request.FILES['new_profile_pict']
        parent = SithFile.objects.filter(parent=None, name="profiles").first()
        name = str(self.object.id) + "_profile.jpg" # Webcamejs uploads JPGs
        im = Image.open(BytesIO(f.read()))
        new_file = SithFile(parent=parent, name=name,
                file=resize_image(im, 400, f.content_type.split('/')[-1]),
                owner=self.object, is_folder=False, mime_type=f.content_type, size=f._size)
        new_file.file.name = name
        new_file.save()
        self.object.profile_pict = new_file
        self.object.save()
        return redirect("core:user_edit", user_id=self.object.id)

240
class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView):
Skia's avatar
Skia committed
241
242
243
244
245
    """
    Edit a user's profile
    """
    model = User
    pk_url_kwarg = "user_id"
Skia's avatar
Skia committed
246
    template_name = "core/user_edit.jinja"
247
    form_class = UserProfileForm
248
    current_tab = "edit"
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = self.get_form()
        if self.form.instance.profile_pict and not request.user.is_in_group(settings.SITH_MAIN_BOARD_GROUP):
            self.form.fields.pop('profile_pict', None)
        return self.render_to_response(self.get_context_data(form=self.form))

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.form = self.get_form()
        if self.form.instance.profile_pict and not request.user.is_in_group(settings.SITH_MAIN_BOARD_GROUP):
            self.form.fields.pop('profile_pict', None)
        files = request.FILES.items()
        self.form.process(files)
        if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid():
            return super(UserUpdateProfileView, self).form_valid(self.form)
        return self.form_invalid(self.form)

    def get_context_data(self, **kwargs):
        kwargs = super(UserUpdateProfileView, self).get_context_data(**kwargs)
        kwargs['profile'] = self.form.instance
        kwargs['form'] = self.form
        return kwargs
Skia's avatar
Skia committed
273

274
class UserUpdateGroupView(UserTabsMixin, CanEditPropMixin, UpdateView):
Skia's avatar
Skia committed
275
276
277
278
279
    """
    Edit a user's groups
    """
    model = User
    pk_url_kwarg = "user_id"
280
281
282
    template_name = "core/user_group.jinja"
    form_class = modelform_factory(User, fields=['groups'],
            widgets={'groups':CheckboxSelectMultiple})
Skia's avatar
Skia committed
283
    context_object_name = "profile"
284
    current_tab = "groups"
Skia's avatar
Skia committed
285

286
class UserToolsView(UserTabsMixin, TemplateView):
287
288
289
    """
    Displays the logged user's tools
    """
Skia's avatar
Skia committed
290
    template_name = "core/user_tools.jinja"
291
    current_tab = "tools"
Skia's avatar
Skia committed
292

293
    def get_context_data(self, **kwargs):
294
        self.object = self.request.user
295
296
297
        from launderette.models import Launderette
        kwargs = super(UserToolsView, self).get_context_data(**kwargs)
        kwargs['launderettes'] = Launderette.objects.all()
Skia's avatar
Skia committed
298
        kwargs['profile'] = self.request.user
299
        kwargs['object'] = self.request.user
300
301
        return kwargs

302
class UserAccountView(UserTabsMixin, DetailView):
Skia's avatar
Skia committed
303
304
305
306
307
308
    """
    Display a user's account
    """
    model = User
    pk_url_kwarg = "user_id"
    template_name = "core/user_account.jinja"
309
    current_tab = "account"
Skia's avatar
Skia committed
310
311
312
313
314

    def dispatch(self, request, *arg, **kwargs): # Manually validates the rights
        res = super(UserAccountView, self).dispatch(request, *arg, **kwargs)
        if (self.object == request.user
                or request.user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name'])
Skia's avatar
Skia committed
315
                or request.user.is_root):
Skia's avatar
Skia committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
            return res
        raise PermissionDenied

    def get_context_data(self, **kwargs):
        kwargs = super(UserAccountView, self).get_context_data(**kwargs)
        kwargs['profile'] = self.object
        try:
            kwargs['customer'] = self.object.customer
        except:
            pass
        # TODO: add list of month where account has activity
        return kwargs