DEVELOPMENT ENVIRONMENT

~liljamo/deck-builder

fb43c0af69ed4a14409e38a413143053869ff74a — Jonni Liljamo 1 year, 7 months ago a0e9ef2
WIP(api): session management
A api/src/actions/user/login.rs => api/src/actions/user/login.rs +19 -0
@@ 0,0 1,19 @@
/*
 * This file is part of laurelin/api
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use diesel::PgConnection;
use laurelin_shared::error::api::APIError;

use crate::models::{User, UserCredentials};

pub(crate) fn login(
    conn: &mut PgConnection,
    credentials: &UserCredentials,
) -> Result<User, APIError> {
    Err(APIError::UserInvalidCredentials)
}

A api/src/actions/user/logout.rs => api/src/actions/user/logout.rs +0 -0
M api/src/actions/user/mod.rs => api/src/actions/user/mod.rs +4 -1
@@ 7,4 7,7 @@
 */

mod create;
pub(crate) use create::*;
pub(crate) use create::create;

mod login;
pub(crate) use login::login;

A api/src/handlers/user/login.rs => api/src/handlers/user/login.rs +49 -0
@@ 0,0 1,49 @@
/*
 * This file is part of laurelin/api
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use actix_session::Session;
use actix_web::{post, web, HttpResponse, Responder};
use laurelin_shared::error::api::APIError;

use crate::{actions, models::UserCredentials, PgPool};

#[post("/api/user/login")]
pub(crate) async fn login(
    pool: web::Data<PgPool>,
    session: Session,
    credentials: web::Json<UserCredentials>,
) -> impl Responder {
    let user = match web::block(move || {
        let mut conn = match pool.get() {
            Err(_) => return Err(APIError::DatabasePoolGetFailed),
            Ok(conn) => conn,
        };
        actions::user::login(&mut conn, &credentials.0)
    })
    .await
    {
        Err(_) => {
            // TODO: handle?
            return HttpResponse::InternalServerError().json(APIError::Undefined);
        }
        Ok(user_res) => match user_res {
            Err(err) => match err {
                APIError::UserInvalidCredentials => {
                    return HttpResponse::Unauthorized().json(APIError::UserInvalidCredentials)
                }
                _ => return HttpResponse::InternalServerError().json(err),
            },
            Ok(user) => user,
        },
    };

    match session.insert("user_id", user.id) {
        Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
        Ok(_) => HttpResponse::Ok().json(user),
    }
}

M api/src/handlers/user/mod.rs => api/src/handlers/user/mod.rs +5 -0
@@ 8,3 8,8 @@

mod create;
pub(crate) use create::*;

mod login;
pub(crate) use login::*;

pub(crate) fn logout() {}

M api/src/main.rs => api/src/main.rs +9 -1
@@ 6,7 6,7 @@
 * See LICENSE for licensing information.
 */

use actix_session::{storage::RedisActorSessionStore, SessionMiddleware};
use actix_session::{storage::RedisActorSessionStore, Session, SessionMiddleware};
use actix_web::{
    cookie::Key, get, middleware::Logger, web, App, HttpResponse, HttpServer, Responder,
};


@@ 27,6 27,11 @@ async fn ping() -> impl Responder {
    HttpResponse::Ok().body("pong")
}

#[get("/api/ping_sec")]
async fn ping_sec(session: Session) -> impl Responder {
    HttpResponse::Ok().body("pong")
}

fn run_migrations(conn: &mut PgConnection) {
    conn.run_pending_migrations(MIGRATIONS).unwrap();
}


@@ 36,6 41,7 @@ mod schema;
mod actions;
mod handlers;
mod models;
mod session;

#[actix_web::main]
async fn main() -> std::io::Result<()> {


@@ 70,8 76,10 @@ async fn main() -> std::io::Result<()> {
                .build(),
            )
            .service(ping)
            .service(ping_sec)
            .service(handlers::info)
            .service(handlers::user::create)
            .service(handlers::user::login)
    })
    .bind(("0.0.0.0", 8080))?
    .run()

M api/src/models/user.rs => api/src/models/user.rs +6 -0
@@ 32,3 32,9 @@ pub(crate) struct InsertableUser {
    pub email: String,
    pub password: String,
}

#[derive(Deserialize)]
pub(crate) struct UserCredentials {
    pub email: String,
    pub password: String,
}

A api/src/session.rs => api/src/session.rs +15 -0
@@ 0,0 1,15 @@
/*
 * This file is part of laurelin/api
 * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
 *
 * Licensed under GPL-3.0-only.
 * See LICENSE for licensing information.
 */

use actix_session::Session;
use actix_web::HttpResponse;
use laurelin_shared::error::api::APIError;

pub(crate) fn validate_session(session: &Session) -> Result<String, HttpResponse> {
    Err(HttpResponse::Unauthorized().json(APIError::NotAuthorized))
}