invitation_backend.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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.http import base36_to_int
  5. from django.utils.crypto import constant_time_compare
  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(self._make_token_with_timestamp(user, ts), token):
  28. return False
  29. # Check the timestamp is within limit
  30. if (self._num_seconds(self._now()) - ts) > REGISTRATION_TIMEOUT_DAYS * 86400:
  31. return False
  32. return True
  33. class InvitationBackend(BaseInvitationBackend):
  34. """
  35. Based on django-organizations InvitationBackend but for org user instead of user
  36. """
  37. def __init__(self, org_model=None, namespace=None):
  38. self.user_model = None
  39. self.org_model = Organization
  40. self.namespace = namespace
  41. def get_urls(self):
  42. return [
  43. re_path(
  44. r"^(?P<user_id>[\d]+)/(?P<token>[0-9A-Za-z]{1,90}-[0-9A-Za-z]{1,90})/$",
  45. view=self.activate_view,
  46. name="invitations_register",
  47. ),
  48. ]
  49. def get_token(self, org_user, **kwargs):
  50. return InvitationTokenGenerator().make_token(org_user)
  51. def send_invitation(self, user, sender=None, **kwargs):
  52. kwargs.update(
  53. {"token": self.get_token(user), "organization": user.organization,}
  54. )
  55. send_email_invite.delay(user.pk, kwargs["token"])
  56. return True