Source code for thorn.generic.models
"""Generic base model mixins."""
from __future__ import absolute_import, unicode_literals
from abc import ABCMeta, abstractmethod, abstractproperty
from six import string_types
from celery.five import with_metaclass
from thorn._state import current_app
__all__ = ['AbstractSubscriber', 'SubscriberModelMixin']
@with_metaclass(ABCMeta)
[docs]class AbstractSubscriber(object):
"""Abstract class for Subscriber identity."""
#: Unique identifier.
uuid = abstractproperty()
#: Event pattern this subscriber is subscribed to (e.g. ``article.*``).
event = abstractproperty()
#: Destination URL to dispatch this event.
url = abstractproperty()
#: User filter: when set only dispatch if the event sender matches.
user = abstractproperty()
#: HMAC secret key, of arbitrary length.
hmac_secret = abstractproperty()
#: HMAC digest type (e.g. ``"sha512"``).
#:
#: The value used must be a member of :data:`hashlib.algorithms_available`.
hmac_digest = abstractproperty()
#: MIME-type to use for web requests made to the subscriber :attr:`url`.
content_type = abstractproperty()
@abstractmethod
[docs] def as_dict(self):
"""Dictionary representation of Subscriber."""
pass # pragma: no cover
@abstractmethod
[docs] def from_dict(self, *args, **kwargs):
"""Create subscriber from dictionary representation.
Note:
Accepts the same arguments as :class:`dict`.
"""
pass # pragma: no cover
@abstractmethod
[docs] def sign(self, message):
"""Sign message using HMAC.
Note:
:attr:`hmac_secret` and the current
:attr:`hmac_digest` type must be set.
"""
pass # pragma: no cover
@abstractmethod
[docs] def user_ident(self):
"""Return :attr:`user` identity.
Note:
Value must be json serializable like a database primary key.
"""
pass # pragma: no cover
@classmethod
[docs] def register(cls, other):
# we override `register` to return other for use as a decorator.
type(cls).register(cls, other)
return other
@AbstractSubscriber.register
[docs]class SubscriberModelMixin(object):
"""Mixin for subscriber models."""
@classmethod
[docs] def from_dict(cls, *args, **kwargs):
if args and isinstance(args[0], string_types):
args = ({'url': args[0]},)
return cls(**dict(*args, **kwargs))
[docs] def as_dict(self):
return {
'uuid': str(self.uuid),
'event': self.event,
'user': self.user_ident(),
'url': self.url,
'hmac_secret': self.hmac_secret,
'hmac_digest': self.hmac_digest,
'content_type': self.content_type,
}
[docs] def sign(self, message):
return current_app().hmac_sign(
self.hmac_digest, self.hmac_secret, message,
)