Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mobergmann committed Nov 21, 2023
1 parent cb358c0 commit 547793e
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 41 deletions.
File renamed without changes.
29 changes: 17 additions & 12 deletions src/logic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
mod auth;
mod account;
mod users;
mod activities;

use crate::activity::{BareActivity, StringBareActivity};
use crate::storage::Error;
use crate::database::Error;
use crate::user::{BareUser, PublicUser, User};
use crate::{hasher, storage};
use crate::{hasher, database};
use axum::extract::Path;
use axum::http::StatusCode;
use axum::response::IntoResponse;
Expand All @@ -17,19 +22,19 @@ pub async fn ping() -> impl IntoResponse {

pub async fn sign_up(Json(payload): Json<BareUser>) -> impl IntoResponse {
// if username already exists, return with error
if storage::user_exists(&payload.name).await {
if database::user_exists(&payload.name).await {
return (StatusCode::CONFLICT).into_response();
}

// create a new user
match storage::insert_new_user(&payload).await {
match database::insert_new_user(&payload).await {
Ok(user) => (StatusCode::CREATED, Json(user)).into_response(),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR).into_response(),
}
}

pub async fn sign_in(mut auth: AuthContext, Json(payload): Json<BareUser>) -> impl IntoResponse {
let user = match storage::get_user(&payload.name).await {
let user = match database::get_user(&payload.name).await {
Ok(user) => user,
Err(_) => return (StatusCode::NOT_FOUND, "name does not exist").into_response(),
};
Expand All @@ -48,7 +53,7 @@ pub async fn sign_out(mut auth: AuthContext) -> impl IntoResponse {
}

pub async fn get_activity(mut auth: AuthContext, Path(activity_id): Path<i64>) -> impl IntoResponse {
let activity = match storage::get_activity(activity_id).await {
let activity = match database::get_activity(activity_id).await {
Ok(activity) => activity,
Err(Error::ElementNotFound) => return (StatusCode::NOT_FOUND).into_response(),
Err(_) => {
Expand Down Expand Up @@ -79,7 +84,7 @@ pub async fn get_activities_from_to(mut auth: AuthContext, Path((from, to)): Pat

println!("from: {}, to: {}", from, to);

match storage::get_activities(&from, &to).await {
match database::get_activities(&from, &to).await {
Ok(activities) => (StatusCode::OK, Json(activities)).into_response(),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR).into_response(),
}
Expand Down Expand Up @@ -121,7 +126,7 @@ pub async fn new_activity(

println!("from: {}, to: {}", end_time, start_time);

match storage::new_activity(&BareActivity {
match database::new_activity(&BareActivity {
amount: payload.amount,
activity_type: payload.activity_type,
start_time: start_time,
Expand All @@ -146,7 +151,7 @@ pub async fn delete_activity(
mut auth: AuthContext,
Path(activity_id): Path<i64>,
) -> impl IntoResponse {
let activity = match storage::get_activity(activity_id).await {
let activity = match database::get_activity(activity_id).await {
Ok(activity) => activity,
Err(Error::ElementNotFound) => return (StatusCode::NOT_FOUND).into_response(),
Err(_) => {
Expand All @@ -159,7 +164,7 @@ pub async fn delete_activity(
return (StatusCode::UNAUTHORIZED).into_response();
}

let activity = match storage::delete_activity(activity_id).await {
let activity = match database::delete_activity(activity_id).await {
Ok(activity) => activity,
Err(_) => {
return (StatusCode::INTERNAL_SERVER_ERROR).into_response()
Expand All @@ -170,7 +175,7 @@ pub async fn delete_activity(

pub async fn get_user(mut auth: AuthContext, Path(username): Path<String>) -> impl IntoResponse
{
let user = match storage::get_user(&username).await {
let user = match database::get_user(&username).await {
Ok(user) => user,
Err(Error::ElementNotFound) => return (StatusCode::NO_CONTENT).into_response(),
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR).into_response(),
Expand All @@ -181,7 +186,7 @@ pub async fn get_user(mut auth: AuthContext, Path(username): Path<String>) -> im

pub async fn get_user_by_id(mut auth: AuthContext, Path(user_id): Path<i64>) -> impl IntoResponse
{
let user = match storage::get_user_by_id(&user_id).await {
let user = match database::get_user_by_id(&user_id).await {
Ok(user) => user,
Err(Error::ElementNotFound) => return (StatusCode::NO_CONTENT).into_response(),
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR).into_response(),
Expand Down
Empty file added src/logic/account.rs
Empty file.
Empty file added src/logic/activities.rs
Empty file.
37 changes: 37 additions & 0 deletions src/logic/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
type AuthContext = axum_login::extractors::AuthContext<i64, User, SqliteStore<User>>;

use crate::user::{BareUser, PublicUser, User};
use crate::database::{BareUser, PublicUser, User};

use axum_login::SqliteStore;
use axum::response::IntoResponse;
use axum::http::StatusCode;
use axum::Json;

pub async fn sign_in(mut auth: AuthContext, Json(payload): Json<BareUser>) -> impl IntoResponse
{
let user = match database::get_user(&payload.name).await
{
Ok(user) => user,
Err(_) => return (StatusCode::NOT_FOUND, "name does not exist").into_response(),
};

if !hasher::verify(&user.password_hash, &payload.password)
{
return (StatusCode::UNAUTHORIZED, "password doesn't match").into_response();
}

auth.login(&user).await.unwrap();
(StatusCode::OK, Json(user)).into_response()
}

pub async fn sign_out(mut auth: AuthContext) -> impl IntoResponse
{
auth.logout().await;
(StatusCode::OK).into_response()
}

pub async fn ping() -> impl IntoResponse
{
(StatusCode::OK).into_response()
}
Empty file added src/logic/users.rs
Empty file.
10 changes: 5 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
mod activity;
mod hasher;
mod logic;
mod services;
mod storage;
mod routes;
mod database;
mod user;

use axum::Router;

#[tokio::main]
async fn main() {
// init database or exit program on error
match storage::init().await {
match database::init().await {
Ok(_) => {},
Err(_) => panic!("Error while initializing the database."),
};

let app = Router::new()
.merge(services::backend_router().await)
.merge(services::frontend_router().await);
.merge(routes::backend_router().await)
.merge(routes::frontend_router().await);

axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
Expand Down
62 changes: 38 additions & 24 deletions src/services.rs → src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::logic::*;
use crate::user::User;

use crate::storage::DB_URI;
use crate::database::DB_URI;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::routing::{delete, get, post};
use axum::routing::{delete, get, put, post};
use axum::Router;
use axum_login::axum_sessions::async_session::MemoryStore;
use axum_login::axum_sessions::{SameSite, SessionLayer};
Expand All @@ -23,40 +23,54 @@ pub async fn frontend_router() -> Router {
}

pub async fn backend_router() -> Router {
let secret = rand::thread_rng().gen::<[u8; 64]>();
let secret = rand::thread_rng().gen::<[u8; 64]>(); // todo use secret from environment variable

let session_store = MemoryStore::new();
let session_layer = SessionLayer::new(session_store, &secret)
.with_secure(false)
.with_same_site_policy(SameSite::Lax);

let pool = SqlitePoolOptions::new().connect(DB_URI).await.unwrap();

let user_store = SqliteStore::<User>::new(pool);
let auth_layer = AuthLayer::new(user_store, &secret);

Router::new()
// account management routes
let auth_router = Router::new()
.route("/v1/auth/ping", get(ping))
.route_layer(RequireAuthorizationLayer::<i64, User>::login())
.route("/v1/auth/login", post(login))
.route("/v1/auth/logout", put(logout))
.layer(&auth_layer)
.layer(&session_layer);

let account_router = Router::new()
.route("/v1/account", get(get_account))
.route("/v1/account/edit", post(edit_account))
.route("/v1/account", post(new_account))
.route("/v1/account", put(edit_account))
.route("/v1/account", delete(delete_account))
// user
.route("/v1/user/id/:id", get(get_user_by_id))
.route("/v1/user/:username", get(get_user))
// activity routes
.route("/v1/activities/:id", get(get_activity))
.route("/v1/activities/:from/:to", get(get_activities_from_to))
.route("/v1/account/password", put(change_account_password))
.route_layer(RequireAuthorizationLayer::<i64, User>::login())
.layer(&auth_layer)
.layer(&session_layer);

let users_router = Router::new()
.route("/v1/users/id/:id", get(get_user_by_id))
.route("/v1/users/:username", get(get_user))
.route_layer(RequireAuthorizationLayer::<i64, User>::login())
.layer(&auth_layer)
.layer(&session_layer);

let activities_router = Router::new()
.route("/v1/activities", post(new_activity))
.route("/v1/activities/edit", post(edit_activity))
.route("/v1/activities/:id", get(get_activity))
.route("/v1/activities/:id", put(edit_activity))
.route("/v1/activities/:id", delete(delete_activity))
// for checking if you are logged in
.route("/v1/ping", get(ping))
// routes above are protected
.route("/v1/activities/:from/:to", get(get_activities_from_to))
.route_layer(RequireAuthorizationLayer::<i64, User>::login())
// authentication routes
.route("/v1/auth/sign_up", post(sign_up))
.route("/v1/auth/sign_in", post(sign_in))
.route("/v1/auth/sign_out", get(sign_out))
.layer(auth_layer)
.layer(session_layer)
.layer(&auth_layer)
.layer(&session_layer);

Router::new()
.merge(auth_router)
.merge(account_router)
.merge(users_router)
.merge(activities_router)
}

0 comments on commit 547793e

Please sign in to comment.