1
- use std:: process:: ExitCode ;
1
+ use std:: { collections :: HashMap , process:: ExitCode } ;
2
2
3
3
use anyhow:: Context ;
4
4
use camino:: Utf8PathBuf ;
5
5
use clap:: Parser ;
6
6
use figment:: Figment ;
7
- use mas_config:: { ConfigurationSection , ConfigurationSectionExt , DatabaseConfig , MatrixConfig } ;
7
+ use mas_config:: {
8
+ ConfigurationSection , ConfigurationSectionExt , DatabaseConfig , MatrixConfig , SyncConfig ,
9
+ UpstreamOAuth2Config ,
10
+ } ;
11
+ use mas_storage:: SystemClock ;
12
+ use mas_storage_pg:: MIGRATOR ;
8
13
use rand:: thread_rng;
9
- use sqlx:: { postgres:: PgConnectOptions , Connection , Either , PgConnection } ;
14
+ use sqlx:: { postgres:: PgConnectOptions , types :: Uuid , Connection , Either , PgConnection } ;
10
15
use syn2mas:: { synapse_config, LockedMasDatabase , MasWriter , SynapseReader } ;
11
- use tracing:: { error, warn} ;
16
+ use tracing:: { error, info_span , warn, Instrument } ;
12
17
13
18
use crate :: util:: database_connection_from_config;
14
19
@@ -75,6 +80,7 @@ enum Subcommand {
75
80
const NUM_WRITER_CONNECTIONS : usize = 8 ;
76
81
77
82
impl Options {
83
+ #[ allow( clippy:: too_many_lines) ]
78
84
pub async fn run ( self , figment : & Figment ) -> anyhow:: Result < ExitCode > {
79
85
warn ! ( "This version of the syn2mas tool is EXPERIMENTAL and INCOMPLETE. Do not use it, except for TESTING." ) ;
80
86
if !self . experimental_accepted {
@@ -107,6 +113,35 @@ impl Options {
107
113
108
114
let mut mas_connection = database_connection_from_config ( & config) . await ?;
109
115
116
+ MIGRATOR
117
+ . run ( & mut mas_connection)
118
+ . instrument ( info_span ! ( "db.migrate" ) )
119
+ . await
120
+ . context ( "could not run migrations" ) ?;
121
+
122
+ if matches ! ( & self . subcommand, Subcommand :: Migrate { .. } ) {
123
+ // First perform a config sync
124
+ // This is crucial to ensure we register upstream OAuth providers
125
+ // in the MAS database
126
+ //
127
+ let config = SyncConfig :: extract ( figment) ?;
128
+ let clock = SystemClock :: default ( ) ;
129
+ let encrypter = config. secrets . encrypter ( ) ;
130
+
131
+ crate :: sync:: config_sync (
132
+ config. upstream_oauth2 ,
133
+ config. clients ,
134
+ & mut mas_connection,
135
+ & encrypter,
136
+ & clock,
137
+ // Don't prune — we don't want to be unnecessarily destructive
138
+ false ,
139
+ // Not a dry run — we do want to create the providers in the database
140
+ false ,
141
+ )
142
+ . await ?;
143
+ }
144
+
110
145
let Either :: Left ( mut mas_connection) = LockedMasDatabase :: try_new ( & mut mas_connection)
111
146
. await
112
147
. context ( "failed to issue query to lock database" ) ?
@@ -166,6 +201,19 @@ impl Options {
166
201
Ok ( ExitCode :: SUCCESS )
167
202
}
168
203
Subcommand :: Migrate => {
204
+ let provider_id_mappings: HashMap < String , Uuid > = {
205
+ let mas_oauth2 = UpstreamOAuth2Config :: extract_or_default ( figment) ?;
206
+
207
+ mas_oauth2
208
+ . providers
209
+ . iter ( )
210
+ . filter_map ( |provider| {
211
+ let synapse_idp_id = provider. synapse_idp_id . clone ( ) ?;
212
+ Some ( ( synapse_idp_id, Uuid :: from ( provider. id ) ) )
213
+ } )
214
+ . collect ( )
215
+ } ;
216
+
169
217
// TODO how should we handle warnings at this stage?
170
218
171
219
let mut reader = SynapseReader :: new ( & mut syn_conn, true ) . await ?;
@@ -181,8 +229,14 @@ impl Options {
181
229
182
230
// TODO progress reporting
183
231
let mas_matrix = MatrixConfig :: extract ( figment) ?;
184
- syn2mas:: migrate ( & mut reader, & mut writer, & mas_matrix. homeserver , & mut rng)
185
- . await ?;
232
+ syn2mas:: migrate (
233
+ & mut reader,
234
+ & mut writer,
235
+ & mas_matrix. homeserver ,
236
+ & mut rng,
237
+ & provider_id_mappings,
238
+ )
239
+ . await ?;
186
240
187
241
reader. finish ( ) . await ?;
188
242
writer. finish ( ) . await ?;
0 commit comments