@@ -154,20 +154,22 @@ pub(crate) async fn post(
154154 state. add_error_on_form ( FormError :: Captcha ) ;
155155 }
156156
157+ let mut homeserver_denied_username = false ;
157158 if form. username . is_empty ( ) {
158159 state. add_error_on_field ( RegisterFormField :: Username , FieldError :: Required ) ;
159160 } else if repo. user ( ) . exists ( & form. username ) . await ? {
160161 // The user already exists in the database
161162 state. add_error_on_field ( RegisterFormField :: Username , FieldError :: Exists ) ;
162163 } else if !homeserver. is_localpart_available ( & form. username ) . await ? {
163164 // The user already exists on the homeserver
164- // XXX: we may want to return different errors like "this username is reserved"
165165 tracing:: warn!(
166166 username = & form. username,
167- "User tried to register with a reserved username "
167+ "Homeserver denied username provided by user "
168168 ) ;
169169
170- state. add_error_on_field ( RegisterFormField :: Username , FieldError :: Exists ) ;
170+ // We defer adding the error on the field, until we know whether we had another
171+ // error from the policy, to avoid showing both
172+ homeserver_denied_username = true ;
171173 }
172174
173175 if form. email . is_empty ( ) {
@@ -197,6 +199,7 @@ pub(crate) async fn post(
197199 state. add_error_on_field (
198200 RegisterFormField :: Password ,
199201 FieldError :: Policy {
202+ code : None ,
200203 message : "Password is too weak" . to_owned ( ) ,
201204 } ,
202205 ) ;
@@ -216,27 +219,41 @@ pub(crate) async fn post(
216219 Some ( "email" ) => state. add_error_on_field (
217220 RegisterFormField :: Email ,
218221 FieldError :: Policy {
222+ code : violation. code . map ( |c| c. as_str ( ) ) ,
219223 message : violation. msg ,
220224 } ,
221225 ) ,
222- Some ( "username" ) => state. add_error_on_field (
223- RegisterFormField :: Username ,
224- FieldError :: Policy {
225- message : violation. msg ,
226- } ,
227- ) ,
226+ Some ( "username" ) => {
227+ // If the homeserver denied the username, but we also had an error on the policy
228+ // side, we don't want to show both, so we reset the state here
229+ homeserver_denied_username = false ;
230+ state. add_error_on_field (
231+ RegisterFormField :: Username ,
232+ FieldError :: Policy {
233+ code : violation. code . map ( |c| c. as_str ( ) ) ,
234+ message : violation. msg ,
235+ } ,
236+ ) ;
237+ }
228238 Some ( "password" ) => state. add_error_on_field (
229239 RegisterFormField :: Password ,
230240 FieldError :: Policy {
241+ code : violation. code . map ( |c| c. as_str ( ) ) ,
231242 message : violation. msg ,
232243 } ,
233244 ) ,
234245 _ => state. add_error_on_form ( FormError :: Policy {
246+ code : violation. code . map ( |c| c. as_str ( ) ) ,
235247 message : violation. msg ,
236248 } ) ,
237249 }
238250 }
239251
252+ if homeserver_denied_username {
253+ // XXX: we may want to return different errors like "this username is reserved"
254+ state. add_error_on_field ( RegisterFormField :: Username , FieldError :: Exists ) ;
255+ }
256+
240257 if state. is_valid ( ) {
241258 // Check the rate limit if we are about to process the form
242259 if let Err ( e) = limiter. check_registration ( requester) {
0 commit comments