diff --git a/crates/cli/src/commands/manage.rs b/crates/cli/src/commands/manage.rs index 60b94bfe..b6c0e465 100644 --- a/crates/cli/src/commands/manage.rs +++ b/crates/cli/src/commands/manage.rs @@ -18,7 +18,7 @@ use mas_config::{DatabaseConfig, PasswordsConfig, RootConfig}; use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod}; use mas_router::UrlBuilder; use mas_storage::{ - oauth2::client::{insert_client_from_config, lookup_client, truncate_clients}, + oauth2::client::{insert_client_from_config, lookup_client}, upstream_oauth2::UpstreamOAuthProviderRepository, user::{UserEmailRepository, UserPasswordRepository, UserRepository}, Clock, Repository, @@ -146,9 +146,9 @@ enum Subcommand { /// Import clients from config ImportClients { - /// Remove all clients before importing + /// Update existing clients #[arg(long)] - truncate: bool, + update: bool, }, /// Set a user password @@ -244,27 +244,28 @@ impl Options { Ok(()) } - SC::ImportClients { truncate } => { + SC::ImportClients { update } => { let config: RootConfig = root.load_config()?; let pool = database_from_config(&config.database).await?; let encrypter = config.secrets.encrypter(); let mut txn = pool.begin().await?; - if *truncate { - warn!("Removing all clients first"); - truncate_clients(&mut txn).await?; - } - for client in config.clients.iter() { let client_id = client.client_id; - let res = lookup_client(&mut txn, client_id).await?; - if res.is_some() { - warn!(%client_id, "Skipping already imported client"); + + let existing = lookup_client(&mut txn, client_id).await?.is_some(); + if !update && existing { + warn!(%client_id, "Skipping already imported client. Run with --update to update existing clients."); continue; } - info!(%client_id, "Importing client"); + if existing { + info!(%client_id, "Updating client"); + } else { + info!(%client_id, "Importing client"); + } + let client_secret = client.client_secret(); let client_auth_method = client.client_auth_method(); let jwks = client.jwks(); diff --git a/crates/storage/sqlx-data.json b/crates/storage/sqlx-data.json index 1676c69a..01036742 100644 --- a/crates/storage/sqlx-data.json +++ b/crates/storage/sqlx-data.json @@ -843,24 +843,6 @@ }, "query": "\n UPDATE oauth2_authorization_grants\n SET exchanged_at = $2\n WHERE oauth2_authorization_grant_id = $1\n " }, - "26a9391df9f1128673cdaf431fe8c5e4a83b576ddf7b02d92abfab6deadd4fa2": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Uuid", - "Text", - "Bool", - "Bool", - "Text", - "Jsonb", - "Text" - ] - } - }, - "query": "\n INSERT INTO oauth2_clients\n (oauth2_client_id,\n encrypted_client_secret,\n grant_type_authorization_code,\n grant_type_refresh_token,\n token_endpoint_auth_method,\n jwks,\n jwks_uri)\n VALUES\n ($1, $2, $3, $4, $5, $6, $7)\n " - }, "2e756fe7be50128c0acc5f79df3a084230e9ca13cd45bd0858f97e59da20006e": { "describe": { "columns": [], @@ -2119,6 +2101,24 @@ }, "query": "\n UPDATE users\n SET primary_user_email_id = user_emails.user_email_id\n FROM user_emails\n WHERE user_emails.user_email_id = $1\n AND users.user_id = user_emails.user_id\n " }, + "c0b4996085f6f2127e1e8cfdf18b9029c22096fadfe6de59dce01c789791edb5": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "Bool", + "Bool", + "Text", + "Jsonb", + "Text" + ] + } + }, + "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , grant_type_authorization_code\n , grant_type_refresh_token\n , token_endpoint_auth_method\n , jwks\n , jwks_uri\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7)\n ON CONFLICT (oauth2_client_id)\n DO\n UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret\n , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code\n , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token\n , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method\n , jwks = EXCLUDED.jwks\n , jwks_uri = EXCLUDED.jwks_uri\n " + }, "c1d90a7f2287ec779c81a521fab19e5ede3fa95484033e0312c30d9b6ecc03f0": { "describe": { "columns": [], @@ -2174,16 +2174,6 @@ }, "query": "\n INSERT INTO compat_sessions (compat_session_id, user_id, device_id, created_at)\n VALUES ($1, $2, $3, $4)\n " }, - "cb8ba981330e58a6c8580f6e394a721df110e1f2206e080434aa821c44c0164b": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [] - } - }, - "query": "TRUNCATE oauth2_client_redirect_uris, oauth2_clients CASCADE" - }, "cc9e30678d673546efca336ee8e550083eed71459611fa2db52264e51e175901": { "describe": { "columns": [], diff --git a/crates/storage/src/oauth2/client.rs b/crates/storage/src/oauth2/client.rs index 6138e377..164b0e80 100644 --- a/crates/storage/src/oauth2/client.rs +++ b/crates/storage/src/oauth2/client.rs @@ -481,15 +481,24 @@ pub async fn insert_client_from_config( sqlx::query!( r#" INSERT INTO oauth2_clients - (oauth2_client_id, - encrypted_client_secret, - grant_type_authorization_code, - grant_type_refresh_token, - token_endpoint_auth_method, - jwks, - jwks_uri) + ( oauth2_client_id + , encrypted_client_secret + , grant_type_authorization_code + , grant_type_refresh_token + , token_endpoint_auth_method + , jwks + , jwks_uri + ) VALUES ($1, $2, $3, $4, $5, $6, $7) + ON CONFLICT (oauth2_client_id) + DO + UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret + , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code + , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token + , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method + , jwks = EXCLUDED.jwks + , jwks_uri = EXCLUDED.jwks_uri "#, Uuid::from(client_id), encrypted_client_secret, @@ -529,10 +538,3 @@ pub async fn insert_client_from_config( Ok(()) } - -pub async fn truncate_clients(executor: impl PgExecutor<'_>) -> Result<(), sqlx::Error> { - sqlx::query!("TRUNCATE oauth2_client_redirect_uris, oauth2_clients CASCADE") - .execute(executor) - .await?; - Ok(()) -}