views.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. from django.contrib import messages
  2. from django.contrib.auth import login as auth_login, logout as auth_logout, update_session_auth_hash
  3. from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
  4. from django.http import HttpResponseForbidden, HttpResponseRedirect
  5. from django.shortcuts import get_object_or_404, redirect, render
  6. from django.urls import reverse
  7. from django.utils.decorators import method_decorator
  8. from django.utils.http import is_safe_url
  9. from django.views.decorators.debug import sensitive_post_parameters
  10. from django.views.generic import View
  11. from secrets.forms import UserKeyForm
  12. from secrets.models import SessionKey, UserKey
  13. from utilities.forms import ConfirmationForm
  14. from .forms import LoginForm, PasswordChangeForm, TokenForm
  15. from .models import Token
  16. #
  17. # Login/logout
  18. #
  19. class LoginView(View):
  20. template_name = 'login.html'
  21. @method_decorator(sensitive_post_parameters('password'))
  22. def dispatch(self, *args, **kwargs):
  23. return super().dispatch(*args, **kwargs)
  24. def get(self, request):
  25. form = LoginForm(request)
  26. return render(request, self.template_name, {
  27. 'form': form,
  28. })
  29. def post(self, request):
  30. form = LoginForm(request, data=request.POST)
  31. if form.is_valid():
  32. # Determine where to direct user after successful login
  33. redirect_to = request.POST.get('next', '')
  34. if not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()):
  35. redirect_to = reverse('home')
  36. # Authenticate user
  37. auth_login(request, form.get_user())
  38. messages.info(request, "Logged in as {}.".format(request.user))
  39. return HttpResponseRedirect(redirect_to)
  40. return render(request, self.template_name, {
  41. 'form': form,
  42. })
  43. class LogoutView(View):
  44. def get(self, request):
  45. # Log out the user
  46. auth_logout(request)
  47. messages.info(request, "You have logged out.")
  48. # Delete session key cookie (if set) upon logout
  49. response = HttpResponseRedirect(reverse('home'))
  50. response.delete_cookie('session_key')
  51. return response
  52. #
  53. # User profiles
  54. #
  55. class ProfileView(LoginRequiredMixin, View):
  56. template_name = 'users/profile.html'
  57. def get(self, request):
  58. return render(request, self.template_name, {
  59. 'active_tab': 'profile',
  60. })
  61. class ChangePasswordView(LoginRequiredMixin, View):
  62. template_name = 'users/change_password.html'
  63. def get(self, request):
  64. form = PasswordChangeForm(user=request.user)
  65. return render(request, self.template_name, {
  66. 'form': form,
  67. 'active_tab': 'change_password',
  68. })
  69. def post(self, request):
  70. form = PasswordChangeForm(user=request.user, data=request.POST)
  71. if form.is_valid():
  72. form.save()
  73. update_session_auth_hash(request, form.user)
  74. messages.success(request, "Your password has been changed successfully.")
  75. return redirect('user:profile')
  76. return render(request, self.template_name, {
  77. 'form': form,
  78. 'active_tab': 'change_password',
  79. })
  80. class UserKeyView(LoginRequiredMixin, View):
  81. template_name = 'users/userkey.html'
  82. def get(self, request):
  83. try:
  84. userkey = UserKey.objects.get(user=request.user)
  85. except UserKey.DoesNotExist:
  86. userkey = None
  87. return render(request, self.template_name, {
  88. 'userkey': userkey,
  89. 'active_tab': 'userkey',
  90. })
  91. class UserKeyEditView(LoginRequiredMixin, View):
  92. template_name = 'users/userkey_edit.html'
  93. def dispatch(self, request, *args, **kwargs):
  94. try:
  95. self.userkey = UserKey.objects.get(user=request.user)
  96. except UserKey.DoesNotExist:
  97. self.userkey = UserKey(user=request.user)
  98. return super().dispatch(request, *args, **kwargs)
  99. def get(self, request):
  100. form = UserKeyForm(instance=self.userkey)
  101. return render(request, self.template_name, {
  102. 'userkey': self.userkey,
  103. 'form': form,
  104. 'active_tab': 'userkey',
  105. })
  106. def post(self, request):
  107. form = UserKeyForm(data=request.POST, instance=self.userkey)
  108. if form.is_valid():
  109. uk = form.save(commit=False)
  110. uk.user = request.user
  111. uk.save()
  112. messages.success(request, "Your user key has been saved.")
  113. return redirect('user:userkey')
  114. return render(request, self.template_name, {
  115. 'userkey': self.userkey,
  116. 'form': form,
  117. 'active_tab': 'userkey',
  118. })
  119. class SessionKeyDeleteView(LoginRequiredMixin, View):
  120. def get(self, request):
  121. sessionkey = get_object_or_404(SessionKey, userkey__user=request.user)
  122. form = ConfirmationForm()
  123. return render(request, 'users/sessionkey_delete.html', {
  124. 'obj_type': sessionkey._meta.verbose_name,
  125. 'form': form,
  126. 'return_url': reverse('user:userkey'),
  127. })
  128. def post(self, request):
  129. sessionkey = get_object_or_404(SessionKey, userkey__user=request.user)
  130. form = ConfirmationForm(request.POST)
  131. if form.is_valid():
  132. # Delete session key
  133. sessionkey.delete()
  134. messages.success(request, "Session key deleted")
  135. # Delete cookie
  136. response = redirect('user:userkey')
  137. response.delete_cookie('session_key')
  138. return response
  139. return render(request, 'users/sessionkey_delete.html', {
  140. 'obj_type': sessionkey._meta.verbose_name,
  141. 'form': form,
  142. 'return_url': reverse('user:userkey'),
  143. })
  144. #
  145. # API tokens
  146. #
  147. class TokenListView(LoginRequiredMixin, View):
  148. def get(self, request):
  149. tokens = Token.objects.filter(user=request.user)
  150. return render(request, 'users/api_tokens.html', {
  151. 'tokens': tokens,
  152. 'active_tab': 'api_tokens',
  153. })
  154. class TokenEditView(LoginRequiredMixin, View):
  155. def get(self, request, pk=None):
  156. if pk is not None:
  157. if not request.user.has_perm('users.change_token'):
  158. return HttpResponseForbidden()
  159. token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
  160. else:
  161. if not request.user.has_perm('users.add_token'):
  162. return HttpResponseForbidden()
  163. token = Token(user=request.user)
  164. form = TokenForm(instance=token)
  165. return render(request, 'utilities/obj_edit.html', {
  166. 'obj': token,
  167. 'obj_type': token._meta.verbose_name,
  168. 'form': form,
  169. 'return_url': reverse('user:token_list'),
  170. })
  171. def post(self, request, pk=None):
  172. if pk is not None:
  173. token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
  174. form = TokenForm(request.POST, instance=token)
  175. else:
  176. token = Token()
  177. form = TokenForm(request.POST)
  178. if form.is_valid():
  179. token = form.save(commit=False)
  180. token.user = request.user
  181. token.save()
  182. msg = "Modified token {}".format(token) if pk else "Created token {}".format(token)
  183. messages.success(request, msg)
  184. if '_addanother' in request.POST:
  185. return redirect(request.path)
  186. else:
  187. return redirect('user:token_list')
  188. return render(request, 'utilities/obj_edit.html', {
  189. 'obj': token,
  190. 'obj_type': token._meta.verbose_name,
  191. 'form': form,
  192. 'return_url': reverse('user:token_list'),
  193. })
  194. class TokenDeleteView(PermissionRequiredMixin, View):
  195. permission_required = 'users.delete_token'
  196. def get(self, request, pk):
  197. token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
  198. initial_data = {
  199. 'return_url': reverse('user:token_list'),
  200. }
  201. form = ConfirmationForm(initial=initial_data)
  202. return render(request, 'utilities/obj_delete.html', {
  203. 'obj': token,
  204. 'obj_type': token._meta.verbose_name,
  205. 'form': form,
  206. 'return_url': reverse('user:token_list'),
  207. })
  208. def post(self, request, pk):
  209. token = get_object_or_404(Token.objects.filter(user=request.user), pk=pk)
  210. form = ConfirmationForm(request.POST)
  211. if form.is_valid():
  212. token.delete()
  213. messages.success(request, "Token deleted")
  214. return redirect('user:token_list')
  215. return render(request, 'utilities/obj_delete.html', {
  216. 'obj': token,
  217. 'obj_type': token._meta.verbose_name,
  218. 'form': form,
  219. 'return_url': reverse('user:token_list'),
  220. })