admin.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. from django.contrib.auth import get_user_model
  2. from django.utils.translation import ugettext_lazy as _
  3. from misago.core import forms, threadstore
  4. from misago.core.validators import validate_sluggable
  5. from misago.acl.models import Role
  6. from misago.users.models import Rank
  7. from misago.users.validators import (validate_username, validate_email,
  8. validate_password)
  9. """
  10. Users forms
  11. """
  12. class UserBaseForm(forms.ModelForm):
  13. username = forms.CharField(
  14. label=_("Username"))
  15. title = forms.CharField(
  16. label=_("Custom title"),
  17. required=False)
  18. email = forms.EmailField(
  19. label=_("E-mail address"))
  20. class Meta:
  21. model = get_user_model()
  22. fields = ['username', 'email', 'title']
  23. def clean_username(self):
  24. data = self.cleaned_data['username']
  25. validate_username(data)
  26. return data
  27. def clean_email(self):
  28. data = self.cleaned_data['email']
  29. validate_email(data)
  30. return data
  31. def clean_new_password(self):
  32. data = self.cleaned_data['new_password']
  33. validate_password(data)
  34. return data
  35. def clean_roles(self):
  36. data = self.cleaned_data['roles']
  37. for role in data:
  38. if role.special_role == 'authenticated':
  39. break
  40. else:
  41. message = _('All registered members must have "Member" role.')
  42. raise forms.ValidationError(message)
  43. return data
  44. class NewUserForm(UserBaseForm):
  45. new_password = forms.CharField(
  46. label=_("Password"),
  47. widget=forms.PasswordInput)
  48. class Meta:
  49. model = get_user_model()
  50. fields = ['username', 'email', 'title']
  51. class EditUserForm(forms.ModelForm):
  52. new_password = forms.CharField(
  53. label=_("Change password to"),
  54. widget=forms.PasswordInput,
  55. required=False)
  56. class Meta:
  57. model = get_user_model()
  58. fields = ['username', 'email', 'title']
  59. def UserFormFactory(FormType, instance):
  60. extra_fields = {}
  61. ranks = Rank.objects.order_by('name')
  62. if ranks.exists():
  63. extra_fields['rank'] = forms.ModelChoiceField(
  64. label=_("Rank"),
  65. help_text=_("Ranks are used to group and distinguish users. "
  66. "They are also used to add permissions to groups of "
  67. "users."),
  68. queryset=ranks,
  69. initial=instance.rank,
  70. required=False,
  71. empty_label=_("No rank"))
  72. roles = Role.objects.order_by('name')
  73. extra_fields['roles'] = forms.ModelMultipleChoiceField(
  74. label=_("Roles"),
  75. help_text=_("Individual roles of this user."),
  76. queryset=roles,
  77. initial=instance.roles.all() if instance.pk else None,
  78. widget=forms.CheckboxSelectMultiple)
  79. return type('UserFormFinal', (FormType,), extra_fields)
  80. def StaffFlagUserFormFactory(FormType, instance, add_staff_field):
  81. FormType = UserFormFactory(FormType, instance)
  82. if add_staff_field:
  83. staff_levels = (
  84. (0, _("No access")),
  85. (1, _("Administrator")),
  86. (2, _("Superadmin")),
  87. )
  88. staff_fields = {
  89. 'staff_level': forms.TypedChoiceField(
  90. label=_("Admin level"),
  91. help_text=_('Only administrators can access admin sites. '
  92. 'In addition to admin site access, superadmins '
  93. 'can also change other members admin levels.'),
  94. coerce=int,
  95. choices=staff_levels,
  96. initial=instance.staff_level),
  97. }
  98. return type('StaffUserForm', (FormType,), staff_fields)
  99. else:
  100. return FormType
  101. class SearchUsersFormBase(forms.Form):
  102. username = forms.CharField(label=_("Username starts with"), required=False)
  103. email = forms.CharField(label=_("E-mail starts with"), required=False)
  104. #rank = forms.TypedChoiceField(label=_("Rank"),
  105. # coerce=int,
  106. # required=False,
  107. # choices=ranks_list)
  108. #role = forms.TypedChoiceField(label=_("Role"),
  109. # coerce=int,
  110. # required=False,
  111. # choices=roles_list)
  112. inactive = forms.YesNoSwitch(label=_("Inactive only"))
  113. is_staff = forms.YesNoSwitch(label=_("Is administrator"))
  114. def filter_queryset(self, cleaned_data, queryset):
  115. if cleaned_data.get('username'):
  116. queryset = queryset.filter(
  117. username_slug__startswith=cleaned_data.get('username').lower())
  118. if cleaned_data.get('email'):
  119. queryset = queryset.filter(
  120. email__istartswith=cleaned_data.get('email'))
  121. if cleaned_data.get('rank'):
  122. queryset = queryset.filter(
  123. rank_id=cleaned_data.get('rank'))
  124. if cleaned_data.get('role'):
  125. queryset = queryset.filter(
  126. roles__id=cleaned_data.get('role'))
  127. if cleaned_data.get('inactive'):
  128. pass
  129. if cleaned_data.get('is_staff'):
  130. queryset = queryset.filter(is_staff=True)
  131. return queryset
  132. def SearchUsersForm(*args, **kwargs):
  133. """
  134. Factory that uses cache for ranks and roles,
  135. and makes those ranks and roles typed choice fields that play nice
  136. with passing values via GET
  137. """
  138. ranks_choices = threadstore.get('misago_admin_ranks_choices', 'nada')
  139. if ranks_choices == 'nada':
  140. ranks_choices = [('', _("All ranks"))]
  141. for rank in Rank.objects.order_by('name').iterator():
  142. ranks_choices.append((rank.pk, rank.name))
  143. threadstore.set('misago_admin_ranks_choices', ranks_choices)
  144. roles_choices = threadstore.get('misago_admin_roles_choices', 'nada')
  145. if roles_choices == 'nada':
  146. roles_choices = [('', _("All roles"))]
  147. for role in Role.objects.order_by('name').iterator():
  148. roles_choices.append((role.pk, role.name))
  149. threadstore.set('misago_admin_roles_choices', roles_choices)
  150. extra_fields = {
  151. 'rank': forms.TypedChoiceField(label=_("Has rank"),
  152. coerce=int,
  153. required=False,
  154. choices=ranks_choices),
  155. 'role': forms.TypedChoiceField(label=_("Has role"),
  156. coerce=int,
  157. required=False,
  158. choices=roles_choices)
  159. }
  160. FinalForm = type('SearchUsersFormFinal',
  161. (SearchUsersFormBase,),
  162. extra_fields)
  163. return FinalForm(*args, **kwargs)
  164. """
  165. Ranks form
  166. """
  167. class RankForm(forms.ModelForm):
  168. name = forms.CharField(
  169. label=_("Name"),
  170. validators=[validate_sluggable()],
  171. help_text=_('Short and descriptive name of all users with this rank. '
  172. '"The Team" or "Game Masters" are good examples.'))
  173. title = forms.CharField(
  174. label=_("User title"), required=False,
  175. help_text=_('Optional, singular version of rank name displayed by '
  176. 'user names. For example "GM" or "Dev".'))
  177. description = forms.CharField(
  178. label=_("Description"), max_length=2048, required=False,
  179. widget=forms.Textarea(attrs={'rows': 3}),
  180. help_text=_("Optional description explaining function or status of "
  181. "members distincted with this rank."))
  182. roles = forms.ModelMultipleChoiceField(
  183. label=_("User roles"), queryset=Role.objects.order_by('name'),
  184. required=False, widget=forms.CheckboxSelectMultiple,
  185. help_text=_('Rank can give users with it additional roles.'))
  186. css_class = forms.CharField(
  187. label=_("CSS class"), required=False,
  188. help_text=_("Optional css class added to content belonging to this "
  189. "rank owner."))
  190. is_tab = forms.BooleanField(
  191. label=_("Give rank dedicated tab on users list"), required=False,
  192. help_text=_("Selecting this option will make users with this rank "
  193. "easily discoverable by others trough dedicated page on "
  194. "forum users list."))
  195. is_on_index = forms.BooleanField(
  196. label=_("Show users online on forum index"), required=False,
  197. help_text=_("Selecting this option will make forum inform other "
  198. "users of their availability by displaying them on forum "
  199. "index page."))
  200. class Meta:
  201. model = Rank
  202. fields = [
  203. 'name',
  204. 'description',
  205. 'css_class',
  206. 'title',
  207. 'roles',
  208. 'is_tab',
  209. 'is_on_index',
  210. ]
  211. def clean(self):
  212. data = super(RankForm, self).clean()
  213. self.instance.set_name(data.get('name'))
  214. return data