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:
+26
-24
@@ -41,14 +41,14 @@ impl AuthService {
|
||||
|
||||
// Rate limiting: check cooldown
|
||||
let cooldown_key = format!("{}cooldown:{}", Self::RESET_PASS_PREFIX, email);
|
||||
if self.ctx.cache.exists(&cooldown_key) {
|
||||
if self.ctx.cache.exists(&cooldown_key).await {
|
||||
tracing::warn!(email = %email, "Password reset request rate limited (cooldown)");
|
||||
return Ok(()); // Don't reveal if email exists
|
||||
}
|
||||
|
||||
// Rate limiting: check daily limit
|
||||
let daily_key = format!("{}daily:{}", Self::RESET_PASS_PREFIX, email);
|
||||
let daily_count: u64 = self.ctx.cache.get(&daily_key).unwrap_or(0);
|
||||
let daily_count: u64 = self.ctx.cache.get(&daily_key).await.unwrap_or(0);
|
||||
if daily_count >= Self::RESET_PASS_DAILY_LIMIT {
|
||||
tracing::warn!(email = %email, count = daily_count, "Password reset request rate limited (daily limit)");
|
||||
return Ok(()); // Don't reveal if email exists
|
||||
@@ -68,30 +68,11 @@ impl AuthService {
|
||||
created_at: now,
|
||||
},
|
||||
Some(StdDuration::from_secs(Self::RESET_PASS_EXPIRY_SECS)),
|
||||
) {
|
||||
).await {
|
||||
tracing::error!(error = %e, user_uid = %user.id, "Failed to cache reset token");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Set cooldown
|
||||
if let Err(e) = self.ctx.cache.set(
|
||||
&cooldown_key,
|
||||
&true,
|
||||
Some(StdDuration::from_secs(Self::RESET_PASS_COOLDOWN_SECS)),
|
||||
) {
|
||||
tracing::warn!(error = %e, "Failed to set cooldown");
|
||||
}
|
||||
|
||||
// Increment daily counter
|
||||
let new_count = daily_count + 1;
|
||||
if let Err(e) = self.ctx.cache.set(
|
||||
&daily_key,
|
||||
&new_count,
|
||||
Some(StdDuration::from_secs(Self::RESET_PASS_DAILY_SECS)),
|
||||
) {
|
||||
tracing::warn!(error = %e, "Failed to increment daily counter");
|
||||
}
|
||||
|
||||
let domain = match self.ctx.config.main_domain() {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
@@ -126,6 +107,26 @@ impl AuthService {
|
||||
.await
|
||||
{
|
||||
tracing::error!(error = %e, email = %email, "Failed to send password reset email");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Set cooldown only after successful email send
|
||||
if let Err(e) = self.ctx.cache.set(
|
||||
&cooldown_key,
|
||||
&true,
|
||||
Some(StdDuration::from_secs(Self::RESET_PASS_COOLDOWN_SECS)),
|
||||
).await {
|
||||
tracing::warn!(error = %e, "Failed to set cooldown");
|
||||
}
|
||||
|
||||
// Increment daily counter only after successful email send
|
||||
let new_count = daily_count + 1;
|
||||
if let Err(e) = self.ctx.cache.set(
|
||||
&daily_key,
|
||||
&new_count,
|
||||
Some(StdDuration::from_secs(Self::RESET_PASS_DAILY_SECS)),
|
||||
).await {
|
||||
tracing::warn!(error = %e, "Failed to increment daily counter");
|
||||
}
|
||||
|
||||
tracing::info!(email = %email, user_uid = %user.id, "Password reset email sent");
|
||||
@@ -148,16 +149,17 @@ impl AuthService {
|
||||
.ctx
|
||||
.cache
|
||||
.get::<PendingResetPassword>(&cache_key)
|
||||
.await
|
||||
.ok_or(AppError::InvalidResetToken)?;
|
||||
|
||||
if Utc::now() - pending.created_at > Duration::hours(Self::RESET_PASS_EXPIRY_HOURS) {
|
||||
let _ = self.ctx.cache.delete(&cache_key);
|
||||
let _ = self.ctx.cache.delete(&cache_key).await;
|
||||
return Err(AppError::ResetTokenExpired);
|
||||
}
|
||||
|
||||
let password = self.auth_rsa_decode(context, params.password).await?;
|
||||
crate::service::util::validate_password_strength(&password)?;
|
||||
let _ = self.ctx.cache.delete(&cache_key);
|
||||
let _ = self.ctx.cache.delete(&cache_key).await;
|
||||
|
||||
let salt = SaltString::generate(&mut rand::thread_rng());
|
||||
let password_hash = Argon2::default()
|
||||
|
||||
Reference in New Issue
Block a user