feat(service): expand service layer with new domain operations
- Add IM service modules: audit, channel roles, custom emojis, forum tags, integrations, invitations, repo links, slash commands, stages, voice, webhooks - Add PR service modules: review requests, templates - Add repo service modules: contributors, release assets, git extras (archive, branch rename, commit extras, diff/merge, tag, tree) - Add user service: social (follow/block) - Add internal auth service - Update existing service modules with expanded functionality - Remove deleted IM modules: articles, delivery trace, drafts, follows, messages, polls, presence, reactions, threads
This commit is contained in:
+17
-25
@@ -192,13 +192,13 @@ impl AuthService {
|
||||
let Some(totp_key) = context.get::<String>(Self::TOTP_KEY).ok().flatten() else {
|
||||
return Ok(false);
|
||||
};
|
||||
let Some(user_uid) = self.ctx.cache.get::<Uuid>(&totp_key) else {
|
||||
let Some(user_uid) = self.ctx.cache.get::<Uuid>(&totp_key).await else {
|
||||
context.remove(Self::TOTP_KEY);
|
||||
return Ok(false);
|
||||
};
|
||||
if user_uid != expected_user_uid {
|
||||
context.remove(Self::TOTP_KEY);
|
||||
let _ = self.ctx.cache.delete(&totp_key);
|
||||
let _ = self.ctx.cache.delete(&totp_key).await;
|
||||
tracing::warn!(expected_user_uid = %expected_user_uid, pending_user_uid = %user_uid, "2FA pending user mismatch");
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -206,7 +206,7 @@ impl AuthService {
|
||||
let verified = self.auth_2fa_verify(user_uid, code).await?;
|
||||
if verified {
|
||||
context.remove(Self::TOTP_KEY);
|
||||
let _ = self.ctx.cache.delete(&totp_key);
|
||||
let _ = self.ctx.cache.delete(&totp_key).await;
|
||||
}
|
||||
Ok(verified)
|
||||
}
|
||||
@@ -349,7 +349,7 @@ impl AuthService {
|
||||
async fn verify_user_password(&self, user_uid: Uuid, password: &str) -> Result<(), AppError> {
|
||||
let row = sqlx::query("SELECT password_hash FROM user_password WHERE user_id = $1")
|
||||
.bind(user_uid)
|
||||
.fetch_optional(self.ctx.db.reader())
|
||||
.fetch_optional(self.ctx.db.writer())
|
||||
.await
|
||||
.map_err(AppError::Database)?
|
||||
.ok_or(AppError::UserNotFound)?;
|
||||
@@ -368,7 +368,7 @@ impl AuthService {
|
||||
FROM user_2fa WHERE user_id = $1",
|
||||
)
|
||||
.bind(user_uid)
|
||||
.fetch_optional(self.ctx.db.reader())
|
||||
.fetch_optional(self.ctx.db.writer())
|
||||
.await
|
||||
.map_err(AppError::Database)
|
||||
}
|
||||
@@ -384,26 +384,18 @@ impl AuthService {
|
||||
}
|
||||
|
||||
let hashed_code = self.hash_backup_code(code)?;
|
||||
let mut backup_codes: Vec<String> = two_fa
|
||||
.backup_codes
|
||||
.split('.')
|
||||
.filter(|c| !c.is_empty())
|
||||
.map(ToOwned::to_owned)
|
||||
.collect();
|
||||
if backup_codes
|
||||
.iter()
|
||||
.any(|stored| constant_time_eq(stored, &hashed_code))
|
||||
{
|
||||
backup_codes.retain(|stored| stored != &hashed_code);
|
||||
sqlx::query(
|
||||
"UPDATE user_2fa SET backup_codes = $1, updated_at = $2 WHERE user_id = $3",
|
||||
)
|
||||
.bind(backup_codes.join("."))
|
||||
.bind(chrono::Utc::now())
|
||||
.bind(two_fa.user_id)
|
||||
.execute(self.ctx.db.writer())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
let result = sqlx::query(
|
||||
"UPDATE user_2fa SET backup_codes = regexp_replace(backup_codes, $1, ''), updated_at = $2 \
|
||||
WHERE user_id = $3 AND backup_codes LIKE '%' || $1 || '%'",
|
||||
)
|
||||
.bind(&hashed_code)
|
||||
.bind(chrono::Utc::now())
|
||||
.bind(two_fa.user_id)
|
||||
.execute(self.ctx.db.writer())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
|
||||
if result.rows_affected() > 0 {
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
|
||||
Reference in New Issue
Block a user