Skip to content

Commit

Permalink
feat: return cookie in response
Browse files Browse the repository at this point in the history
  • Loading branch information
EstebanBorai committed Aug 18, 2024
1 parent 7d6ab21 commit 34df229
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 11 deletions.
2 changes: 2 additions & 0 deletions crates/core/src/auth/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub type Result<T> = std::result::Result<T, AuthError>;

#[derive(Clone, Debug, Error, PartialEq, Eq)]
pub enum AuthError {
#[error("Verify Password Error. {0}")]
VerifyPasswordError(String),
#[error("Failed to sign token")]
SignTokenError,
#[error("Failed to encode JWT")]
Expand Down
4 changes: 2 additions & 2 deletions crates/core/src/auth/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ impl AuthService {
Ok(token_data.claims)
}

pub fn validate_password(&self, encoded: &str, raw: &str) -> bool {
pub fn validate_password(&self, encoded: &str, raw: &str) -> Result<bool> {
let raw = raw.as_bytes();

verify_encoded(encoded, raw).unwrap()
verify_encoded(encoded, raw).map_err(|err| AuthError::VerifyPasswordError(err.to_string()))
}

pub fn parse_jwt(&self, jwt: &str) -> Result<Token> {
Expand Down
3 changes: 3 additions & 0 deletions crates/core/src/user/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use thiserror::Error;

use crate::auth::error::AuthError;
use crate::image::error::ImageError;

use super::model::EmailError;
Expand All @@ -11,6 +12,8 @@ pub type Result<T> = std::result::Result<T, UserError>;

#[derive(Clone, Debug, Error, PartialEq, Eq)]
pub enum UserError {
#[error("Authentication Error. {0}")]
AuthError(#[from] AuthError),
#[error("The username is invalid")]
UsernameError(UsernameError),
#[error("The username {0} is already taken")]
Expand Down
8 changes: 5 additions & 3 deletions crates/core/src/user/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct CreateUserDto {
pub surname: String,
pub username: Username,
pub email: Email,
pub password: Password,
pub password: String, // FIXME: Use a secret based ds
}

pub struct UploadAvatarDto {
Expand Down Expand Up @@ -65,14 +65,16 @@ impl<P: ImageProvider> UserService<P> {
}

pub async fn register(&self, dto: CreateUserDto) -> Result<User> {
let password_hash = Password::hash(&dto.password)?;

self.repository
.insert(InsertUserDto {
id: User::pxid()?.to_string(),
name: dto.name,
surname: dto.surname,
username: dto.username.to_string(),
email: dto.email.to_string(),
password_hash: dto.password.to_string(),
password_hash,
})
.await
}
Expand Down Expand Up @@ -125,7 +127,7 @@ impl<P: ImageProvider> UserService<P> {
if let Some(password_hash) = maybe_password_hash {
if self
.auth_service
.validate_password(&password_hash, password)
.validate_password(&password_hash, password)?
{
return Ok(true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use async_graphql::{Context, Result, SimpleObject};

use axum::http::header::SET_COOKIE;
use serde::{Deserialize, Serialize};

use crate::context::SharedContext;
Expand All @@ -26,6 +27,7 @@ impl TokenCreate {
if credentials_ok {
if let Some(user) = context.services.user.find_by_email(&email).await? {
let token = context.services.auth.sign_token(user.id)?;
ctx.insert_http_header(SET_COOKIE, format!("Set-Cookie={token}"));

return Ok(Self {
token: Some(AccessToken {
Expand All @@ -35,7 +37,6 @@ impl TokenCreate {
});
}
}

Ok(Self {
token: None,
error: Some(AuthError {
Expand All @@ -45,6 +46,7 @@ impl TokenCreate {
})
}
Err(err) => {
println!("{:?}", err);
tracing::error!(%err, "Failed to verify credentials");

Ok(Self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ impl UserRegister {
pub async fn exec(ctx: &Context<'_>, input: UserRegisterInput) -> Result<Self> {
let context = ctx.data_unchecked::<SharedContext>();
let username = Username::from_str(&input.username)?;
let password = Password::from_str(&input.password)?;
let dto = CreateUserDto {
name: input.name,
surname: input.surname,
username,
email: input.email.into_inner(),
password,
password: input.password.clone(),
};

match context.services.user.register(dto).await {
Expand Down
1 change: 1 addition & 0 deletions crates/test/src/modules/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod token_create;
63 changes: 63 additions & 0 deletions crates/test/src/modules/auth/token_create.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::str::FromStr;

use async_graphql::{Request, Variables};
use serde_json::json;
use townhall::user::{
model::{Email, Password, Username},
service::CreateUserDto,
};

use crate::TestUtil;

#[tokio::test]
async fn authenticates_successfully() {
let test_util = TestUtil::new_cleared().await;
let (context, schema) = test_util.parts();
let mutation: &str = "
mutation TokenCreate($email: String!, $password: String!) {
tokenCreate(email: $email, password: $password) {
token {
accessToken
}
error {
code
message
}
}
}
";
let password = String::from("TestingPassword1234");
let user = context
.services
.user
.register(CreateUserDto {
name: "John".into(),
surname: "Appleseed".into(),
username: Username::from_str("jappleseed").unwrap(),
email: Email::from_str("j.appleseed@mail.com").unwrap(),
password: password.clone(),
})
.await
.unwrap();

let result = schema
.execute(
Request::new(mutation).variables(Variables::from_json(json!({
"email": "j.appleseed@mail.com",
"password": password.clone(),
}))),
)
.await;

println!("{:#?}", result);

let set_cookie = result.http_headers.get("Set-Cookie");

assert!(set_cookie.is_some());

let data = result.data.into_json().unwrap();
let access_token = &data["tokenCreate"]["token"]["accessToken"];

assert!(!access_token.to_string().is_empty());
assert_eq!(set_cookie.unwrap().to_str().unwrap(), access_token.to_string());
}
1 change: 1 addition & 0 deletions crates/test/src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
mod auth;
mod post;
mod user;
4 changes: 2 additions & 2 deletions crates/test/src/modules/post/post_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async fn create_post() {
let (context, schema) = test_util.parts();
let username = Username::from_str("john_appleseed").unwrap();
let email = Email::from_str("john_appleseed@whizzes.io").unwrap();
let password = Password::from_str("Root$1234").unwrap();
let password = String::from("Root$1234");
let user = context
.services
.user
Expand Down Expand Up @@ -93,7 +93,7 @@ async fn creates_post_with_parent() {
let (context, schema) = test_util.parts();
let username = Username::from_str("john_appleseed").unwrap();
let email = Email::from_str("john_appleseed@whizzes.io").unwrap();
let password = Password::from_str("Root$1234").unwrap();
let password = String::from("Root$1234");
let user = context
.services
.user
Expand Down
2 changes: 1 addition & 1 deletion crates/test/src/modules/user/user_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async fn updates_a_user() {
surname: "Madu".into(),
email: Email::from_str("augustine@gmail.com").unwrap(),
username: Username::from_str("Cudi").unwrap(),
password: Password::from_str("Password12##$$").unwrap(),
password: String::from("Password12##$$"),
})
.await
.unwrap();
Expand Down

0 comments on commit 34df229

Please sign in to comment.