@@ -74,6 +74,7 @@ bitflags::bitflags! {
7474 const IS_SYNAPSE_ADMIN = 0b0000_0001 ;
7575 const IS_DEACTIVATED = 0b0000_0010 ;
7676 const IS_GUEST = 0b0000_0100 ;
77+ const IS_APPSERVICE = 0b0000_1000 ;
7778 }
7879}
7980
@@ -89,6 +90,10 @@ impl UserFlags {
8990 const fn is_synapse_admin ( self ) -> bool {
9091 self . contains ( UserFlags :: IS_SYNAPSE_ADMIN )
9192 }
93+
94+ const fn is_appservice ( self ) -> bool {
95+ self . contains ( UserFlags :: IS_APPSERVICE )
96+ }
9297}
9398
9499#[ derive( Debug , Clone , Copy ) ]
@@ -177,6 +182,20 @@ async fn migrate_users(
177182 if bool:: from ( user. is_guest ) {
178183 flags |= UserFlags :: IS_GUEST ;
179184 }
185+ if user. appservice_id . is_some ( ) {
186+ flags |= UserFlags :: IS_APPSERVICE ;
187+
188+ // Special case for appservice users: we don't insert them into the database
189+ // We just record the user's information in the state and continue
190+ state. users . insert (
191+ CompactString :: new ( & mas_user. username ) ,
192+ UserInfo {
193+ mas_user_id : Uuid :: nil ( ) ,
194+ flags,
195+ } ,
196+ ) ;
197+ continue ;
198+ }
180199
181200 state. users . insert (
182201 CompactString :: new ( & mas_user. username ) ,
@@ -233,15 +252,16 @@ async fn migrate_threepids(
233252 . into_extract_localpart ( synapse_user_id. clone ( ) ) ?
234253 . to_owned ( ) ;
235254 let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
236- if is_likely_appservice ( & username) {
237- continue ;
238- }
239255 return Err ( Error :: MissingUserFromDependentTable {
240256 table : "user_threepids" . to_owned ( ) ,
241257 user : synapse_user_id,
242258 } ) ;
243259 } ;
244260
261+ if user_infos. flags . is_appservice ( ) {
262+ continue ;
263+ }
264+
245265 if medium == "email" {
246266 email_buffer
247267 . write (
@@ -311,15 +331,16 @@ async fn migrate_external_ids(
311331 . into_extract_localpart ( synapse_user_id. clone ( ) ) ?
312332 . to_owned ( ) ;
313333 let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
314- if is_likely_appservice ( & username) {
315- continue ;
316- }
317334 return Err ( Error :: MissingUserFromDependentTable {
318335 table : "user_external_ids" . to_owned ( ) ,
319336 user : synapse_user_id,
320337 } ) ;
321338 } ;
322339
340+ if user_infos. flags . is_appservice ( ) {
341+ continue ;
342+ }
343+
323344 let Some ( & upstream_provider_id) = state. provider_id_mapping . get ( & auth_provider) else {
324345 return Err ( Error :: MissingAuthProviderMapping {
325346 synapse_id : auth_provider,
@@ -389,16 +410,16 @@ async fn migrate_devices(
389410 . into_extract_localpart ( synapse_user_id. clone ( ) ) ?
390411 . to_owned ( ) ;
391412 let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
392- if is_likely_appservice ( & username) {
393- continue ;
394- }
395413 return Err ( Error :: MissingUserFromDependentTable {
396414 table : "devices" . to_owned ( ) ,
397415 user : synapse_user_id,
398416 } ) ;
399417 } ;
400418
401- if user_infos. flags . is_deactivated ( ) || user_infos. flags . is_guest ( ) {
419+ if user_infos. flags . is_deactivated ( )
420+ || user_infos. flags . is_guest ( )
421+ || user_infos. flags . is_appservice ( )
422+ {
402423 continue ;
403424 }
404425
@@ -483,16 +504,16 @@ async fn migrate_unrefreshable_access_tokens(
483504 . into_extract_localpart ( synapse_user_id. clone ( ) ) ?
484505 . to_owned ( ) ;
485506 let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
486- if is_likely_appservice ( & username) {
487- continue ;
488- }
489507 return Err ( Error :: MissingUserFromDependentTable {
490508 table : "access_tokens" . to_owned ( ) ,
491509 user : synapse_user_id,
492510 } ) ;
493511 } ;
494512
495- if user_infos. flags . is_deactivated ( ) || user_infos. flags . is_guest ( ) {
513+ if user_infos. flags . is_deactivated ( )
514+ || user_infos. flags . is_guest ( )
515+ || user_infos. flags . is_appservice ( )
516+ {
496517 continue ;
497518 }
498519
@@ -595,16 +616,16 @@ async fn migrate_refreshable_token_pairs(
595616 . into_extract_localpart ( synapse_user_id. clone ( ) ) ?
596617 . to_owned ( ) ;
597618 let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
598- if is_likely_appservice ( & username) {
599- continue ;
600- }
601619 return Err ( Error :: MissingUserFromDependentTable {
602620 table : "refresh_tokens" . to_owned ( ) ,
603621 user : synapse_user_id,
604622 } ) ;
605623 } ;
606624
607- if user_infos. flags . is_deactivated ( ) || user_infos. flags . is_guest ( ) {
625+ if user_infos. flags . is_deactivated ( )
626+ || user_infos. flags . is_guest ( )
627+ || user_infos. flags . is_appservice ( )
628+ {
608629 continue ;
609630 }
610631
@@ -701,15 +722,3 @@ fn transform_user(
701722
702723 Ok ( ( new_user, mas_password) )
703724}
704-
705- /// Returns true if and only if the given localpart looks like it would belong
706- /// to an application service user.
707- /// The rule here is that it must start with an underscore.
708- /// Synapse reserves these by default, but there is no hard rule prohibiting
709- /// other namespaces from being reserved, so this is not a robust check.
710- // TODO replace with a more robust mechanism, if we even care about this sanity check
711- // e.g. read application service registration files.
712- #[ inline]
713- fn is_likely_appservice ( localpart : & str ) -> bool {
714- localpart. starts_with ( '_' )
715- }
0 commit comments