feat(webserver): add reset_user_auth_token mutation (#1001)

* feat(webserver): add reset_user_auth_token mutation

* fix

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
r0.7
Meng Zhang 2023-12-10 12:12:49 +08:00 committed by GitHub
parent f00b2c3334
commit 03c418340a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 5 deletions

View File

@ -10,6 +10,7 @@ enum WorkerKind {
type Mutation {
resetRegistrationToken: String!
resetUserAuthToken: Boolean!
register(email: String!, password1: String!, password2: String!, invitationCode: String): RegisterResponse!
tokenAuth(email: String!, password: String!): TokenAuthResponse!
verifyToken(token: String!): VerifyTokenResponse!

View File

@ -274,6 +274,8 @@ pub trait AuthenticationService: Send + Sync {
async fn create_invitation(&self, email: String) -> Result<i32>;
async fn list_invitations(&self) -> Result<Vec<Invitation>>;
async fn delete_invitation(&self, id: i32) -> Result<i32>;
async fn reset_user_auth_token(&self, email: &str) -> Result<()>;
}
#[cfg(test)]

View File

@ -144,6 +144,18 @@ impl Mutation {
))
}
async fn reset_user_auth_token(ctx: &Context) -> Result<bool> {
if let Some(claims) = &ctx.claims {
ctx.locator
.auth()
.reset_user_auth_token(&claims.sub)
.await?;
Ok(true)
} else {
Err(CoreError::Unauthorized("You're not logged in"))
}
}
async fn register(
ctx: &Context,
email: String,

View File

@ -292,6 +292,10 @@ impl AuthenticationService for DbConn {
async fn delete_invitation(&self, id: i32) -> Result<i32> {
self.delete_invitation(id).await
}
async fn reset_user_auth_token(&self, email: &str) -> Result<()> {
self.reset_user_auth_token_by_email(email).await
}
}
fn password_hash(raw: &str) -> password_hash::Result<String> {
@ -460,4 +464,16 @@ mod tests {
// expire time should be no change
assert_eq!(resp1.refresh_expires_at, resp2.refresh_expires_at);
}
#[tokio::test]
async fn test_reset_user_auth_token() {
let conn = DbConn::new_in_memory().await.unwrap();
register_admin_user(&conn).await;
let user = conn.get_user_by_email(ADMIN_EMAIL).await.unwrap().unwrap();
conn.reset_user_auth_token(&user.email).await.unwrap();
let user2 = conn.get_user_by_email(ADMIN_EMAIL).await.unwrap().unwrap();
assert_ne!(user.auth_token, user2.auth_token);
}
}

View File

@ -162,16 +162,17 @@ impl DbConn {
id.is_ok()
}
pub async fn reset_auth_token(&self, id: i32) -> Result<i32> {
pub async fn reset_user_auth_token_by_email(&self, email: &str) -> Result<()> {
let email = email.to_owned();
self.conn
.call(move |c| {
let mut stmt = c.prepare(r#"UPDATE users SET auth_token = ? WHERE id = ?"#)?;
stmt.execute((Uuid::new_v4().to_string(), id))?;
let mut stmt = c.prepare(r#"UPDATE users SET auth_token = ? WHERE email = ?"#)?;
stmt.execute((generate_auth_token(), email))?;
Ok(())
})
.await?;
Ok(id)
Ok(())
}
}
@ -215,7 +216,9 @@ mod tests {
assert!(conn.verify_auth_token(&user.auth_token).await);
conn.reset_auth_token(id).await.unwrap();
conn.reset_user_auth_token_by_email(&user.email)
.await
.unwrap();
let new_user = conn.get_user(id).await.unwrap().unwrap();
assert_eq!(user.email, new_user.email);
assert_ne!(user.auth_token, new_user.auth_token);