-
Notifications
You must be signed in to change notification settings - Fork 442
/
Copy pathgroup.py
139 lines (106 loc) · 4.5 KB
/
group.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Schema for validating API group resources."""
from h.i18n import TranslationString as _
from h.models.group import (
GROUP_DESCRIPTION_MAX_LENGTH,
GROUP_NAME_MAX_LENGTH,
GROUP_NAME_MIN_LENGTH,
)
from h.schemas.base import JSONSchema, ValidationError
from h.util.group import GROUPID_PATTERN, split_groupid
GROUP_SCHEMA_PROPERTIES = {
"name": {
"type": "string",
"minLength": GROUP_NAME_MIN_LENGTH,
"maxLength": GROUP_NAME_MAX_LENGTH,
},
"description": {"type": "string", "maxLength": GROUP_DESCRIPTION_MAX_LENGTH},
"groupid": {"type": "string", "pattern": GROUPID_PATTERN},
"type": {"enum": ["private", "restricted", "open"]},
"pre_moderated": {"type": "boolean"},
}
class GroupAPISchema(JSONSchema):
"""Base class for validating group resource API data."""
schema = {"type": "object", "properties": GROUP_SCHEMA_PROPERTIES} # noqa: RUF012
def __init__(self, group_authority=None, default_authority=None):
"""
Initialize a new group schema instance.
The ``group_authority`` and ``default_authority`` args are used for
validating any ``groupid`` present in the data being validated.
:arg group_authority: The authority associated with the group resource.
(default None)
:arg default_authority: The service's default authority (default None)
"""
super().__init__()
self.group_authority = group_authority
self.default_authority = default_authority
def validate(self, data):
"""
Validate against the JSON schema and also valid any ``groupid`` present.
:raise h.schemas.ValidationError: if any part of validation fails
:return: The validated data
:rtype: dict
"""
appstruct = super().validate(data)
appstruct = self._whitelisted_fields_only(appstruct)
self._validate_name(appstruct)
self._validate_groupid(appstruct)
return appstruct
def _validate_name(self, appstruct):
name = appstruct.get("name")
if name and name.strip() != name:
raise ValidationError( # noqa: TRY003
"Group names can't have leading or trailing whitespace." # noqa: EM101
)
def _validate_groupid(self, appstruct):
"""
Validate the ``groupid`` to make sure it adheres to authority restrictions.
``groupid`` is only allowed if the authority of the group associated
with it is not the default authority—i.e. this is a third-party group.
:arg appstruct: Data, which may or may not contain a ``groupid`` entry
:type appstruct: dict
:raise h.schemas.ValidationError:
"""
groupid = appstruct.get("groupid", None)
if groupid is None: # Nothing to validate
return
if (self.group_authority is None) or (
self.group_authority == self.default_authority
):
# This is a first-party group
raise ValidationError(
"{err_msg} '{authority}'".format( # noqa: EM103
err_msg=_(
"groupid may only be set on groups outside of the default authority"
),
authority=self.default_authority,
)
)
groupid_parts = split_groupid(groupid)
if groupid_parts["authority"] != self.group_authority:
# The authority part of the ``groupid`` doesn't match the
# group's authority
raise ValidationError(
"{err_msg} '{groupid}'".format( # noqa: EM103
err_msg=_("Invalid authority specified in groupid"), groupid=groupid
)
)
@staticmethod
def _whitelisted_fields_only(appstruct):
"""Return a new appstruct containing only schema-defined fields."""
new_appstruct = {}
for allowed_field in GROUP_SCHEMA_PROPERTIES:
if allowed_field in appstruct:
new_appstruct[allowed_field] = appstruct[allowed_field]
return new_appstruct
class CreateGroupAPISchema(GroupAPISchema):
"""Schema for validating create-group API data."""
schema = { # noqa: RUF012
"type": "object",
"properties": GROUP_SCHEMA_PROPERTIES,
"required": ["name"], # ``name`` is a required field when creating
}
class UpdateGroupAPISchema(GroupAPISchema):
"""
Class for validating update-group API data.
Currently identical to base schema
"""