auth.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. # coding=utf-8
  2. from django import forms
  3. from django.contrib.auth.forms import (UserCreationForm, UserChangeForm,
  4. AdminPasswordChangeForm, PasswordChangeForm)
  5. from django.contrib.auth.models import Group, Permission
  6. from django.core.exceptions import PermissionDenied
  7. from django.conf import settings
  8. from django.template.response import TemplateResponse
  9. from django.utils.decorators import method_decorator
  10. from django.http import HttpResponseRedirect
  11. from django.utils.html import escape
  12. from django.utils.encoding import smart_text
  13. from django.utils.translation import ugettext as _
  14. from django.views.decorators.debug import sensitive_post_parameters
  15. from django.forms import ModelMultipleChoiceField
  16. from django.contrib.auth import get_user_model
  17. from xadmin.layout import Fieldset, Main, Side, Row, FormHelper
  18. from xadmin.sites import site
  19. from xadmin.util import unquote
  20. from xadmin.views import BaseAdminPlugin, ModelFormAdminView, ModelAdminView, CommAdminView, csrf_protect_m
  21. User = get_user_model()
  22. ACTION_NAME = {
  23. 'add': _('Can add %s'),
  24. 'change': _('Can change %s'),
  25. 'edit': _('Can edit %s'),
  26. 'delete': _('Can delete %s'),
  27. 'view': _('Can view %s'),
  28. }
  29. def get_permission_name(p):
  30. action = p.codename.split('_')[0]
  31. if action in ACTION_NAME:
  32. return ACTION_NAME[action] % str(p.content_type)
  33. else:
  34. return p.name
  35. class PermissionModelMultipleChoiceField(ModelMultipleChoiceField):
  36. def label_from_instance(self, p):
  37. return get_permission_name(p)
  38. class GroupAdmin(object):
  39. search_fields = ('name',)
  40. ordering = ('name',)
  41. style_fields = {'permissions': 'm2m_transfer'}
  42. model_icon = 'fa fa-group'
  43. def get_field_attrs(self, db_field, **kwargs):
  44. attrs = super(GroupAdmin, self).get_field_attrs(db_field, **kwargs)
  45. if db_field.name == 'permissions':
  46. attrs['form_class'] = PermissionModelMultipleChoiceField
  47. return attrs
  48. class UserAdmin(object):
  49. change_user_password_template = None
  50. list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
  51. list_filter = ('is_staff', 'is_superuser', 'is_active')
  52. search_fields = ('username', 'first_name', 'last_name', 'email')
  53. ordering = ('username',)
  54. style_fields = {'user_permissions': 'm2m_transfer'}
  55. model_icon = 'fa fa-user'
  56. relfield_style = 'fk-ajax'
  57. def get_field_attrs(self, db_field, **kwargs):
  58. attrs = super(UserAdmin, self).get_field_attrs(db_field, **kwargs)
  59. if db_field.name == 'user_permissions':
  60. attrs['form_class'] = PermissionModelMultipleChoiceField
  61. return attrs
  62. def get_model_form(self, **kwargs):
  63. if self.org_obj is None:
  64. self.form = UserCreationForm
  65. else:
  66. self.form = UserChangeForm
  67. return super(UserAdmin, self).get_model_form(**kwargs)
  68. def get_form_layout(self):
  69. if self.org_obj:
  70. self.form_layout = (
  71. Main(
  72. Fieldset('',
  73. 'username', 'password',
  74. css_class='unsort no_title'
  75. ),
  76. Fieldset(_('Personal info'),
  77. Row('first_name', 'last_name'),
  78. 'email'
  79. ),
  80. Fieldset(_('Permissions'),
  81. 'groups', 'user_permissions'
  82. ),
  83. Fieldset(_('Important dates'),
  84. 'last_login', 'date_joined'
  85. ),
  86. ),
  87. Side(
  88. Fieldset(_('Status'),
  89. 'is_active', 'is_staff', 'is_superuser',
  90. ),
  91. )
  92. )
  93. return super(UserAdmin, self).get_form_layout()
  94. class PermissionAdmin(object):
  95. def show_name(self, p):
  96. return get_permission_name(p)
  97. show_name.short_description = _('Permission Name')
  98. show_name.is_column = True
  99. model_icon = 'fa fa-lock'
  100. list_display = ('show_name', )
  101. site.register(Group, GroupAdmin)
  102. site.register(User, UserAdmin)
  103. site.register(Permission, PermissionAdmin)
  104. class UserFieldPlugin(BaseAdminPlugin):
  105. user_fields = []
  106. def get_field_attrs(self, __, db_field, **kwargs):
  107. if self.user_fields and db_field.name in self.user_fields:
  108. return {'widget': forms.HiddenInput}
  109. return __()
  110. def get_form_datas(self, datas):
  111. if self.user_fields and 'data' in datas:
  112. if hasattr(datas['data'],'_mutable') and not datas['data']._mutable:
  113. datas['data'] = datas['data'].copy()
  114. for f in self.user_fields:
  115. datas['data'][f] = self.user.id
  116. return datas
  117. site.register_plugin(UserFieldPlugin, ModelFormAdminView)
  118. class ModelPermissionPlugin(BaseAdminPlugin):
  119. user_can_access_owned_objects_only = False
  120. user_owned_objects_field = 'user'
  121. def queryset(self, qs):
  122. if self.user_can_access_owned_objects_only and \
  123. not self.user.is_superuser:
  124. filters = {self.user_owned_objects_field: self.user}
  125. qs = qs.filter(**filters)
  126. return qs
  127. def get_list_display(self, list_display):
  128. if self.user_can_access_owned_objects_only and \
  129. not self.user.is_superuser and \
  130. self.user_owned_objects_field in list_display:
  131. list_display.remove(self.user_owned_objects_field)
  132. return list_display
  133. site.register_plugin(ModelPermissionPlugin, ModelAdminView)
  134. class AccountMenuPlugin(BaseAdminPlugin):
  135. def block_top_account_menu(self, context, nodes):
  136. return '<li><a href="%s"><i class="fa fa-key"></i> %s</a></li>' % (self.get_admin_url('account_password'), _('Change Password'))
  137. site.register_plugin(AccountMenuPlugin, CommAdminView)
  138. class ChangePasswordView(ModelAdminView):
  139. model = User
  140. change_password_form = AdminPasswordChangeForm
  141. change_user_password_template = None
  142. @csrf_protect_m
  143. def get(self, request, object_id):
  144. if not self.has_change_permission(request):
  145. raise PermissionDenied
  146. self.obj = self.get_object(unquote(object_id))
  147. self.form = self.change_password_form(self.obj)
  148. return self.get_response()
  149. def get_media(self):
  150. media = super(ChangePasswordView, self).get_media()
  151. media = media + self.vendor('xadmin.form.css', 'xadmin.page.form.js') + self.form.media
  152. return media
  153. def get_context(self):
  154. context = super(ChangePasswordView, self).get_context()
  155. helper = FormHelper()
  156. helper.form_tag = False
  157. helper.include_media = False
  158. self.form.helper = helper
  159. context.update({
  160. 'title': _('Change password: %s') % escape(smart_text(self.obj)),
  161. 'form': self.form,
  162. 'has_delete_permission': False,
  163. 'has_change_permission': True,
  164. 'has_view_permission': True,
  165. 'original': self.obj,
  166. })
  167. return context
  168. def get_response(self):
  169. return TemplateResponse(self.request, [
  170. self.change_user_password_template or
  171. 'xadmin/auth/user/change_password.html'
  172. ], self.get_context())
  173. @method_decorator(sensitive_post_parameters())
  174. @csrf_protect_m
  175. def post(self, request, object_id):
  176. if not self.has_change_permission(request):
  177. raise PermissionDenied
  178. self.obj = self.get_object(unquote(object_id))
  179. self.form = self.change_password_form(self.obj, request.POST)
  180. if self.form.is_valid():
  181. self.form.save()
  182. self.message_user(_('Password changed successfully.'), 'success')
  183. return HttpResponseRedirect(self.model_admin_url('change', self.obj.pk))
  184. else:
  185. return self.get_response()
  186. class ChangeAccountPasswordView(ChangePasswordView):
  187. change_password_form = PasswordChangeForm
  188. @csrf_protect_m
  189. def get(self, request):
  190. self.obj = self.user
  191. self.form = self.change_password_form(self.obj)
  192. return self.get_response()
  193. def get_context(self):
  194. context = super(ChangeAccountPasswordView, self).get_context()
  195. context.update({
  196. 'title': _('Change password'),
  197. 'account_view': True,
  198. })
  199. return context
  200. @method_decorator(sensitive_post_parameters())
  201. @csrf_protect_m
  202. def post(self, request):
  203. self.obj = self.user
  204. self.form = self.change_password_form(self.obj, request.POST)
  205. if self.form.is_valid():
  206. self.form.save()
  207. self.message_user(_('Password changed successfully.'), 'success')
  208. return HttpResponseRedirect(self.get_admin_url('index'))
  209. else:
  210. return self.get_response()
  211. user_model = settings.AUTH_USER_MODEL.lower().replace('.','/')
  212. site.register_view(r'^%s/(.+)/password/$' % user_model,
  213. ChangePasswordView, name='user_change_password')
  214. site.register_view(r'^account/password/$', ChangeAccountPasswordView,
  215. name='account_password')