# ~*~ coding: utf-8 ~*~ from __future__ import unicode_literals import logging from django.conf import settings from django.contrib.auth import login as auth_login, logout as auth_logout from django.contrib.messages.views import SuccessMessageMixin from django.db.models import Q from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, reverse, redirect from django.utils.decorators import method_decorator from django.utils.translation import ugettext as _ from django.urls import reverse_lazy from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters from django.views.generic.base import TemplateView from django.views.generic.list import ListView from django.views.generic.edit import CreateView, DeleteView, UpdateView, FormView from django.views.generic.detail import DetailView from common.utils import get_object_or_none from .models import User, UserGroup from .forms import UserCreateForm, UserUpdateForm, UserGroupForm, UserLoginForm from .utils import AdminUserRequiredMixin, user_add_success_next, send_reset_password_mail logger = logging.getLogger('jumpserver.users.views') @method_decorator(sensitive_post_parameters(), name='dispatch') @method_decorator(csrf_protect, name='dispatch') @method_decorator(never_cache, name='dispatch') class UserLoginView(FormView): template_name = 'users/login.html' form_class = UserLoginForm redirect_field_name = 'next' def get(self, request, *args, **kwargs): if request.user.is_staff: return redirect(request.POST.get(self.redirect_field_name, reverse('index'))) return self.render_to_response(self.get_context_data(**kwargs)) def form_valid(self, form): auth_login(self.request, form.get_user()) return redirect(self.request.POST.get(self.redirect_field_name, reverse('index'))) @method_decorator(never_cache, name='dispatch') class UserLogoutView(TemplateView): template_name = 'common/flash_message_standalone.html' def get(self, request, *args, **kwargs): auth_logout(request) return super(UserLogoutView, self).get(request) def get_context_data(self, **kwargs): context = { 'title': _('Logout success'), 'messages': _('Logout success, return login page'), 'redirect_url': reverse('users:login'), 'auto_redirect': True, } kwargs.update(context) return super(UserLogoutView, self).get_context_data(**kwargs) class UserListView(AdminUserRequiredMixin, ListView): model = User paginate_by = settings.CONFIG.DISPLAY_PER_PAGE context_object_name = 'user_list' template_name = 'users/user_list.html' ordering = '-date_joined' def get_queryset(self): self.queryset = super(UserListView, self).get_queryset() self.keyword = keyword = self.request.GET.get('keyword', '') self.sort = sort = self.request.GET.get('sort') if keyword: self.queryset = self.queryset.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)) if sort: self.queryset = self.queryset.order_by(sort) return self.queryset def get_context_data(self, **kwargs): context = super(UserListView, self).get_context_data(**kwargs) context.update({'app': _('Users'), 'action': _('User list'), 'keyword': self.keyword}) return context class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): model = User form_class = UserCreateForm template_name = 'users/user_create.html' success_url = reverse_lazy('users:user-list') success_message = _('Create user %s success.') def get_context_data(self, **kwargs): context = super(UserCreateView, self).get_context_data(**kwargs) context.update({'app': _('Users'), 'action': _('Create user')}) return context def form_valid(self, form): user = form.save(commit=False) user.created_by = self.request.user.username or 'System' user.save() user_add_success_next(user) return super(UserCreateView, self).form_valid(form) def get_success_message(self, cleaned_data): return self.success_message % ( reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk}), self.object.name, ) class UserUpdateView(AdminUserRequiredMixin, UpdateView): model = User form_class = UserUpdateForm template_name = 'users/user_update.html' context_object_name = 'user' success_url = reverse_lazy('users:user-list') def form_valid(self, form): username = self.object.username user = form.save(commit=False) user.username = username user.save() password = self.request.POST.get('password', '') if password: user.set_password(password) return super(UserUpdateView, self).form_valid(form) def form_invalid(self, form): print(form.errors) return super(UserUpdateView, self).form_invalid(form) def get_context_data(self, **kwargs): context = super(UserUpdateView, self).get_context_data(**kwargs) context.update({'app': _('Users'), 'action': _('Update user')}) return context class UserDeleteView(AdminUserRequiredMixin, DeleteView): model = User success_url = reverse_lazy('users:user-list') template_name = 'users/user_delete_confirm.html' class UserDetailView(AdminUserRequiredMixin, DetailView): model = User template_name = 'users/user_detail.html' context_object_name = "user" def get_context_data(self, **kwargs): groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()] context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups} kwargs.update(context) return super(UserDetailView, self).get_context_data(**kwargs) class UserGroupListView(AdminUserRequiredMixin, ListView): model = UserGroup paginate_by = settings.CONFIG.DISPLAY_PER_PAGE context_object_name = 'user_group_list' template_name = 'users/user_group_list.html' ordering = '-date_added' def get_queryset(self): self.queryset = super(UserGroupListView, self).get_queryset() self.keyword = keyword = self.request.GET.get('keyword', '') self.sort = sort = self.request.GET.get('sort') if keyword: self.queryset = self.queryset.filter(name__icontains=keyword) if sort: self.queryset = self.queryset.order_by(sort) return self.queryset def get_context_data(self, **kwargs): context = super(UserGroupListView, self).get_context_data(**kwargs) context.update({'app': _('Users'), 'action': _('User group list'), 'keyword': self.keyword}) return context class UserGroupCreateView(AdminUserRequiredMixin, CreateView): model = UserGroup form_class = UserGroupForm template_name = 'users/user_group_create.html' success_url = reverse_lazy('users:user-group-list') def get_context_data(self, **kwargs): context = super(UserGroupCreateView, self).get_context_data(**kwargs) users = User.objects.all() context.update({'app': _('Users'), 'action': _('Create user group'), 'users': users}) return context def form_valid(self, form): user_group = form.save() users_id_list = self.request.POST.getlist('users', []) users = [get_object_or_404(User, id=user_id) for user_id in users_id_list] user_group.created_by = self.request.user.username or 'Admin' user_group.users.add(*tuple(users)) user_group.save() return super(UserGroupCreateView, self).form_valid(form) class UserGroupUpdateView(UpdateView): pass class UserGroupDetailView(DetailView): pass class UserGroupDeleteView(DeleteView): pass class UserForgotPasswordView(TemplateView): template_name = 'users/forgot_password.html' def post(self, request, *args, **kwargs): email = request.POST.get('email') user = get_object_or_none(User, email=email) if not user: return self.get(request, errors=_('Email address invalid, input again')) else: send_reset_password_mail(user) return HttpResponseRedirect(reverse('users:forgot-password-sendmail-success')) class UserForgotPasswordSendmailSuccessView(TemplateView): template_name = 'common/flash_message_standalone.html' def get_context_data(self, **kwargs): context = { 'title': _('Send reset password message'), 'messages': _('Send reset password mail success, login your mail box and follow it '), 'redirect_url': reverse('users:login'), } kwargs.update(context) return super(UserForgotPasswordSendmailSuccessView, self).get_context_data(**kwargs) class UserResetPasswordSuccessView(TemplateView): template_name = 'common/flash_message_standalone.html' def get_context_data(self, **kwargs): context = { 'title': _('Reset password success'), 'messages': _('Reset password success, return to login page'), 'redirect_url': reverse('users:login'), 'auto_redirect': True, } kwargs.update(context) return super(UserResetPasswordSuccessView, self).get_context_data(**kwargs) class UserResetPasswordView(TemplateView): template_name = 'users/reset_password.html' def get(self, request, *args, **kwargs): token = request.GET.get('token') user = User.validate_reset_token(token) if not user: kwargs.update({'errors': _('Token invalid or expired')}) return super(UserResetPasswordView, self).get(request, *args, **kwargs) def post(self, request, *args, **kwargs): password = request.POST.get('password') password_confirm = request.POST.get('password-confirm') token = request.GET.get('token') if password != password_confirm: return self.get(request, errors=_('Password not same')) user = User.validate_reset_token(token) if not user: return self.get(request, errors=_('Token invalid or expired')) user.reset_password(password) return HttpResponseRedirect(reverse('users:reset-password-success'))