diff --git a/auth/src/main.rs b/auth/src/main.rs index 5f26542..b9f4196 100644 --- a/auth/src/main.rs +++ b/auth/src/main.rs @@ -39,6 +39,7 @@ async fn main() -> anyhow::Result<()> { id SERIAL, username VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, + new_email VARCHAR(255), avatar TEXT NOT NULL, login_code INT(6), tokens TEXT, diff --git a/auth/src/server.rs b/auth/src/server.rs index be05df0..034355d 100644 --- a/auth/src/server.rs +++ b/auth/src/server.rs @@ -122,6 +122,22 @@ impl RealmAuthServer { } } } + + pub async fn is_login_code_valid(&self, username: &str, login_code: u16) -> Result { + let result = sqlx::query("SELECT login_code FROM user WHERE username = ?;") + .bind(username) + .fetch_one(&self.db_pool).await; + + match result { + Ok(row) => { + if row.try_get::("login_code").unwrap() != login_code { + return Ok(false) + } + Ok(true) + } + Err(_) => Err(InvalidUsername) + } + } } impl RealmAuth for RealmAuthServer { @@ -236,17 +252,8 @@ impl RealmAuth for RealmAuthServer { } async fn finish_login_flow(self, _: Context, username: String, login_code: u16) -> Result { - let result = sqlx::query("SELECT login_code FROM user WHERE username = ?;") - .bind(&username) - .fetch_one(&self.db_pool).await; - - match result { - Ok(row) => { - if row.try_get::("login_code").unwrap() != login_code { - return Err(InvalidLoginCode) - } - } - Err(_) => return Err(InvalidUsername) + if !self.is_login_code_valid(&username, login_code).await? { + return Err(InvalidLoginCode) } let _ = sqlx::query("UPDATE user SET login_code = NULL WHERE username = ?").bind(&username).execute(&self.db_pool).await; @@ -261,7 +268,10 @@ impl RealmAuth for RealmAuthServer { let mut tokens = token_long.split(',').collect::>(); tokens.push(&token); - let result = sqlx::query("UPDATE user SET tokens = ? WHERE username = ?").bind(tokens.join(",")).bind(&username).execute(&self.db_pool).await; + let result = sqlx::query("UPDATE user SET tokens = ? WHERE username = ?") + .bind(tokens.join(",")) // TODO: This doesn't seem right and may cause problems + .bind(&username) + .execute(&self.db_pool).await; match result { Ok(_) => Ok(token), Err(_) => Err(InvalidUsername) @@ -272,11 +282,83 @@ impl RealmAuth for RealmAuthServer { } async fn change_email_flow(self, _: Context, username: String, new_email: String, token: String) -> ErrorCode { - todo!() + let result = self.is_authorized(&username, &token).await; + match result { + Ok(authorized) => { + if !authorized { + return Unauthorized + } + } + Err(error) => return error + } + + let result = self.is_email_taken(&new_email).await; + match result { + Ok(taken) => { + if taken { + return EmailTaken + } + } + Err(error) => return error + } + + let result = sqlx::query("UPDATE user SET new_email = ? WHERE username = ?") + .bind(&new_email) + .bind(&username) + .execute(&self.db_pool).await; + match result { + Ok(_) => {} + Err(_) => return InvalidUsername + } + + let code = self.gen_login_code(); + + let result = sqlx::query("UPDATE user SET login_code = ? WHERE username = ?;") + .bind(code) + .bind(&username) + .execute(&self.db_pool).await; + + match result { + Ok(_) => self.send_login_message(&username, &new_email, code).await, + Err(_) => InvalidUsername + } } - async fn finish_change_email_flow(self, _: Context, username: String, token: String, login_code: u16) -> ErrorCode { - todo!() + async fn finish_change_email_flow(self, _: Context, username: String, new_email: String, token: String, login_code: u16) -> ErrorCode { + let result = self.is_authorized(&username, &token).await; + match result { + Ok(authorized) => { + if !authorized { + return Unauthorized + } + } + Err(error) => return error + } + + let result = self.is_email_taken(&new_email).await; + match result { + Ok(taken) => { + if taken { + return EmailTaken + } + } + Err(error) => return error + } + + if !self.is_login_code_valid(&username, login_code).await.unwrap() { + return InvalidLoginCode + } + + let _ = sqlx::query("UPDATE user SET new_email = NULL WHERE username = ?") + .bind(&username) + .execute(&self.db_pool).await; + + let _ = sqlx::query("UPDATE user SET email = ? WHERE username = ?") + .bind(&new_email) + .bind(&username) + .execute(&self.db_pool).await; + + NoError } async fn change_username(self, _: Context, username: String, token: String, new_username: String) -> ErrorCode { diff --git a/auth/src/types.rs b/auth/src/types.rs index c107d42..617723d 100644 --- a/auth/src/types.rs +++ b/auth/src/types.rs @@ -10,7 +10,7 @@ pub trait RealmAuth { //NOTE: Need to be the user async fn change_email_flow(username: String, new_email: String, token: String) -> ErrorCode; - async fn finish_change_email_flow(username: String, token: String, login_code: u16) -> ErrorCode; + async fn finish_change_email_flow(username: String, new_email: String, token: String, login_code: u16) -> ErrorCode; async fn change_username(username: String, token: String, new_username: String) -> ErrorCode; async fn change_avatar(username: String, token: String, new_avatar: String) -> ErrorCode; async fn get_all_data(username: String, token: String) -> Result; @@ -19,8 +19,8 @@ pub trait RealmAuth { //NOTE: Anyone can call async fn get_avatar_for_user(username: String) -> Result; //TODO: + // Refactor all to use Result<_, ErrorCode> for ones with only -> ErrorCode // Create account - // Change email // Change username // OAuth login, check against email, store token, take avatar: Google, Apple, GitHub, Discord }