Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion auth/server/src/api/login/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub async fn sign_up_local_user<I: AuthImpl + ?Sized>(

let no_users_exist = auth.no_users_exist().await?;

if auth.registration_disabled() && !no_users_exist {
if auth.local_registration_disabled() && !no_users_exist {
return Err(
anyhow!("User registration is disabled")
.status_code(StatusCode::UNAUTHORIZED),
Expand Down
118 changes: 118 additions & 0 deletions auth/server/src/api/login/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,15 @@ pub fn get_login_options<I: AuthImpl + ?Sized>(
.google_config()
.map(|config| config.enabled())
.unwrap_or_default(),
<<<<<<< granular-registration-control
registration_disabled: auth.local_registration_disabled(),
=======
registration_disabled: auth.registration_disabled(),
oidc_auto_redirect: auth
.oidc_config()
.map(|config| config.enabled() && config.auto_redirect)
.unwrap_or_default(),
>>>>>>> main
}
}

Expand All @@ -138,11 +142,20 @@ mod tests {
use crate::AuthImpl;
use mogh_auth_client::config::OidcConfig;

<<<<<<< granular-registration-control
/// Minimal AuthImpl for testing
=======
/// Minimal AuthImpl for testing get_login_options
>>>>>>> main
struct TestAuth {
local: bool,
oidc: Option<OidcConfig>,
registration_disabled: bool,
<<<<<<< granular-registration-control
local_registration_disabled: Option<bool>,
oidc_registration_disabled: Option<bool>,
=======
>>>>>>> main
}

impl TestAuth {
Expand All @@ -151,6 +164,11 @@ mod tests {
local: true,
oidc: None,
registration_disabled: false,
<<<<<<< granular-registration-control
local_registration_disabled: None,
oidc_registration_disabled: None,
=======
>>>>>>> main
}
}
}
Expand All @@ -172,6 +190,21 @@ mod tests {
self.registration_disabled
}

<<<<<<< granular-registration-control
fn local_registration_disabled(&self) -> bool {
self
.local_registration_disabled
.unwrap_or_else(|| self.registration_disabled())
}

fn oidc_registration_disabled(&self) -> bool {
self
.oidc_registration_disabled
.unwrap_or_else(|| self.registration_disabled())
}

=======
>>>>>>> main
fn get_user(
&self,
_user_id: String,
Expand All @@ -194,12 +227,96 @@ mod tests {
})
}

<<<<<<< granular-registration-control
fn jwt_provider(
&self,
) -> &crate::provider::jwt::JwtProvider {
panic!("not needed for these tests")
=======
fn jwt_provider(&self) -> &crate::provider::jwt::JwtProvider {
panic!("not needed for login options tests")
>>>>>>> main
}
}

#[test]
<<<<<<< granular-registration-control
fn test_default_granular_methods_delegate_to_registration_disabled()
{
// When granular overrides are None, they should
// fall back to the global registration_disabled flag.
let auth = TestAuth {
registration_disabled: true,
..TestAuth::default_test()
};
assert!(auth.local_registration_disabled());
assert!(auth.oidc_registration_disabled());
assert!(auth.github_registration_disabled());
assert!(auth.google_registration_disabled());
}

#[test]
fn test_global_disabled_local_override_enabled() {
// Global registration disabled, but local override allows it
let auth = TestAuth {
registration_disabled: true,
local_registration_disabled: Some(false),
..TestAuth::default_test()
};
assert!(!auth.local_registration_disabled());
assert!(auth.oidc_registration_disabled());
}

#[test]
fn test_global_enabled_local_override_disabled() {
// Global registration enabled, but local override blocks it
let auth = TestAuth {
registration_disabled: false,
local_registration_disabled: Some(true),
..TestAuth::default_test()
};
assert!(auth.local_registration_disabled());
assert!(!auth.oidc_registration_disabled());
}

#[test]
fn test_disable_local_allow_oidc() {
// The #1087 use case: disable local signup, allow OIDC
let auth = TestAuth {
registration_disabled: false,
local_registration_disabled: Some(true),
oidc_registration_disabled: Some(false),
..TestAuth::default_test()
};
assert!(auth.local_registration_disabled());
assert!(!auth.oidc_registration_disabled());
}

#[test]
fn test_registration_disabled_reflects_local_in_login_options() {
// registration_disabled in the response controls the Sign Up button,
// which is local-only. It should reflect local_registration_disabled.
let auth = TestAuth {
registration_disabled: false,
local_registration_disabled: Some(true),
oidc_registration_disabled: Some(false),
..TestAuth::default_test()
};
let opts = get_login_options(&auth);
assert!(opts.registration_disabled);
}

#[test]
fn test_registration_disabled_false_when_local_allowed() {
let auth = TestAuth {
registration_disabled: true,
local_registration_disabled: Some(false),
oidc_registration_disabled: Some(true),
..TestAuth::default_test()
};
let opts = get_login_options(&auth);
assert!(!opts.registration_disabled);
=======
fn test_oidc_auto_redirect_defaults_false() {
let auth = TestAuth::default_test();
let opts = get_login_options(&auth);
Expand Down Expand Up @@ -266,6 +383,7 @@ mod tests {
};
let opts = get_login_options(&auth);
assert!(!opts.oidc_auto_redirect);
>>>>>>> main
}
}

Expand Down
2 changes: 1 addition & 1 deletion auth/server/src/api/named/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ pub async fn github_callback<I: AuthImpl>(
None => {
let no_users_exist = auth.no_users_exist().await?;

if auth.registration_disabled() && !no_users_exist {
if auth.github_registration_disabled() && !no_users_exist {
return Err(
anyhow!("User registration is disabled")
.status_code(StatusCode::UNAUTHORIZED),
Expand Down
2 changes: 1 addition & 1 deletion auth/server/src/api/named/google.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub async fn google_callback<I: AuthImpl>(
None => {
let no_users_exist = auth.no_users_exist().await?;

if auth.registration_disabled() && !no_users_exist {
if auth.google_registration_disabled() && !no_users_exist {
return Err(
anyhow!("User registration is disabled")
.status_code(StatusCode::UNAUTHORIZED),
Expand Down
2 changes: 1 addition & 1 deletion auth/server/src/api/oidc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ pub async fn oidc_callback<I: AuthImpl>(
None => {
let no_users_exist = auth.no_users_exist().await?;

if auth.registration_disabled() && !no_users_exist {
if auth.oidc_registration_disabled() && !no_users_exist {
return Err(
anyhow!("User registration is disabled")
.status_code(StatusCode::UNAUTHORIZED),
Expand Down
26 changes: 25 additions & 1 deletion auth/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,35 @@ pub trait AuthImpl: Send + Sync + 'static {
"/auth"
}

/// Disable new user registration.
/// Disable new user registration (all providers).
fn registration_disabled(&self) -> bool {
false
}

/// Disable new user registration for local (username/password) signups only.
/// Defaults to [Self::registration_disabled].
fn local_registration_disabled(&self) -> bool {
self.registration_disabled()
}

/// Disable new user registration via OIDC only.
/// Defaults to [Self::registration_disabled].
fn oidc_registration_disabled(&self) -> bool {
self.registration_disabled()
}

/// Disable new user registration via GitHub only.
/// Defaults to [Self::registration_disabled].
fn github_registration_disabled(&self) -> bool {
self.registration_disabled()
}

/// Disable new user registration via Google only.
/// Defaults to [Self::registration_disabled].
fn google_registration_disabled(&self) -> bool {
self.registration_disabled()
}

/// Provide usernames to lock credential updates for,
/// such as demo users.
fn locked_usernames(&self) -> &'static [String] {
Expand Down