Single sign-on servers need no setup step
With single sign-on there is no first-start code and no /setup form: the identity provider says who may sign in and who is admin, and the first allowed sign-in makes the organisation, named after ARCHIFY_SYNC_NAME. Server 0.1.1, chart 0.1.2.
This commit is contained in:
1 parent
d8d46266dc
commit
01a35f7ba6
7 files changed
+45
-12
No files matched your search
@@ -531,9 +531,12 @@ async fn sso_account(
|
||||
.invite_organisation(&auth::sha256(invite))
|
||||
.await?
|
||||
.map(|(org, _)| org),
|
||||
None if !config.allowed_groups.is_empty() || admin => {
|
||||
state.store.first_organisation().await?
|
||||
}
|
||||
None if !config.allowed_groups.is_empty() || admin => Some(
|
||||
state
|
||||
.store
|
||||
.organisation_or_create(&state.config.server_name)
|
||||
.await?,
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
let Some(organisation) = organisation else {
|
||||
|
||||
@@ -42,7 +42,9 @@ impl AppState {
|
||||
let secret = STANDARD.decode(stored.as_str().unwrap_or_default())?;
|
||||
anyhow::ensure!(secret.len() >= 32, "the stored signing key is too short");
|
||||
|
||||
let first_start = if store.account_count().await? == 0 {
|
||||
// With single sign-on the identity provider says who is admin; there
|
||||
// is no first-start code and no setup page.
|
||||
let first_start = if config.oidc.is_none() && store.account_count().await? == 0 {
|
||||
let code = auth::first_start_code();
|
||||
tracing::warn!(
|
||||
"first start: no accounts yet. Set up the first admin at {}/setup with code {code}",
|
||||
|
||||
@@ -313,6 +313,34 @@ impl Store {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The server's organisation, made with `name` when there is none yet
|
||||
/// (a single sign-on server has no setup step).
|
||||
pub async fn organisation_or_create(&self, name: &str) -> Result<Uuid> {
|
||||
let mut tx = self.pool.begin().await?;
|
||||
// Serialises the first sign-ins, so only one organisation is made.
|
||||
sqlx::query("LOCK TABLE organisations IN EXCLUSIVE MODE")
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
let found: Option<Uuid> =
|
||||
sqlx::query_scalar("SELECT id FROM organisations ORDER BY created_at LIMIT 1")
|
||||
.fetch_optional(&mut *tx)
|
||||
.await?;
|
||||
let id = match found {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
let id = Uuid::now_v7();
|
||||
sqlx::query("INSERT INTO organisations (id, name) VALUES ($1, $2)")
|
||||
.bind(id)
|
||||
.bind(name)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
id
|
||||
}
|
||||
};
|
||||
tx.commit().await?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// The server's organisation: the one made at setup.
|
||||
pub async fn first_organisation(&self) -> Result<Option<Uuid>> {
|
||||
Ok(
|
||||
|
||||
Reference in new issue
Block a user