@@ -74,6 +74,7 @@ bitflags::bitflags! {
74
74
const IS_SYNAPSE_ADMIN = 0b0000_0001 ;
75
75
const IS_DEACTIVATED = 0b0000_0010 ;
76
76
const IS_GUEST = 0b0000_0100 ;
77
+ const IS_APPSERVICE = 0b0000_1000 ;
77
78
}
78
79
}
79
80
@@ -89,6 +90,10 @@ impl UserFlags {
89
90
const fn is_synapse_admin ( self ) -> bool {
90
91
self . contains ( UserFlags :: IS_SYNAPSE_ADMIN )
91
92
}
93
+
94
+ const fn is_appservice ( self ) -> bool {
95
+ self . contains ( UserFlags :: IS_APPSERVICE )
96
+ }
92
97
}
93
98
94
99
#[ derive( Debug , Clone , Copy ) ]
@@ -188,6 +193,20 @@ async fn migrate_users(
188
193
if bool:: from ( user. is_guest ) {
189
194
flags |= UserFlags :: IS_GUEST ;
190
195
}
196
+ if user. appservice_id . is_some ( ) {
197
+ flags |= UserFlags :: IS_APPSERVICE ;
198
+
199
+ // Special case for appservice users: we don't insert them into the database
200
+ // We just record the user's information in the state and continue
201
+ state. users . insert (
202
+ CompactString :: new ( & mas_user. username ) ,
203
+ UserInfo {
204
+ mas_user_id : Uuid :: nil ( ) ,
205
+ flags,
206
+ } ,
207
+ ) ;
208
+ continue ;
209
+ }
191
210
192
211
state. users . insert (
193
212
CompactString :: new ( & mas_user. username ) ,
@@ -247,15 +266,16 @@ async fn migrate_threepids(
247
266
. into_extract_localpart ( synapse_user_id. clone ( ) ) ?
248
267
. to_owned ( ) ;
249
268
let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
250
- if is_likely_appservice ( & username) {
251
- continue ;
252
- }
253
269
return Err ( Error :: MissingUserFromDependentTable {
254
270
table : "user_threepids" . to_owned ( ) ,
255
271
user : synapse_user_id,
256
272
} ) ;
257
273
} ;
258
274
275
+ if user_infos. flags . is_appservice ( ) {
276
+ continue ;
277
+ }
278
+
259
279
if medium == "email" {
260
280
email_buffer
261
281
. write (
@@ -325,15 +345,16 @@ async fn migrate_external_ids(
325
345
. into_extract_localpart ( synapse_user_id. clone ( ) ) ?
326
346
. to_owned ( ) ;
327
347
let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
328
- if is_likely_appservice ( & username) {
329
- continue ;
330
- }
331
348
return Err ( Error :: MissingUserFromDependentTable {
332
349
table : "user_external_ids" . to_owned ( ) ,
333
350
user : synapse_user_id,
334
351
} ) ;
335
352
} ;
336
353
354
+ if user_infos. flags . is_appservice ( ) {
355
+ continue ;
356
+ }
357
+
337
358
let Some ( & upstream_provider_id) = state. provider_id_mapping . get ( & auth_provider) else {
338
359
return Err ( Error :: MissingAuthProviderMapping {
339
360
synapse_id : auth_provider,
@@ -403,16 +424,16 @@ async fn migrate_devices(
403
424
. into_extract_localpart ( synapse_user_id. clone ( ) ) ?
404
425
. to_owned ( ) ;
405
426
let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
406
- if is_likely_appservice ( & username) {
407
- continue ;
408
- }
409
427
return Err ( Error :: MissingUserFromDependentTable {
410
428
table : "devices" . to_owned ( ) ,
411
429
user : synapse_user_id,
412
430
} ) ;
413
431
} ;
414
432
415
- if user_infos. flags . is_deactivated ( ) || user_infos. flags . is_guest ( ) {
433
+ if user_infos. flags . is_deactivated ( )
434
+ || user_infos. flags . is_guest ( )
435
+ || user_infos. flags . is_appservice ( )
436
+ {
416
437
continue ;
417
438
}
418
439
@@ -428,7 +449,9 @@ async fn migrate_devices(
428
449
// As we're using a real IP type in the MAS database, it is possible
429
450
// that we encounter invalid IP addresses in the Synapse database.
430
451
// In that case, we should ignore them, but still log a warning.
431
- let last_active_ip = ip. and_then ( |ip| {
452
+ // One special case: Synapse will record '-' as IP in some cases, we don't want
453
+ // to log about those
454
+ let last_active_ip = ip. filter ( |ip| ip != "-" ) . and_then ( |ip| {
432
455
ip. parse ( )
433
456
. map_err ( |e| {
434
457
tracing:: warn!(
@@ -497,16 +520,16 @@ async fn migrate_unrefreshable_access_tokens(
497
520
. into_extract_localpart ( synapse_user_id. clone ( ) ) ?
498
521
. to_owned ( ) ;
499
522
let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
500
- if is_likely_appservice ( & username) {
501
- continue ;
502
- }
503
523
return Err ( Error :: MissingUserFromDependentTable {
504
524
table : "access_tokens" . to_owned ( ) ,
505
525
user : synapse_user_id,
506
526
} ) ;
507
527
} ;
508
528
509
- if user_infos. flags . is_deactivated ( ) || user_infos. flags . is_guest ( ) {
529
+ if user_infos. flags . is_deactivated ( )
530
+ || user_infos. flags . is_guest ( )
531
+ || user_infos. flags . is_appservice ( )
532
+ {
510
533
continue ;
511
534
}
512
535
@@ -609,16 +632,16 @@ async fn migrate_refreshable_token_pairs(
609
632
. into_extract_localpart ( synapse_user_id. clone ( ) ) ?
610
633
. to_owned ( ) ;
611
634
let Some ( user_infos) = state. users . get ( username. as_str ( ) ) . copied ( ) else {
612
- if is_likely_appservice ( & username) {
613
- continue ;
614
- }
615
635
return Err ( Error :: MissingUserFromDependentTable {
616
636
table : "refresh_tokens" . to_owned ( ) ,
617
637
user : synapse_user_id,
618
638
} ) ;
619
639
} ;
620
640
621
- if user_infos. flags . is_deactivated ( ) || user_infos. flags . is_guest ( ) {
641
+ if user_infos. flags . is_deactivated ( )
642
+ || user_infos. flags . is_guest ( )
643
+ || user_infos. flags . is_appservice ( )
644
+ {
622
645
continue ;
623
646
}
624
647
@@ -715,15 +738,3 @@ fn transform_user(
715
738
716
739
Ok ( ( new_user, mas_password) )
717
740
}
718
-
719
- /// Returns true if and only if the given localpart looks like it would belong
720
- /// to an application service user.
721
- /// The rule here is that it must start with an underscore.
722
- /// Synapse reserves these by default, but there is no hard rule prohibiting
723
- /// other namespaces from being reserved, so this is not a robust check.
724
- // TODO replace with a more robust mechanism, if we even care about this sanity check
725
- // e.g. read application service registration files.
726
- #[ inline]
727
- fn is_likely_appservice ( localpart : & str ) -> bool {
728
- localpart. starts_with ( '_' )
729
- }
0 commit comments