tokens.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.core.auth.tokens
  4. ~~~~~~~~~~~~~~~~~~~~~~~~
  5. This module provides ways of interacting
  6. with tokens in FlaskBB
  7. :copyright: (c) 2014-2018 by the FlaskBB Team.
  8. :license: BSD, see LICENSE for more details
  9. """
  10. from abc import abstractmethod
  11. import attr
  12. from flask_babelplus import gettext as _
  13. from .._compat import ABC
  14. from .exceptions import BaseFlaskBBError
  15. class TokenError(BaseFlaskBBError):
  16. """
  17. Raised when there is an issue with deserializing
  18. a token. Has helper classmethods to ensure
  19. consistent verbiage.
  20. :param str reason: An explanation of why the token is invalid
  21. """
  22. def __init__(self, reason):
  23. self.reason = reason
  24. super(TokenError, self).__init__(reason)
  25. @classmethod
  26. def invalid(cls):
  27. """
  28. Used to raise an exception about a token that is invalid
  29. due to being signed incorrectly, has been tampered with,
  30. is unparsable or contains an inappropriate action.
  31. """
  32. return cls(_('Token is invalid'))
  33. @classmethod
  34. def expired(cls):
  35. """
  36. Used to raise an exception about a token that has expired and is
  37. no longer usable.
  38. """
  39. return cls(_('Token is expired'))
  40. # in theory this would never be raised
  41. # but it's provided for a generic catchall
  42. # when processing goes horribly wrong
  43. @classmethod # pragma: no cover
  44. def bad(cls):
  45. return cls(_('Token cannot be processed'))
  46. # holder for token actions
  47. # not an enum so plugins can add to it
  48. class TokenActions:
  49. """
  50. Collection of token actions.
  51. .. note::
  52. This is just a class rather than an enum because enums cannot be
  53. extended at runtime which would limit the number of token actions
  54. to the ones implemented by FlaskBB itself and block extension of
  55. tokens by plugins.
  56. """
  57. RESET_PASSWORD = 'reset_password'
  58. ACTIVATE_ACCOUNT = 'activate_account'
  59. @attr.s(frozen=True, cmp=True, hash=True)
  60. class Token(object):
  61. """
  62. :param int user_id:
  63. :param str operation: An operation taken from
  64. :class:`TokenActions<flaskbb.core.tokens.TokenActions>`
  65. """
  66. user_id = attr.ib()
  67. operation = attr.ib()
  68. class TokenSerializer(ABC):
  69. """
  70. """
  71. @abstractmethod
  72. def dumps(self, token):
  73. """
  74. This method is abstract.
  75. Used to transform a token into a string representation of it.
  76. :param token:
  77. :type token: :class:`Token<flaskbb.core.tokens.Token>`
  78. :returns str:
  79. """
  80. pass
  81. @abstractmethod
  82. def loads(self, raw_token):
  83. """
  84. This method is abstract
  85. Used to transform a string representation of a token into an
  86. actual :class:`Token<flaskbb.core.tokens.Token>` instance
  87. :param str raw_token:
  88. :returns token: The parsed token
  89. :rtype: :class:`Token<flaskbb.core.tokens.Token`>
  90. """
  91. pass
  92. class TokenVerifier(ABC):
  93. """
  94. Used to verify the validatity of tokens post
  95. deserialization, such as an email matching the
  96. user id in the provided token.
  97. Should raise a
  98. :class:`ValidationError<flaskbb.core.exceptions.ValidationError>`
  99. if verification fails.
  100. """
  101. @abstractmethod
  102. def verify_token(self, token, **kwargs):
  103. """
  104. This method is abstract.
  105. :param token: The parsed token to verify
  106. :param kwargs: Arbitrary context for validation of the token
  107. :type token: :class:`Token<flaskbb.core.tokens.Token>`
  108. """
  109. pass
  110. def __call__(self, token, **kwargs):
  111. return self.verify_token(token, **kwargs)