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

mozilla / fx-private-relay / d3128616-238d-446e-82c5-ab66cd38ceaf

09 May 2024 06:22PM UTC coverage: 84.07% (-0.6%) from 84.64%
d3128616-238d-446e-82c5-ab66cd38ceaf

push

circleci

web-flow
Merge pull request #4684 from mozilla/enable-flak8-bandit-checks-mpp-3802

fix MPP-3802: stop ignoring bandit security checks

3601 of 4734 branches covered (76.07%)

Branch coverage included in aggregate %.

74 of 158 new or added lines in 24 files covered. (46.84%)

5 existing lines in 5 files now uncovered.

14686 of 17018 relevant lines covered (86.3%)

10.86 hits per line

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

83.61
/api/exceptions.py
1
from __future__ import annotations
1✔
2

3
from typing import TYPE_CHECKING, Any, TypedDict
1✔
4

5
from rest_framework import status
1✔
6
from rest_framework.exceptions import APIException
1✔
7

8
from privaterelay.ftl_bundles import main as ftl_bundle
1✔
9

10
if TYPE_CHECKING:
11
    # Provided by djangorestframework-stubs
12
    # https://github.com/typeddjango/djangorestframework-stubs/blob/master/rest_framework-stubs/exceptions.pyi
13
    from rest_framework.exceptions import _APIExceptionInput
14

15

16
class ConflictError(APIException):
1✔
17
    status_code = status.HTTP_409_CONFLICT
1✔
18
    default_detail = "Request conflicts with current state of the target resource."
1✔
19
    default_code = "conflict_error"
1✔
20

21

22
ErrorContextType = dict[str, int | str]
1✔
23

24

25
class OptionalErrorData(TypedDict, total=False):
1✔
26
    error_context: ErrorContextType
1✔
27

28

29
class ErrorData(OptionalErrorData):
1✔
30
    detail: str
1✔
31
    error_code: str | list[Any] | dict[str, Any] | None
1✔
32

33

34
class RelayAPIException(APIException):
1✔
35
    """
36
    Base class for exceptions that may be returned through the API.
37

38
    Derived classes should set `default_code` to a unique string identifying the
39
    exception. There should be a matching Fluent string with an `api-error-`
40
    prefix. For example, the Fluent string "api-error-free-tier-limit" matches
41
    the exception class with the default_code "free-tier-limit". These Fluent
42
    strings are in misc.ftl.
43

44
    Derived classes can set `default_detail` to a human-readable string, or they
45
    can set `default_detail_template` to dynamically create the string from extra
46
    context. When using default_detail_template, the Fluent string should use the same
47
    variable names.
48

49
    Derived classes can set `status_code` to the HTTP status code, or accept the
50
    APIException default of 500 for a Server Error.
51
    """
52

53
    default_code: str
1✔
54
    default_detail: str
1✔
55
    status_code: int
1✔
56

57
    def __init__(
1✔
58
        self, detail: _APIExceptionInput = None, code: str | None = None
59
    ) -> None:
60
        """Check that derived classes have set the required data."""
61
        if not isinstance(self.default_code, str):
1!
NEW
62
            raise TypeError("default_code must be type str")
×
63
        if not isinstance(self.status_code, int):
1!
NEW
64
            raise TypeError("self.status_code must be type int")
×
65
        if hasattr(self, "default_detail_template"):
1✔
66
            context = self.error_context()
1✔
67
            if not context:
1!
NEW
68
                raise ValueError("error_context is required")
×
69
            self.default_detail = self.default_detail_template.format(**context)
1✔
70
        if not isinstance(self.default_detail, str):
1!
NEW
71
            raise TypeError("self.default_detail must be type str")
×
72
        super().__init__(detail, code)
1✔
73

74
    def error_context(self) -> ErrorContextType:
1✔
75
        """Return context variables for client-side translation."""
76
        return {}
1✔
77

78
    def error_data(self) -> ErrorData:
1✔
79
        """Return extra data for API error responses."""
80

81
        # For RelayAPIException classes, this is the default_code and is a string
82
        error_code = self.get_codes()
1✔
83
        if not isinstance(error_code, str):
1!
NEW
84
            raise TypeError("error_code must be type str")
×
85

86
        # Build the Fluent error ID
87
        ftl_id_sub = "api-error-"
1✔
88
        ftl_id_error = error_code.replace("_", "-")
1✔
89
        ftl_id = ftl_id_sub + ftl_id_error
1✔
90

91
        # Replace the default message with the translated Fluent string
92
        error_context = self.error_context()
1✔
93
        translated_detail = ftl_bundle.format(ftl_id, error_context)
1✔
94

95
        error_data = ErrorData(detail=translated_detail, error_code=error_code)
1✔
96
        if error_context:
1✔
97
            error_data["error_context"] = error_context
1✔
98
        return error_data
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