PageRenderTime 30ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/userena/managers.py

http://github.com/bread-and-pepper/django-userena
Python | 314 lines | 246 code | 18 blank | 50 comment | 3 complexity | 32e522cb42dd75ba448a9af4ec0c1e3b MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from django.db import models
  2. from django.db.models import Q
  3. from django.core.exceptions import ObjectDoesNotExist
  4. from django.contrib.auth import get_user_model
  5. from django.contrib.auth.models import UserManager, Permission, AnonymousUser
  6. from django.contrib.contenttypes.models import ContentType
  7. from django.utils.encoding import smart_text
  8. from django.utils.translation import ugettext as _
  9. from django.conf import settings
  10. from django.utils.six import text_type
  11. from userena import settings as userena_settings
  12. from userena.utils import generate_sha1, get_profile_model, get_datetime_now, \
  13. get_user_profile
  14. from userena import signals as userena_signals
  15. from guardian.shortcuts import assign_perm, get_perms
  16. import re
  17. SHA1_RE = re.compile('^[a-f0-9]{40}$')
  18. ASSIGNED_PERMISSIONS = {
  19. 'profile':
  20. (('view_profile', 'Can view profile'),
  21. ('change_profile', 'Can change profile'),
  22. ('delete_profile', 'Can delete profile')),
  23. 'user':
  24. (('change_user', 'Can change user'),
  25. ('delete_user', 'Can delete user'))
  26. }
  27. class UserenaManager(UserManager):
  28. """ Extra functionality for the Userena model. """
  29. def create_user(self, username, email, password, active=False,
  30. send_email=True):
  31. """
  32. A simple wrapper that creates a new :class:`User`.
  33. :param username:
  34. String containing the username of the new user.
  35. :param email:
  36. String containing the email address of the new user.
  37. :param password:
  38. String containing the password for the new user.
  39. :param active:
  40. Boolean that defines if the user requires activation by clicking
  41. on a link in an e-mail. Defaults to ``False``.
  42. :param send_email:
  43. Boolean that defines if the user should be sent an email. You could
  44. set this to ``False`` when you want to create a user in your own
  45. code, but don't want the user to activate through email.
  46. :return: :class:`User` instance representing the new user.
  47. """
  48. new_user = get_user_model().objects.create_user(
  49. username, email, password)
  50. new_user.is_active = active
  51. new_user.save()
  52. # Give permissions to view and change profile
  53. for perm in ASSIGNED_PERMISSIONS['profile']:
  54. assign_perm(perm[0], new_user, get_user_profile(user=new_user))
  55. # Give permissions to view and change itself
  56. for perm in ASSIGNED_PERMISSIONS['user']:
  57. assign_perm(perm[0], new_user, new_user)
  58. userena_profile = self.create_userena_profile(new_user)
  59. if send_email:
  60. userena_profile.send_activation_email()
  61. return new_user
  62. def create_userena_profile(self, user):
  63. """
  64. Creates an :class:`UserenaSignup` instance for this user.
  65. :param user:
  66. Django :class:`User` instance.
  67. :return: The newly created :class:`UserenaSignup` instance.
  68. """
  69. if isinstance(user.username, text_type):
  70. user.username = smart_text(user.username)
  71. salt, activation_key = generate_sha1(user.username)
  72. try:
  73. profile = self.get(user=user)
  74. except self.model.DoesNotExist:
  75. profile = self.create(user=user,
  76. activation_key=activation_key)
  77. return profile
  78. def reissue_activation(self, activation_key):
  79. """
  80. Creates a new ``activation_key`` resetting activation timeframe when
  81. users let the previous key expire.
  82. :param activation_key:
  83. String containing the secret SHA1 activation key.
  84. """
  85. try:
  86. userena = self.get(activation_key=activation_key)
  87. except self.model.DoesNotExist:
  88. return False
  89. try:
  90. salt, new_activation_key = generate_sha1(userena.user.username)
  91. userena.activation_key = new_activation_key
  92. userena.save(using=self._db)
  93. userena.user.date_joined = get_datetime_now()
  94. userena.user.save(using=self._db)
  95. userena.send_activation_email()
  96. return True
  97. except Exception:
  98. return False
  99. def activate_user(self, activation_key):
  100. """
  101. Activate an :class:`User` by supplying a valid ``activation_key``.
  102. If the key is valid and an user is found, activates the user and
  103. return it. Also sends the ``activation_complete`` signal.
  104. :param activation_key:
  105. String containing the secret SHA1 for a valid activation.
  106. :return:
  107. The newly activated :class:`User` or ``False`` if not successful.
  108. """
  109. if SHA1_RE.search(activation_key):
  110. try:
  111. userena = self.get(activation_key=activation_key)
  112. except self.model.DoesNotExist:
  113. return False
  114. if not userena.activation_key_expired():
  115. userena.activation_key = userena_settings.USERENA_ACTIVATED
  116. user = userena.user
  117. user.is_active = True
  118. userena.save(using=self._db)
  119. user.save(using=self._db)
  120. # Send the activation_complete signal
  121. userena_signals.activation_complete.send(sender=None,
  122. user=user)
  123. return user
  124. return False
  125. def check_expired_activation(self, activation_key):
  126. """
  127. Check if ``activation_key`` is still valid.
  128. Raises a ``self.model.DoesNotExist`` exception if key is not present or
  129. ``activation_key`` is not a valid string
  130. :param activation_key:
  131. String containing the secret SHA1 for a valid activation.
  132. :return:
  133. True if the ket has expired, False if still valid.
  134. """
  135. if SHA1_RE.search(activation_key):
  136. userena = self.get(activation_key=activation_key)
  137. return userena.activation_key_expired()
  138. raise self.model.DoesNotExist
  139. def confirm_email(self, confirmation_key):
  140. """
  141. Confirm an email address by checking a ``confirmation_key``.
  142. A valid ``confirmation_key`` will set the newly wanted e-mail
  143. address as the current e-mail address. Returns the user after
  144. success or ``False`` when the confirmation key is
  145. invalid. Also sends the ``confirmation_complete`` signal.
  146. :param confirmation_key:
  147. String containing the secret SHA1 that is used for verification.
  148. :return:
  149. The verified :class:`User` or ``False`` if not successful.
  150. """
  151. if SHA1_RE.search(confirmation_key):
  152. try:
  153. userena = self.get(email_confirmation_key=confirmation_key,
  154. email_unconfirmed__isnull=False)
  155. except self.model.DoesNotExist:
  156. return False
  157. else:
  158. user = userena.user
  159. old_email = user.email
  160. user.email = userena.email_unconfirmed
  161. userena.email_unconfirmed, userena.email_confirmation_key = '',''
  162. userena.save(using=self._db)
  163. user.save(using=self._db)
  164. # Send the confirmation_complete signal
  165. userena_signals.confirmation_complete.send(sender=None,
  166. user=user,
  167. old_email=old_email)
  168. return user
  169. return False
  170. def delete_expired_users(self):
  171. """
  172. Checks for expired users and delete's the ``User`` associated with
  173. it. Skips if the user ``is_staff``.
  174. :return: A list containing the deleted users.
  175. """
  176. deleted_users = []
  177. for user in get_user_model().objects.filter(is_staff=False,
  178. is_active=False):
  179. if user.userena_signup.activation_key_expired():
  180. deleted_users.append(user)
  181. user.delete()
  182. return deleted_users
  183. def check_permissions(self):
  184. """
  185. Checks that all permissions are set correctly for the users.
  186. :return: A set of users whose permissions was wrong.
  187. """
  188. # Variable to supply some feedback
  189. changed_permissions = []
  190. changed_users = []
  191. warnings = []
  192. # Check that all the permissions are available.
  193. for model, perms in ASSIGNED_PERMISSIONS.items():
  194. if model == 'profile':
  195. model_obj = get_profile_model()
  196. else: model_obj = get_user_model()
  197. model_content_type = ContentType.objects.get_for_model(model_obj)
  198. for perm in perms:
  199. try:
  200. Permission.objects.get(codename=perm[0],
  201. content_type=model_content_type)
  202. except Permission.DoesNotExist:
  203. changed_permissions.append(perm[1])
  204. Permission.objects.create(name=perm[1],
  205. codename=perm[0],
  206. content_type=model_content_type)
  207. # it is safe to rely on settings.ANONYMOUS_USER_ID since it is a
  208. # requirement of django-guardian
  209. for user in get_user_model().objects.exclude(id=settings.ANONYMOUS_USER_ID):
  210. try:
  211. user_profile = get_user_profile(user=user)
  212. except ObjectDoesNotExist:
  213. warnings.append(_("No profile found for %(username)s") \
  214. % {'username': user.username})
  215. else:
  216. all_permissions = get_perms(user, user_profile) + get_perms(user, user)
  217. for model, perms in ASSIGNED_PERMISSIONS.items():
  218. if model == 'profile':
  219. perm_object = get_user_profile(user=user)
  220. else: perm_object = user
  221. for perm in perms:
  222. if perm[0] not in all_permissions:
  223. assign_perm(perm[0], user, perm_object)
  224. changed_users.append(user)
  225. return (changed_permissions, changed_users, warnings)
  226. class UserenaBaseProfileManager(models.Manager):
  227. """ Manager for :class:`UserenaProfile` """
  228. def get_visible_profiles(self, user=None):
  229. """
  230. Returns all the visible profiles available to this user.
  231. For now keeps it simple by just applying the cases when a user is not
  232. active, a user has it's profile closed to everyone or a user only
  233. allows registered users to view their profile.
  234. :param user:
  235. A Django :class:`User` instance.
  236. :return:
  237. All profiles that are visible to this user.
  238. """
  239. profiles = self.all()
  240. filter_kwargs = {'user__is_active': True}
  241. profiles = profiles.filter(**filter_kwargs)
  242. if user and isinstance(user, AnonymousUser):
  243. profiles = profiles.exclude(Q(privacy='closed') | Q(privacy='registered'))
  244. else: profiles = profiles.exclude(Q(privacy='closed'))
  245. return profiles