Skip to content

Commit 5f47039

Browse files
committed
Allow setting an explicit upstream account name
1 parent 2c01b43 commit 5f47039

File tree

21 files changed

+279
-146
lines changed

21 files changed

+279
-146
lines changed

crates/cli/src/commands/manage.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,9 +955,10 @@ impl UserCreationRequest<'_> {
955955
}
956956

957957
for (provider, subject) in upstream_provider_mappings {
958+
// Note that we don't pass a human_account_name here, as we don't ask for it
958959
let link = repo
959960
.upstream_oauth_link()
960-
.add(rng, clock, provider, subject)
961+
.add(rng, clock, provider, subject, None)
961962
.await?;
962963

963964
repo.upstream_oauth_link()

crates/cli/src/sync.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ fn map_claims_imports(
6767
mas_data_model::UpsreamOAuthProviderSetEmailVerification::Import
6868
}
6969
},
70+
account_name: mas_data_model::UpstreamOAuthProviderSubjectPreference {
71+
template: config.account_name.template.clone(),
72+
},
7073
}
7174
}
7275

crates/config/src/sections/upstream_oauth2.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,23 @@ impl EmailImportPreference {
285285
}
286286
}
287287

288+
/// What should be done for the account name attribute
289+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)]
290+
pub struct AccountNameImportPreference {
291+
/// The Jinja2 template to use for the account name. This name is only used
292+
/// for display purposes.
293+
///
294+
/// If not provided, it will be ignored.
295+
#[serde(default, skip_serializing_if = "Option::is_none")]
296+
pub template: Option<String>,
297+
}
298+
299+
impl AccountNameImportPreference {
300+
const fn is_default(&self) -> bool {
301+
self.template.is_none()
302+
}
303+
}
304+
288305
/// How claims should be imported
289306
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, JsonSchema)]
290307
pub struct ClaimsImports {
@@ -307,6 +324,13 @@ pub struct ClaimsImports {
307324
/// `email_verified` claims
308325
#[serde(default, skip_serializing_if = "EmailImportPreference::is_default")]
309326
pub email: EmailImportPreference,
327+
328+
/// Set a human-readable name for the upstream account for display purposes
329+
#[serde(
330+
default,
331+
skip_serializing_if = "AccountNameImportPreference::is_default"
332+
)]
333+
pub account_name: AccountNameImportPreference,
310334
}
311335

312336
impl ClaimsImports {

crates/data-model/src/upstream_oauth2/link.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ pub struct UpstreamOAuthLink {
1414
pub provider_id: Ulid,
1515
pub user_id: Option<Ulid>,
1616
pub subject: String,
17+
pub human_account_name: Option<String>,
1718
pub created_at: DateTime<Utc>,
1819
}

crates/data-model/src/upstream_oauth2/provider.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,14 @@ pub struct ClaimsImports {
301301
#[serde(default)]
302302
pub email: ImportPreference,
303303

304+
#[serde(default)]
305+
pub account_name: SubjectPreference,
306+
304307
#[serde(default)]
305308
pub verify_email: SetEmailVerification,
306309
}
307310

311+
// XXX: this should have another name
308312
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
309313
pub struct SubjectPreference {
310314
#[serde(default)]

crates/handlers/src/upstream_oauth2/callback.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ pub(crate) async fn handler(
359359
.as_deref()
360360
.unwrap_or("{{ user.sub }}");
361361
let subject = env
362-
.render_str(template, context)
362+
.render_str(template, context.clone())
363363
.map_err(RouteError::ExtractSubject)?;
364364

365365
if subject.is_empty() {
@@ -375,8 +375,26 @@ pub(crate) async fn handler(
375375
let link = if let Some(link) = maybe_link {
376376
link
377377
} else {
378+
// Try to render the human account name if we have one,
379+
// but just log if it fails
380+
let human_account_name = provider
381+
.claims_imports
382+
.account_name
383+
.template
384+
.as_deref()
385+
.and_then(|template| match env.render_str(template, context) {
386+
Ok(name) => Some(name),
387+
Err(e) => {
388+
tracing::warn!(
389+
error = &e as &dyn std::error::Error,
390+
"Failed to render account name"
391+
);
392+
None
393+
}
394+
});
395+
378396
repo.upstream_oauth_link()
379-
.add(&mut rng, &clock, &provider, subject)
397+
.add(&mut rng, &clock, &provider, subject, human_account_name)
380398
.await?
381399
};
382400

crates/handlers/src/upstream_oauth2/link.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ pub(crate) async fn get(
332332
.await?
333333
.ok_or(RouteError::ProviderNotFound)?;
334334

335-
let ctx = UpstreamRegister::default();
335+
let ctx = UpstreamRegister::new(link.clone(), provider.clone());
336336

337337
let env = environment();
338338

@@ -596,7 +596,7 @@ pub(crate) async fn post(
596596
.map_or(false, |v| v == "true");
597597

598598
// Create a template context in case we need to re-render because of an error
599-
let ctx = UpstreamRegister::default();
599+
let ctx = UpstreamRegister::new(link.clone(), provider.clone());
600600

601601
let display_name = if provider
602602
.claims_imports
@@ -954,7 +954,13 @@ mod tests {
954954

955955
let link = repo
956956
.upstream_oauth_link()
957-
.add(&mut rng, &state.clock, &provider, "subject".to_owned())
957+
.add(
958+
&mut rng,
959+
&state.clock,
960+
&provider,
961+
"subject".to_owned(),
962+
None,
963+
)
958964
.await
959965
.unwrap();
960966

crates/storage-pg/.sqlx/query-4187907bfc770b2c76f741671d5e672f5c35eed7c9a9e57ff52888b1768a5ed6.json

Lines changed: 0 additions & 46 deletions
This file was deleted.

crates/storage-pg/.sqlx/query-5f6b7e38ef9bc3b39deabba277d0255fb8cfb2adaa65f47b78a8fac11d8c91c3.json

Lines changed: 0 additions & 17 deletions
This file was deleted.

crates/storage-pg/.sqlx/query-e6dc63984aced9e19c20e90e9cd75d6f6d7ade64f782697715ac4da077b2e1fc.json

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)