Compare commits

..

2 Commits

Author SHA1 Message Date
b9f02e9f6e Formatted files 2025-03-17 15:02:58 +01:00
1280c745c7 Added default headers (cors) 2025-03-17 15:00:02 +01:00
5 changed files with 75 additions and 34 deletions

View File

@@ -1,15 +1,15 @@
use crate::types::*;
use crate::AppState; use crate::AppState;
use actix_web::web::Data; use actix_web::web::Data;
use actix_web::{get, web, HttpResponse, Responder}; use actix_web::{get, web, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
use serde_json::to_string; use serde_json::to_string;
use sqlx::query_as; use sqlx::query_as;
use crate::types::*;
#[get("/case")] #[get("/case")]
async fn get_case(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder { async fn get_case(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder {
let case = query_as!(Case, "SELECT * FROM cases WHERE uuid = $1", query.uuid).fetch_one(&app_state.database).await; let case = query_as!(Case, "SELECT * FROM cases WHERE uuid = $1", query.uuid)
.fetch_one(&app_state.database)
.await;
if case.is_err() { if case.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
@@ -22,7 +22,9 @@ async fn get_case(query: web::Query<DataUuid>, app_state: Data<AppState>) -> imp
#[get("/cases")] #[get("/cases")]
async fn get_cases(app_state: Data<AppState>) -> impl Responder { async fn get_cases(app_state: Data<AppState>) -> impl Responder {
let cases = query_as!(Case, "SELECT * FROM cases").fetch_all(&app_state.database).await; let cases = query_as!(Case, "SELECT * FROM cases")
.fetch_all(&app_state.database)
.await;
if cases.is_err() { if cases.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
@@ -33,22 +35,32 @@ async fn get_cases(app_state: Data<AppState>) -> impl Responder {
HttpResponse::Ok().body(json.unwrap()) HttpResponse::Ok().body(json.unwrap())
} }
#[get("/case-items")] #[get("/case-items")]
async fn get_case_items(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder { async fn get_case_items(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder {
let case = query_as!(Case, "SELECT * FROM cases WHERE uuid = $1", query.uuid).fetch_one(&app_state.database).await; let case = query_as!(Case, "SELECT * FROM cases WHERE uuid = $1", query.uuid)
.fetch_one(&app_state.database)
.await;
if case.is_err() { if case.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
let case = case.unwrap(); let case = case.unwrap();
let items_cases = query_as!(ItemCases, "SELECT * FROM items_cases WHERE \"case\" = $1", case.id).fetch_all(&app_state.database).await; let items_cases = query_as!(
ItemCases,
"SELECT * FROM items_cases WHERE \"case\" = $1",
case.id
)
.fetch_all(&app_state.database)
.await;
if items_cases.is_err() { if items_cases.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
let items_cases = items_cases.unwrap(); let items_cases = items_cases.unwrap();
let mut items = vec![]; let mut items = vec![];
for item_case in items_cases { for item_case in items_cases {
if let Ok(item) = query_as!(Item, "SELECT * FROM items WHERE id = $1", item_case.item).fetch_one(&app_state.database).await { if let Ok(item) = query_as!(Item, "SELECT * FROM items WHERE id = $1", item_case.item)
.fetch_one(&app_state.database)
.await
{
items.push(item); items.push(item);
} }
} }
@@ -58,4 +70,3 @@ async fn get_case_items(query: web::Query<DataUuid>, app_state: Data<AppState>)
} }
HttpResponse::Ok().body(json.unwrap()) HttpResponse::Ok().body(json.unwrap())
} }

View File

@@ -1,14 +1,15 @@
use actix_web::{get, web, HttpResponse, Responder, options}; use crate::types::*;
use crate::AppState;
use actix_web::web::Data; use actix_web::web::Data;
use actix_web::{get, web, HttpResponse, Responder};
use serde_json::to_string; use serde_json::to_string;
use sqlx::query_as; use sqlx::query_as;
use crate::AppState;
use crate::types::*;
#[get("/item")] #[get("/item")]
async fn get_item(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder { async fn get_item(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder {
let item = query_as!(Item, "SELECT * FROM items WHERE uuid = $1", query.uuid).fetch_one(&app_state.database).await; let item = query_as!(Item, "SELECT * FROM items WHERE uuid = $1", query.uuid)
.fetch_one(&app_state.database)
.await;
if item.is_err() { if item.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
@@ -16,12 +17,16 @@ async fn get_item(query: web::Query<DataUuid>, app_state: Data<AppState>) -> imp
if json.is_err() { if json.is_err() {
return HttpResponse::InternalServerError().finish(); return HttpResponse::InternalServerError().finish();
} }
HttpResponse::Ok().append_header(("Access-Control-Allow-Origin", "*")).body(json.unwrap()) HttpResponse::Ok()
.append_header(("Access-Control-Allow-Origin", "*"))
.body(json.unwrap())
} }
#[get("/items")] #[get("/items")]
async fn get_items(app_state: Data<AppState>) -> impl Responder { async fn get_items(app_state: Data<AppState>) -> impl Responder {
let items = query_as!(Item, "SELECT * FROM items").fetch_all(&app_state.database).await; let items = query_as!(Item, "SELECT * FROM items")
.fetch_all(&app_state.database)
.await;
if items.is_err() { if items.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
@@ -34,19 +39,30 @@ async fn get_items(app_state: Data<AppState>) -> impl Responder {
#[get("/item-cases")] #[get("/item-cases")]
async fn get_item_cases(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder { async fn get_item_cases(query: web::Query<DataUuid>, app_state: Data<AppState>) -> impl Responder {
let item = query_as!(Item, "SELECT * FROM items WHERE uuid = $1", query.uuid).fetch_one(&app_state.database).await; let item = query_as!(Item, "SELECT * FROM items WHERE uuid = $1", query.uuid)
.fetch_one(&app_state.database)
.await;
if item.is_err() { if item.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
let item = item.unwrap(); let item = item.unwrap();
let items_cases = query_as!(ItemCases, "SELECT * FROM items_cases WHERE \"item\" = $1", item.id).fetch_all(&app_state.database).await; let items_cases = query_as!(
ItemCases,
"SELECT * FROM items_cases WHERE \"item\" = $1",
item.id
)
.fetch_all(&app_state.database)
.await;
if items_cases.is_err() { if items_cases.is_err() {
return HttpResponse::NotFound().finish(); return HttpResponse::NotFound().finish();
} }
let items_cases = items_cases.unwrap(); let items_cases = items_cases.unwrap();
let mut cases = vec![]; let mut cases = vec![];
for item_case in items_cases { for item_case in items_cases {
if let Ok(item) = query_as!(Case, "SELECT * FROM cases WHERE id = $1", item_case.case).fetch_one(&app_state.database).await { if let Ok(item) = query_as!(Case, "SELECT * FROM cases WHERE id = $1", item_case.case)
.fetch_one(&app_state.database)
.await
{
cases.push(item); cases.push(item);
} }
} }

View File

@@ -1,25 +1,25 @@
mod users;
mod cases; mod cases;
mod items; mod items;
mod types; mod types;
mod users;
mod utils; mod utils;
use users::*;
use cases::*; use cases::*;
use items::*; use items::*;
use users::*;
use utils::*; use utils::*;
use actix_web::web::Data; use actix_web::web::Data;
use actix_web::{App, HttpServer}; use actix_web::{middleware::DefaultHeaders, App, HttpServer};
use sqlx::sqlite::SqlitePool; use sqlx::sqlite::SqlitePool;
#[derive(Clone)] #[derive(Clone)]
struct AppState { struct AppState {
database: SqlitePool, database: SqlitePool,
token_expiration: u64, token_expiration: u64,
allow_origins: Vec<&'static str>,
} }
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
let pool = SqlitePool::connect("sqlite:database.db") let pool = SqlitePool::connect("sqlite:database.db")
@@ -28,9 +28,14 @@ async fn main() -> std::io::Result<()> {
let app_state = Data::new(AppState { let app_state = Data::new(AppState {
database: pool, database: pool,
token_expiration: 86400, token_expiration: 86400,
allow_origins: vec!["http://localhost:5173"],
}); });
HttpServer::new(move || { HttpServer::new(move || {
App::new() App::new()
.wrap(DefaultHeaders::new().add((
"Access-Control-Allow-Origin",
app_state.allow_origins.join(","),
)))
.service(login) .service(login)
.service(register) .service(register)
.service(logout) .service(logout)

View File

@@ -1,19 +1,19 @@
use std::fs::File;
use std::io::Read;
use crate::AppState; use crate::AppState;
use actix_web::cookie::Cookie; use actix_web::cookie::Cookie;
use actix_web::web::{Data, Json}; use actix_web::web::{Data, Json};
use actix_web::{HttpRequest, HttpResponse, Responder, post}; use actix_web::{post, HttpRequest, HttpResponse, Responder};
use argon2::Argon2;
use argon2::password_hash::{ use argon2::password_hash::{
PasswordHash, PasswordHasher, PasswordVerifier, SaltString, rand_core::OsRng rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString,
}; };
use argon2::Argon2;
use jsonwebtoken::{ use jsonwebtoken::{
Algorithm, DecodingKey, EncodingKey, Header, Validation, decode, encode, get_current_timestamp, decode, encode, get_current_timestamp, Algorithm, DecodingKey, EncodingKey, Header, Validation,
}; };
use rand::Rng; use rand::Rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{query, query_as}; use sqlx::{query, query_as};
use std::fs::File;
use std::io::Read;
use uuid::Uuid; use uuid::Uuid;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -121,13 +121,17 @@ async fn logout(req: HttpRequest, app_state: Data<AppState>) -> impl Responder {
.await .await
.is_err() .is_err()
{ {
return HttpResponse::InternalServerError().reason("Query fail").finish(); return HttpResponse::InternalServerError()
.reason("Query fail")
.finish();
} }
} }
Err(e) => { Err(e) => {
let message = format!("Error: {e}"); let message = format!("Error: {e}");
println!("{}", message); println!("{}", message);
return HttpResponse::InternalServerError().reason("Token caca").finish(); return HttpResponse::InternalServerError()
.reason("Token caca")
.finish();
} }
} }
let mut cookie = Cookie::new("token", ""); let mut cookie = Cookie::new("token", "");

View File

@@ -1,11 +1,16 @@
use crate::AppState;
use actix_web::web::Data;
use actix_web::{options, HttpResponse, Responder}; use actix_web::{options, HttpResponse, Responder};
// This is needed for the web client. // This is needed for the web client.
// This returns the same options for every path of the api // This returns the same options for every path of the api
#[options("/{_:.*}")] #[options("/{_:.*}")]
async fn options() -> impl Responder { async fn options(app_state: Data<AppState>) -> impl Responder {
HttpResponse::Ok() HttpResponse::Ok()
.append_header(("Access-Control-Allow-Origin", "*")) .append_header((
"Access-Control-Allow-Origin",
app_state.allow_origins.join(","),
))
.append_header(("Access-Control-Allow-Methods", "GET, OPTIONS")) .append_header(("Access-Control-Allow-Methods", "GET, OPTIONS"))
.append_header(("Access-Control-Allow-Headers", "Content-Type")) .append_header(("Access-Control-Allow-Headers", "Content-Type"))
.finish() .finish()