@@ -17,7 +17,7 @@ class UserId(str):
17
17
"""
18
18
A Checkmk user ID
19
19
20
- UserIds must comply to a restricted set of allowed characters (see UserId.validate ).
20
+ UserIds must comply to a restricted set of allowed characters (see UserId.validate_userid ).
21
21
22
22
UserIds must either be compatible with all protocols and components we interface with, or we
23
23
must ensure proper encoding whenever UserIds leave Checkmk.
@@ -62,93 +62,96 @@ def __get_pydantic_core_schema__(
62
62
cls , source_type : Any , _handler : GetCoreSchemaHandler
63
63
) -> core_schema .CoreSchema :
64
64
return core_schema .no_info_after_validator_function (
65
- cls . validate_userid ,
65
+ cls ,
66
66
core_schema .union_schema (
67
67
[core_schema .str_schema (), core_schema .is_instance_schema (cls )]
68
68
),
69
69
serialization = core_schema .to_string_ser_schema (),
70
70
)
71
71
72
- @classmethod
73
- def validate (cls , text : str ) -> None :
74
- """Check if it is a valid UserId
72
+ def __new__ (cls , text : str ) -> UserId :
73
+ """Construct a new UserId object
75
74
76
75
UserIds are used in a variety of contexts, including HTML, file paths and other external
77
76
systems. Currently we have no means of ensuring proper output encoding wherever UserIds
78
77
are used. Thus, we strictly limit the characters that can be used in a UserId.
79
78
80
79
See class docstring for an incomplete list of places where UserIds are processed.
81
80
82
- Examples:
81
+ Raises:
82
+ - ValueError: whenever the given text contains special characters.
83
83
84
+ Examples:
84
85
The empty UserId is allowed for historical reasons (see `UserId.builtin`).
85
86
86
- >>> UserId.validate("")
87
+ >>> UserId("")
88
+ ''
87
89
88
90
ASCII letters, digits, and selected special characters are allowed.
89
91
90
- >>> UserId.validate("cmkadmin")
91
- >>> UserId.validate("$cmk_@dmün.1")
92
+ >>> UserId("cmkadmin")
93
+ 'cmkadmin'
94
+
95
+ >>> UserId("$cmk_@dmün.1")
96
+ '$cmk_@dmün.1'
92
97
93
98
Anything considered a letter in Unicode and the dollar sign is allowed.
94
99
95
- >>> UserId.validate("cmkadmin")
96
- >>> UserId.validate("$cmkädmin")
97
- >>> UserId.validate("ↄ𝒽ѥ𝕔𖹬-艋く")
100
+ >>> UserId("$cmkädmin")
101
+ '$cmkädmin'
102
+
103
+ >>> UserId("ↄ𝒽ѥ𝕔𖹬-艋く")
104
+ 'ↄ𝒽ѥ𝕔𖹬-艋く'
98
105
99
106
Emails are allowed
100
107
101
- >>> UserId.validate("[email protected] ")
102
- >>> UserId.validate("[email protected] ")
108
+
109
+
110
+
111
+
112
+
103
113
104
114
Special characters other than '$_-@.' are not allowed (see `USER_ID_REGEX`).
105
115
106
- >>> UserId.validate ("foo/../")
116
+ >>> UserId("foo/../")
107
117
Traceback (most recent call last):
108
118
...
109
- ValueError: Invalid username: 'foo/../'
119
+ ValueError: invalid username: 'foo/../'
110
120
111
- >>> UserId.validate ("%2F")
121
+ >>> UserId("%2F")
112
122
Traceback (most recent call last):
113
123
...
114
- ValueError: Invalid username: '%2F'
124
+ ValueError: invalid username: '%2F'
115
125
116
126
Some special characters are not allowed at the start.
117
127
118
- >>> UserId.validate (".")
128
+ >>> UserId(".")
119
129
Traceback (most recent call last):
120
130
...
121
- ValueError: Invalid username: '.'
131
+ ValueError: invalid username: '.'
122
132
123
- >>> UserId.validate ("@example.com")
133
+ >>> UserId("@example.com")
124
134
Traceback (most recent call last):
125
135
...
126
- ValueError: Invalid username: '@example.com'
136
+ ValueError: invalid username: '@example.com'
127
137
128
138
UserIds must not be longer than 255 bytes.
129
139
130
- >>> UserId.validate("𐌈")
131
- >>> UserId.validate(64*"𐌈")
140
+ >>> UserId("𐌈")
141
+ '𐌈'
142
+
143
+ >>> UserId(64*"𐌈")
132
144
Traceback (most recent call last):
133
145
...
134
- ValueError: Username too long: '𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈…'
146
+ ValueError: username too long: '𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈𐌈…'
135
147
"""
136
- cls .validate_userid (text )
137
-
138
- @classmethod
139
- def validate_userid (cls , text : str ) -> str :
140
- if not text :
141
- # see UserId.builtin
142
- return ""
143
-
148
+ # Ext4 and other file systems allow filenames of up to 255 bytes.
144
149
if len (bytes (text , encoding = "utf-8" )) > 255 :
145
- # ext4 and others allow filenames of up to 255 bytes
146
- raise ValueError (f"Username too long: { text [:16 ] + '…' !r} " )
147
-
148
- if not cls .USER_ID_REGEX .match (text ):
149
- raise ValueError (f"Invalid username: { text !r} " )
150
-
151
- return text
150
+ raise ValueError (f"username too long: { text [:16 ] + '…' !r} " )
151
+ # For the empty case, see UserId.builtin().
152
+ if text and not cls .USER_ID_REGEX .match (text ):
153
+ raise ValueError (f"invalid username: { text !r} " )
154
+ return super ().__new__ (cls , text )
152
155
153
156
@classmethod
154
157
def builtin (cls ) -> UserId :
@@ -161,12 +164,3 @@ def builtin(cls) -> UserId:
161
164
with a different meaning.
162
165
"""
163
166
return UserId ("" )
164
-
165
- def __new__ (cls , text : str ) -> UserId :
166
- """Construct a new UserId object
167
-
168
- Raises:
169
- - ValueError: whenever the given text contains special characters. See `validate`.
170
- """
171
- cls .validate (text )
172
- return super ().__new__ (cls , text )
0 commit comments