Store cached OAuth username and add to `AuthMethods`

This commit is contained in:
JSH32 2022-09-21 11:43:59 -05:00
parent c4d4a8245c
commit 778c85ad52
8 changed files with 63 additions and 22 deletions

View File

@ -5,11 +5,20 @@
* Enabled authorization methods.
*/
export type AuthMethods = {
discord: boolean;
github: boolean;
google: boolean;
/**
* Password authentication.
* Cached discord tag.
*/
discord?: string;
/**
* Cached github username.
*/
github?: string;
/**
* Google username (email before the @).
*/
google?: string;
/**
* Is password authentication enabled.
*/
password: boolean;
};

View File

@ -44,6 +44,7 @@ impl MigrationTrait for Migration {
.enumeration("auth_method", ["password", "google", "github", "discord"])
.not_null(),
)
.col(ColumnDef::new(AuthMethods::CachedUsername).text())
.col(ColumnDef::new(AuthMethods::Value).text().not_null())
.col(
ColumnDef::new(AuthMethods::LastAccessed)
@ -106,15 +107,17 @@ impl MigrationTrait for Migration {
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(AuthMethods::Table).to_owned())
.await?;
if manager.get_database_backend() == DbBackend::Postgres {
manager
.drop_type(Type::drop().name(AuthMethod::Type).to_owned())
.await?;
}
manager
.drop_table(Table::drop().table(AuthMethods::Table).to_owned())
.await
Ok(())
}
}
@ -131,6 +134,7 @@ enum AuthMethods {
Table,
Id,
UserId,
CachedUsername,
AuthMethod,
Value,
LastAccessed,

View File

@ -12,6 +12,7 @@ pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: String,
pub user_id: String,
pub cached_username: Option<String>,
pub auth_method: AuthMethod,
#[sea_orm(column_type = "Text")]
pub value: String,

View File

@ -17,9 +17,12 @@ pub struct AuthRequest {
/// Enabled authorization methods.
#[derive(Serialize, ToSchema, Default)]
pub struct AuthMethods {
/// Password authentication.
/// Is password authentication enabled.
pub password: bool,
pub google: bool,
pub github: bool,
pub discord: bool,
/// Google username (email before the @).
pub google: Option<String>,
/// Cached github username.
pub github: Option<String>,
/// Cached discord tag.
pub discord: Option<String>,
}

View File

@ -120,7 +120,7 @@ async fn create(
.create_user(
form.0.username,
form.0.email,
(AuthMethod::Password, form.0.password),
(AuthMethod::Password, form.0.password, None),
form.0.registration_key,
)
.await

View File

@ -49,10 +49,11 @@ impl AuthMethodService {
let mut methods = AuthMethods::default();
for method in found_methods {
// These should all be true except for password.
match method.auth_method {
AuthMethod::Discord => methods.discord = true,
AuthMethod::Github => methods.github = true,
AuthMethod::Google => methods.google = true,
AuthMethod::Discord => methods.discord = method.cached_username,
AuthMethod::Github => methods.github = method.cached_username,
AuthMethod::Google => methods.google = method.cached_username,
AuthMethod::Password => methods.password = true,
};
}
@ -66,6 +67,7 @@ impl AuthMethodService {
&self,
method: AuthMethod,
value: &str,
new_cached_username: Option<String>,
) -> ServiceResult<Option<users::Model>> {
match self
.by_condition(
@ -85,6 +87,8 @@ impl AuthMethodService {
// Update `last_accessed`.
let mut active_method = v.into_active_model();
active_method.last_accessed = Set(Utc::now());
active_method.cached_username = Set(new_cached_username);
active_method
.update(self.database.as_ref())
.await
@ -104,6 +108,7 @@ impl AuthMethodService {
&self,
user_id: &str,
method: AuthMethod,
cached_username: Option<String>,
value: &str,
) -> ServiceResult<auth_methods::Model> {
match auth_methods::Entity::find()
@ -126,7 +131,10 @@ impl AuthMethodService {
.await
.map_err(|e| ServiceError::DbErr(e))
}
None => self.create_auth_method(user_id, method, value).await,
None => {
self.create_auth_method(user_id, method, cached_username, value)
.await
}
}
}
@ -135,6 +143,7 @@ impl AuthMethodService {
&self,
user_id: &str,
method: AuthMethod,
cached_username: Option<String>,
value: &str,
) -> ServiceResult<auth_methods::Model> {
let value = match method {
@ -145,6 +154,7 @@ impl AuthMethodService {
auth_methods::ActiveModel {
user_id: Set(user_id.to_owned()),
auth_method: Set(method),
cached_username: Set(cached_username),
value: Set(value),
..Default::default()
}

View File

@ -229,7 +229,11 @@ impl AuthService {
// Get a user based on auth method.
let user = match self
.auth_method_service
.get_user_by_value(provider_type.clone().into(), &oauth_data.id)
.get_user_by_value(
provider_type.clone().into(),
&oauth_data.id,
Some(oauth_data.username.clone()),
)
.await?
{
// User found.
@ -252,7 +256,12 @@ impl AuthService {
{
Ok(user) => {
self.auth_method_service
.create_auth_method(&user.id, provider_type.into(), &oauth_data.id)
.create_auth_method(
&user.id,
provider_type.into(),
Some(oauth_data.username),
&oauth_data.id,
)
.await?;
user
@ -264,7 +273,11 @@ impl AuthService {
.create_user(
self.new_unique_username(&oauth_data.username).await?,
oauth_data.email,
(provider_type.into(), oauth_data.id),
(
provider_type.into(),
oauth_data.id,
Some(oauth_data.username),
),
None,
)
.await?

View File

@ -101,13 +101,13 @@ impl UserService {
///
/// * `username` - Users username
/// * `email` - User email
/// * `auth_method` - Authentication method
/// * `auth_method` - (method, identifier, optional username)
/// * `registration_key` - Registration key. This can always be validated later.
pub async fn create_user(
&self,
username: String,
email: String,
auth_method: (AuthMethod, String),
auth_method: (AuthMethod, String, Option<String>),
registration_key: Option<String>,
) -> ServiceResult<users::Model> {
validate_username(&username)?;
@ -187,6 +187,7 @@ impl UserService {
auth_methods::ActiveModel {
user_id: Set(user.id.clone()),
auth_method: Set(auth_method.0.clone()),
cached_username: Set(auth_method.2),
value: Set(method_value),
..Default::default()
}
@ -297,7 +298,7 @@ impl UserService {
// This is done last since it is a seperate operation and occurs last.
if let Some(password) = &password {
self.auth_method_service
.create_or_set_method(&user.id, AuthMethod::Password, password)
.create_or_set_method(&user.id, AuthMethod::Password, None, password)
.await?;
}