• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ephios-dev / ephios / 15171934576

21 May 2025 08:28PM UTC coverage: 84.143% (+0.1%) from 84.024%
15171934576

push

github

felixrindt
log participation comments

3108 of 3668 branches covered (84.73%)

Branch coverage included in aggregate %.

13 of 13 new or added lines in 2 files covered. (100.0%)

60 existing lines in 8 files now uncovered.

12456 of 14829 relevant lines covered (84.0%)

0.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.41
/ephios/api/models.py
1
from django.db import models
1✔
2
from django.urls import reverse
1✔
3
from django.utils import timezone
1✔
4
from django.utils.translation import gettext_lazy as _
1✔
5
from oauth2_provider.models import (
1✔
6
    AbstractAccessToken,
7
    AbstractApplication,
8
    AbstractGrant,
9
    AbstractIDToken,
10
    AbstractRefreshToken,
11
    ApplicationManager,
12
)
13

14
from ephios.modellogging.log import ModelFieldsLogConfig, dont_log, log
1✔
15

16

17
@log(
1✔
18
    ModelFieldsLogConfig(
19
        unlogged_fields={"id"},
20
        redacted_fields={"client_secret"},
21
    )
22
)
23
class Application(AbstractApplication):
1✔
24
    objects = ApplicationManager()
1✔
25

26
    class Meta(AbstractApplication.Meta):
1✔
27
        swappable = "OAUTH2_PROVIDER_APPLICATION_MODEL"
1✔
28

29
    def natural_key(self):
1✔
UNCOV
30
        return (self.client_id,)
×
31

32
    def get_absolute_url(self):
1✔
33
        return reverse("api:settings-oauth-app-detail", args=[str(self.id)])
1✔
34

35

36
@log(
1✔
37
    ModelFieldsLogConfig(
38
        unlogged_fields={"id"},
39
        redacted_fields={"token"},
40
    )
41
)
42
class AccessToken(AbstractAccessToken):
1✔
43
    class Meta(AbstractAccessToken.Meta):
1✔
44
        swappable = "OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL"
1✔
45

46
    description = models.CharField(
1✔
47
        verbose_name=_("Description"),
48
        blank=True,
49
        max_length=1000,
50
    )
51

52
    revoked = models.BooleanField(null=True)
1✔
53

54
    # make expires nullable for non-expiring personal API token
55
    expires = models.DateTimeField(
1✔
56
        null=True,
57
    )
58

59
    def is_expired(self):
1✔
60
        if not self.expires:
1!
61
            return False  # never expires
1✔
UNCOV
62
        return timezone.now() >= self.expires
×
63

64
    def is_valid(self, scopes=None):
1✔
65
        # expand super to include revoked check
66
        return not self.revoked and super().is_valid(scopes)
1✔
67

68
    def __str__(self):
1✔
69
        if self.application:
1!
UNCOV
70
            return _("Access Token") + f" #{self.id}"
×
71
        return _("Personal Token") + f" #{self.id}"
1✔
72

73
    def revoke_related(self):
1✔
74
        """
75
        Revoke this token and other types of related OAuth2 tokens.
76
        """
77
        try:
1✔
78
            # aquired from OAuth2 refresh token, so revoke that one (which will revoke this access token as well)
79
            self.refresh_token.revoke()
1✔
80
        except RefreshToken.DoesNotExist:
1✔
81
            # manually created token (?), so revoke it directly
82
            self.revoke()
1✔
83

84
    def revoke(self):
1✔
85
        if self.expires is not None:
1!
UNCOV
86
            self.expires = min(self.expires, timezone.now())
×
87
        else:
88
            self.expires = timezone.now()
1✔
89
        self.revoked = True
1✔
90
        self.save()
1✔
91

92

93
@dont_log
1✔
94
class RefreshToken(AbstractRefreshToken):
1✔
95
    class Meta(AbstractRefreshToken.Meta):
1✔
96
        swappable = "OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL"
1✔
97

98

99
@dont_log
1✔
100
class IDToken(AbstractIDToken):
1✔
101
    class Meta(AbstractIDToken.Meta):
1✔
102
        swappable = "OAUTH2_PROVIDER_ID_TOKEN_MODEL"
1✔
103

104

105
@dont_log
1✔
106
class Grant(AbstractGrant):
1✔
107
    class Meta(AbstractGrant.Meta):
1✔
108
        swappable = "OAUTH2_PROVIDER_GRANT_MODEL"
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc