views.py 8.8 KB

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