Skip to content

Commit

Permalink
Implement login endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksbgbg committed Feb 10, 2024
1 parent 8fd97a2 commit 1242b01
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
6 changes: 6 additions & 0 deletions backend-rs/src/controllers/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub enum HandlerError {
UsernameTaken,
#[error("Email Address must not be taken.")]
EmailTaken,
#[error("Login credentials are invalid.")]
InvalidCredentials,
#[error("Authentication token is invalid.")]
DecodeJwt(jsonwebtoken::errors::Error),

Expand All @@ -71,6 +73,8 @@ pub enum HandlerError {
Database(#[from] DbErr),
#[error("Could not create user.")]
CreateUser(#[from] user::CreateError),
#[error("Could not validate credentials.")]
ValidateCredentials(#[from] user::ValidateCredentialsError),
#[error("Could not encode JWT.")]
EncodeJwt(jsonwebtoken::errors::Error),
}
Expand Down Expand Up @@ -128,12 +132,14 @@ impl IntoResponse for HandlerError {
}),
HandlerError::UsernameTaken => self.failed_validation(StatusCode::BAD_REQUEST, "username"),
HandlerError::EmailTaken => self.failed_validation(StatusCode::BAD_REQUEST, "emailAddress"),
HandlerError::InvalidCredentials => self.into_generic(StatusCode::BAD_REQUEST),
HandlerError::DecodeJwt(_) => self.into_generic(StatusCode::BAD_REQUEST),

HandlerError::UserRequired => self.into_generic(StatusCode::UNAUTHORIZED),

HandlerError::Database(_) => self.into_generic(StatusCode::INTERNAL_SERVER_ERROR),
HandlerError::CreateUser(_) => self.into_generic(StatusCode::INTERNAL_SERVER_ERROR),
HandlerError::ValidateCredentials(_) => self.into_generic(StatusCode::INTERNAL_SERVER_ERROR),
HandlerError::EncodeJwt(_) => self.into_generic(StatusCode::INTERNAL_SERVER_ERROR),
}
.into_response()
Expand Down
23 changes: 23 additions & 0 deletions backend-rs/src/controllers/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,29 @@ pub async fn register(
Ok((StatusCode::CREATED, cookies))
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LoginUser {
username: String,
password: String,
}

pub async fn login(
State(state): State<AppState>,
cookies: CookieJar,
Json(details): Json<LoginUser>,
) -> Result<(StatusCode, CookieJar), HandlerError> {
if let Some(user) =
user::login_with_credentials(&state.connection, &details.username, &details.password).await?
{
let cookies = authenticate(cookies, &user, state.config.app.token_lifespan)?;

Ok((StatusCode::CREATED, cookies))
} else {
Err(HandlerError::InvalidCredentials)
}
}

#[async_trait]
impl FromRequestParts<AppState> for User {
type Rejection = HandlerError;
Expand Down
1 change: 1 addition & 0 deletions backend-rs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ async fn main() -> Result<(), AppError> {

let app = Router::new()
.route("/auth/register", routing::post(user::register))
.route("/auth/login", routing::post(user::login))
.route("/user", routing::get(user::get_user))
.layer(
TraceLayer::new_for_http()
Expand Down
33 changes: 33 additions & 0 deletions backend-rs/src/models/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,39 @@ pub async fn create(
)
}

#[derive(Error, Debug)]
pub enum ValidateCredentialsError {
#[error(transparent)]
Database(#[from] DbErr),
#[error(transparent)]
Hash(#[from] BcryptError),
}

pub async fn login_with_credentials(
connection: &DatabaseConnection,
name: &str,
password: &str,
) -> Result<Option<User>, ValidateCredentialsError> {
let user = Entity::find()
.filter(Column::Username.eq(name))
.one(connection)
.await?;

match user {
None => Ok(None),
Some(user) => match &user.password {
None => Ok(None),
Some(hash) => {
if bcrypt::verify(password, hash)? {
Ok(Some(user))
} else {
Ok(None)
}
}
},
}
}

pub async fn find(connection: &DatabaseConnection, id: Id) -> Result<Option<User>, DbErr> {
Entity::find_by_id(id).one(connection).await
}

0 comments on commit 1242b01

Please sign in to comment.