@@ -0,0 +1,2912 @@
+import base64%0Aimport uuid as _uuid%0A%0Afrom django.contrib.postgres.fields import ArrayField%0Afrom django.db import models%0Afrom django.utils import timezone%0Afrom django.utils.crypto import constant_time_compare%0A%0Afrom libs.crypto import get_hmac%0A%0A%0Aclass EphemeralToken(models.Model):%0A    KEY_SALT = 'polyaxon.scope.key_salt'%0A%0A    uuid = models.UUIDField(%0A        default=_uuid.uuid4,%0A        editable=False,%0A        unique=True,%0A        null=False)%0A    salt = models.UUIDField(%0A        default=_uuid.uuid4,%0A        editable=False,%0A        null=False)%0A    created_at = models.DateTimeField(auto_now_add=True)%0A    num_uses = models.SmallIntegerField(%0A        blank=True,%0A        null=True,%0A        default=1)%0A    ttl = models.IntegerField(%0A        null=True,%0A        blank=True,%0A        default=60 * 60 * 3)%0A    scope = ArrayField(%0A        base_field=models.CharField(max_length=64),%0A        blank=True,%0A        null=True)%0A%0A    @staticmethod%0A    def clean_timestamp(timestamp):%0A        %22%22%22%0A        Cleans a timestamp to ensure that results are consistent across database%0A        backends.%0A        %22%22%22%0A        return timestamp.replace(microsecond=0, tzinfo=None)%0A%0A    @classmethod%0A    def make_token(cls, ephemeral_token):%0A        %22%22%22%0A        Returns a token to be used x number of times to allow a user account to access%0A        certain resource.%0A        %22%22%22%0A        created_at = cls.clean_timestamp(ephemeral_token.created_at)%0A        value = str(created_at) + ephemeral_token.uuid.hex%0A        if ephemeral_token.scope:%0A            value += ''.join(ephemeral_token.scope)%0A%0A        return get_hmac(cls.KEY_SALT + ephemeral_token.salt.hex, value)%5B::2%5D%0A%0A    @classmethod%0A    def is_timed_out(cls, ephemeral_token):%0A        %22%22%22%0A        Check that if a token is timed out.%0A        %22%22%22%0A        return (timezone.now() - ephemeral_token.created_at).seconds %3E ephemeral_token.ttl%0A%0A    @classmethod%0A    def check_token(cls, ephemeral_token, token):%0A        %22%22%22%0A        Check that a token is correct for a given scope token.%0A        %22%22%22%0A        ephemeral_token.num_uses -= 1%0A%0A        if ephemeral_token.num_uses %3C 0:%0A            ephemeral_token.delete()%0A            return False%0A%0A        if cls.is_timed_out(ephemeral_token):%0A            ephemeral_token.delete()%0A            return False%0A%0A        correct_token = cls.make_token(ephemeral_token)%0A%0A        if ephemeral_token.num_uses %3C= 0:%0A            ephemeral_token.delete()%0A        else:%0A            ephemeral_token.save()%0A%0A        return constant_time_compare(correct_token, token)%0A%0A    @classmethod%0A    def create_header_token(cls, ephemeral_token):%0A        token = cls.make_token(ephemeral_token)%0A        return base64.b64encode(%0A            '%7B%7DXEPH:%7B%7D'.format(token, ephemeral_token.uuid.hex).encode('utf-8')).decode(%22utf-8%22)%0A%0A    @staticmethod%0A    def get_scope(username, model, object_id):%0A        return %5B'username:%7B%7D'.format(username), '%7B%7D:%7B%7D'.format(model, object_id)%5D%0A

Add ephemeral token model