auth.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from datetime import timedelta
  2. from django.utils import timezone
  3. from django.utils.translation import ugettext_lazy as _
  4. from misago.conf import settings
  5. from misago.models import Ban, SignInAttempt, Token, User
  6. """
  7. Exception constants
  8. """
  9. CREDENTIALS = 0
  10. ACTIVATION_USER = 1
  11. ACTIVATION_ADMIN = 2
  12. BANNED = 3
  13. NOT_ADMIN = 4
  14. class AuthException(Exception):
  15. """
  16. Auth Exception is thrown when auth_* method finds problem with allowing user to sign-in
  17. """
  18. def __init__(self, type=None, error=None, password=False, activation=False, ban=False):
  19. self.type = type
  20. self.error = error
  21. self.password = password
  22. self.activation = activation
  23. self.ban = ban
  24. def __str__(self):
  25. return self.error
  26. def get_user(email, password, admin=False):
  27. """
  28. Fetch user from DB using email/pass pair, scream if either of data is incorrect
  29. """
  30. try:
  31. user = User.objects.get_by_email(email)
  32. if not user.check_password(password):
  33. raise AuthException(CREDENTIALS, _("Your e-mail address or password is incorrect. Please try again."), password=True)
  34. if not admin:
  35. if user.activation == User.ACTIVATION_ADMIN:
  36. # Only admin can activate your account.
  37. raise AuthException(ACTIVATION_ADMIN, _("Board Administrator has not yet accepted your account."))
  38. if user.activation != User.ACTIVATION_NONE:
  39. # You have to activate your account - new member
  40. raise AuthException(ACTIVATION_USER, _("You have to activate your account before you will be able to sign-in."), activation=True)
  41. except User.DoesNotExist:
  42. raise AuthException(CREDENTIALS, _("Your e-mail address or password is incorrect. Please try again."), password=True)
  43. return user;
  44. def auth_forum(request, email, password):
  45. """
  46. Forum auth - check bans and if we are in maintenance - maintenance access
  47. """
  48. user = get_user(email, password)
  49. user_ban = Ban.objects.check_ban(username=user.username, email=user.email)
  50. if user_ban:
  51. if user_ban.reason_user:
  52. raise AuthException(BANNED, _("Your account has been banned for following reason:"), ban=user_ban)
  53. raise AuthException(BANNED, _("Your account has been banned."), ban=user_ban)
  54. return user;
  55. def auth_remember(request, ip):
  56. """
  57. Remember-me auth - check if token is valid
  58. Dont worry about AuthException being empty, it doesnt have to have anything
  59. """
  60. if request.firewall.admin:
  61. raise AuthException()
  62. if SignInAttempt.objects.is_jammed(ip):
  63. raise AuthException()
  64. cookie_token = settings.COOKIES_PREFIX + 'TOKEN'
  65. try:
  66. cookie_token = request.COOKIES[cookie_token]
  67. if len(cookie_token) != 42:
  68. raise AuthException()
  69. try:
  70. token_rk = Token.objects.select_related().get(pk=cookie_token)
  71. except Token.DoesNotExist:
  72. request.cookiejar.delete('TOKEN')
  73. raise AuthException()
  74. # See if token is not expired
  75. token_expires = timezone.now() - timedelta(days=settings.remember_me_lifetime)
  76. if settings.remember_me_extensible and token_rk.accessed < token_expires:
  77. # Token expired because it's last use is smaller than expiration date
  78. raise AuthException()
  79. if not settings.remember_me_extensible and token_rk.created < token_expires:
  80. # Token expired because it was created before expiration date
  81. raise AuthException()
  82. # Update token date
  83. token_rk.accessed = timezone.now()
  84. token_rk.save(force_update=True)
  85. request.cookiejar.set('TOKEN', token_rk.id, True)
  86. except (AttributeError, KeyError):
  87. raise AuthException()
  88. return token_rk
  89. def auth_admin(request, email, password):
  90. """
  91. Admin auth - check ACP permissions
  92. """
  93. user = get_user(email, password, True)
  94. if not user.is_god() and not user.acl(request).special.is_admin():
  95. raise AuthException(NOT_ADMIN, _("Your account does not have admin privileges."))
  96. return user;
  97. def sign_user_in(request, user):
  98. user.set_last_visit(
  99. request.session.get_ip(request),
  100. request.META.get('HTTP_USER_AGENT', ''),
  101. )
  102. user.save(force_update=True)
  103. request.session.set_user(user)
  104. if not request.firewall.admin:
  105. request.onlines.sign_in()