invitation_backend.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. from django.conf import settings
  2. from django.contrib.auth.tokens import PasswordResetTokenGenerator
  3. from django.urls import re_path
  4. from django.utils.crypto import constant_time_compare
  5. from django.utils.http import base36_to_int
  6. from organizations.backends.defaults import InvitationBackend as BaseInvitationBackend
  7. from .models import Organization
  8. from .tasks import send_email_invite
  9. REGISTRATION_TIMEOUT_DAYS = getattr(settings, "REGISTRATION_TIMEOUT_DAYS", 15)
  10. class InvitationTokenGenerator(PasswordResetTokenGenerator):
  11. def _make_hash_value(self, user, timestamp):
  12. return str(user.pk) + str(timestamp)
  13. def check_token(self, user, token):
  14. """
  15. Check that a password reset token is correct for a given user.
  16. """
  17. # Parse the token
  18. try:
  19. ts_b36, _hash = token.split("-")
  20. except ValueError:
  21. return False
  22. try:
  23. ts = base36_to_int(ts_b36)
  24. except ValueError:
  25. return False
  26. # Check that the timestamp/uid has not been tampered with
  27. if not constant_time_compare(
  28. self._make_token_with_timestamp(user, ts, self.secret), token
  29. ):
  30. return False
  31. # Check the timestamp is within limit
  32. if (self._num_seconds(self._now()) - ts) > REGISTRATION_TIMEOUT_DAYS * 86400:
  33. return False
  34. return True
  35. class InvitationBackend(BaseInvitationBackend):
  36. """
  37. Based on django-organizations InvitationBackend but for org user instead of user
  38. """
  39. def __init__(self, org_model=None, namespace=None):
  40. self.user_model = None
  41. self.org_model = Organization
  42. self.namespace = namespace
  43. def get_urls(self):
  44. return [
  45. re_path(
  46. r"^(?P<user_id>[\d]+)/(?P<token>[0-9A-Za-z]{1,90}-[0-9A-Za-z]{1,90})/$",
  47. view=self.activate_view,
  48. name="invitations_register",
  49. ),
  50. ]
  51. def get_token(self, org_user, **kwargs):
  52. return InvitationTokenGenerator().make_token(org_user)
  53. def send_invitation(self, user, sender=None, **kwargs):
  54. kwargs.update(
  55. {
  56. "token": self.get_token(user),
  57. "organization": user.organization,
  58. }
  59. )
  60. send_email_invite.delay(user.pk, kwargs["token"])
  61. return True