some fixes, first push to ovh, discord webhook
This commit is contained in:
786
Cargo.lock
generated
786
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@ rand_core = {version = "0.6.4", features = ["getrandom"]}
|
||||
futures-util = {version = "0.3.31"}
|
||||
uuid = {version = "1.18.1", features = ["serde"] }
|
||||
base64 = "0.22.1"
|
||||
reqwest = { version = "0.12.24", features = ["json","blocking"] }
|
||||
|
||||
|
||||
|
||||
|
||||
11
Dockerfile
11
Dockerfile
@@ -4,11 +4,18 @@ COPY . .
|
||||
RUN cargo build --release
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
# Create the app user with UID 1001
|
||||
RUN useradd -u 1001 -m appuser
|
||||
|
||||
# Create working directory (only needed if your app expects /app)
|
||||
WORKDIR /app
|
||||
|
||||
# Copy binary from builder
|
||||
COPY --from=builder /app/target/release/hotel-api-rs /usr/local/bin/hotel-api-rs
|
||||
|
||||
# Create the directory where DB will be stored
|
||||
RUN mkdir -p /db
|
||||
# Switch to non-root user
|
||||
USER 1001
|
||||
|
||||
# Expose API port
|
||||
EXPOSE 8080
|
||||
|
||||
16
Dockerfile copy
Normal file
16
Dockerfile copy
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM rust:latest AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN cargo build --release
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/target/release/hotel-api-rs /usr/local/bin/hotel-api-rs
|
||||
|
||||
# Create the directory where DB will be stored
|
||||
RUN mkdir -p /db
|
||||
|
||||
# Expose API port
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["/usr/local/bin/hotel-api-rs"]
|
||||
BIN
db/1.sqlite
BIN
db/1.sqlite
Binary file not shown.
BIN
db/auth copy.sqlite
Normal file
BIN
db/auth copy.sqlite
Normal file
Binary file not shown.
BIN
db/auth.sqlite
BIN
db/auth.sqlite
Binary file not shown.
BIN
db/test_backup/1.sqlite
Normal file
BIN
db/test_backup/1.sqlite
Normal file
Binary file not shown.
BIN
db/test_backup/auth.sqlite
Normal file
BIN
db/test_backup/auth.sqlite
Normal file
Binary file not shown.
BIN
rust-api-1-0-2.tar
Normal file
BIN
rust-api-1-0-2.tar
Normal file
Binary file not shown.
@@ -1,16 +1,18 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use axum::{
|
||||
extract::{
|
||||
Json, extract::{
|
||||
FromRequest,FromRequestParts, State,
|
||||
|
||||
}, http::StatusCode, response::{sse::KeepAlive, IntoResponse},
|
||||
}, http::StatusCode, response::{IntoResponse, sse::KeepAlive}
|
||||
|
||||
};
|
||||
//use axum::extract::ws::Message;
|
||||
use chrono::NaiveDateTime;
|
||||
use rusqlite::params;
|
||||
use rusqlite::{Name, params};
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use serde_json::{json, to_value};
|
||||
|
||||
use crate::chat::extractor::{
|
||||
AddUserConversationPayload, CreateConversationPayload, GetMessagesPayload, SendMessagePayload
|
||||
@@ -154,6 +156,7 @@ pub async fn send_message(
|
||||
|
||||
if let Some(hotel_users) = state.ws_map.get(&hotel_id) {
|
||||
let update_msg = serde_json::json!({
|
||||
"event-type": "chat-message",
|
||||
"conv_id": payload.conv_id,
|
||||
"sender": user_id,
|
||||
"content": payload.message,
|
||||
@@ -280,3 +283,140 @@ pub async fn get_hotel_users(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct Conversation {
|
||||
id: i32,
|
||||
title: String,
|
||||
}
|
||||
|
||||
pub async fn get_convs(
|
||||
State(state): State<AppState>,
|
||||
//Path((item_name, item_amount)): Path<(String, i32)>,
|
||||
AuthClaims{ user_id, hotel_id}: AuthClaims,
|
||||
) -> impl IntoResponse {
|
||||
|
||||
let pool = state.hotel_pools.get_pool(hotel_id);
|
||||
|
||||
let conn = match pool.get(){
|
||||
Ok(conn) => conn,
|
||||
Err(err) => {
|
||||
let body = json!({ "error": format!("Pool error: {}", err) });
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, Json(body));
|
||||
}
|
||||
};
|
||||
|
||||
let mut stmt = match conn.prepare(
|
||||
"SELECT conversation_id, name FROM conversation_participants WHERE user_id = ?1",
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
let body = json!({ "error": format!("Prepare failed: {}", e) });
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, Json(body) )
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let rows = match stmt.query_map(params![user_id], |row| {
|
||||
let conversation_id: i32 = row.get(0)?;
|
||||
let name: String = row.get(1)?;
|
||||
Ok((conversation_id, name))
|
||||
}) {
|
||||
Ok(rows) => rows,
|
||||
//Ok(_) => {}, IMPLEMENT NO CONV ?
|
||||
Err(e) => {
|
||||
let body = json!({ "error": format!("Query failed: {}", e) });
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, Json(body));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let mut map = HashMap::new();
|
||||
|
||||
// ✅ Iterate through the row results
|
||||
for row_result in rows {
|
||||
match row_result {
|
||||
Ok((id, name)) => {
|
||||
map.insert(id, name);
|
||||
}
|
||||
Err(e) => {
|
||||
let body = json!({ "error": format!("Row parsing failed: {}", e) });
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, Json(body));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let convs_string = serde_json::to_string(&map)
|
||||
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, Json("error".to_string())));
|
||||
|
||||
let conv_map_json = to_value(map).unwrap();
|
||||
(StatusCode::OK, Json(conv_map_json))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
pub async fn get_convs(
|
||||
State(state): State<AppState>,
|
||||
//Path((item_name, item_amount)): Path<(String, i32)>,
|
||||
AuthClaims{ user_id, hotel_id}: AuthClaims,
|
||||
) -> impl IntoResponse {
|
||||
|
||||
let pool = state.hotel_pools.get_pool(hotel_id);
|
||||
|
||||
let conn = match pool.get(){
|
||||
Ok(conn) => conn,
|
||||
Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {}", err).into_response() )
|
||||
|
||||
};
|
||||
|
||||
let mut stmt = match conn.prepare(
|
||||
"SELECT id, title FROM conversation WHERE creator_id = ?1",
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) =>
|
||||
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, format!("Prepare failed: {}", e).into_response() )
|
||||
|
||||
|
||||
};
|
||||
|
||||
let rows = match stmt.query_map(params![user_id], |row| {
|
||||
let id: i32 = row.get(0)?;
|
||||
let title: String = row.get(1)?;
|
||||
Ok((title, id))
|
||||
}) {
|
||||
Ok(rows) => rows,
|
||||
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Query failed: {}", e).into_response() )
|
||||
|
||||
};
|
||||
|
||||
|
||||
let mut map = HashMap::new();
|
||||
|
||||
// ✅ Iterate through the row results
|
||||
for row_result in rows {
|
||||
match row_result {
|
||||
Ok((title, id)) => {
|
||||
map.insert(title, id);
|
||||
}
|
||||
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Row parsing failed: {}", e).into_response() )
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let conv_map_json = match to_value(map) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("List unwrapping failed: {}", e).into_response() )
|
||||
};
|
||||
|
||||
let conv_map_clean_json = serde_json::to_value(map)
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("Serialization failed: {}", e).into_response() ));
|
||||
|
||||
|
||||
|
||||
(StatusCode::OK, Json(conv_map_clean_json)).into_response()
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -18,6 +18,7 @@ pub fn chat_routes() -> Router<AppState> {
|
||||
.route("/create_conversation", post (create_conversation))
|
||||
.route("/add_users_conv", put(add_user_to_conv))
|
||||
.route("/send_message", post(send_message))
|
||||
.route("/get_conv", get(get_convs))
|
||||
.route("/get_message", get(get_message))
|
||||
.route("/hotel_users", get(get_hotel_users))
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
use argon2::Params;
|
||||
use axum::{extract::{ws::{close_code::STATUS, Message}, Path, State}, http::StatusCode, response::IntoResponse};
|
||||
use rusqlite::params;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
|
||||
|
||||
@@ -33,6 +34,14 @@ pub async fn create_inventory_item(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct InventoryItems {
|
||||
id: i32,
|
||||
amount: i32,
|
||||
name: String,
|
||||
user_id: i32,
|
||||
updated_at: String,
|
||||
}
|
||||
|
||||
pub async fn update_inventory_item(
|
||||
State(state): State<AppState>,
|
||||
@@ -82,3 +91,47 @@ pub async fn update_inventory_item(
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_inventory_item(
|
||||
State(state): State<AppState>,
|
||||
AuthClaims { user_id, hotel_id }: AuthClaims,
|
||||
) -> impl IntoResponse {
|
||||
let pool = state.hotel_pools.get_pool(hotel_id);
|
||||
|
||||
let conn = match pool.get() {
|
||||
Ok(c) => c,
|
||||
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Pool error".to_string()),
|
||||
};
|
||||
|
||||
let mut stmt = match conn.prepare("SELECT id, amount, item_name, user_id FROM inventory") {
|
||||
Ok(s) => s,
|
||||
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Statement error".to_string()),
|
||||
};
|
||||
|
||||
let mut query_result = match stmt.query([]) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Query error".to_string()),
|
||||
};
|
||||
|
||||
let mut items = Vec::new();
|
||||
|
||||
while let Ok(Some(row)) = query_result.next() {
|
||||
let item = InventoryItems {
|
||||
id: row.get("id").unwrap_or_default(),
|
||||
amount: row.get("amount").unwrap_or_default(),
|
||||
name: row.get("name").unwrap_or_default(),
|
||||
user_id: row.get("user_id").unwrap_or_default(),
|
||||
updated_at: row.get("updated_at").unwrap_or_default(),
|
||||
};
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
// Serialize to JSON
|
||||
let json = match serde_json::to_string(&items) {
|
||||
Ok(j) => j,
|
||||
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Serialization error".to_string()),
|
||||
};
|
||||
|
||||
(StatusCode::OK, json)
|
||||
}
|
||||
@@ -10,4 +10,5 @@ pub fn inventory_routes() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/update_item/{item_id}/{item_amount}", put(update_inventory_item))
|
||||
.route("/add_item/{item_name}/{item_amount}", post(create_inventory_item))
|
||||
.route("/get_item/", get(get_inventory_item))
|
||||
}
|
||||
33
src/main.rs
33
src/main.rs
@@ -5,6 +5,8 @@ use jsonwebtoken::{DecodingKey, EncodingKey};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use reqwest::Client;
|
||||
|
||||
mod utils;
|
||||
mod routes;
|
||||
mod rooms;
|
||||
@@ -23,12 +25,43 @@ use std::env;
|
||||
use dotenvy::dotenv;
|
||||
|
||||
|
||||
pub async fn notify_discord(msg: &str) -> Result<(), reqwest::Error> {
|
||||
let payload = serde_json::json!({
|
||||
"content": msg
|
||||
});
|
||||
|
||||
reqwest::Client::new()
|
||||
.post("https://discord.com/api/webhooks/1440912618205347891/Ekg89krDoPm41kA27LA3gXgNWmMWvCCtziYIUsjqaY22Jnw4a6IWhZOht0in5JjnPX-W")
|
||||
.json(&payload)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[tokio::main(flavor = "multi_thread", worker_threads = 8)]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
|
||||
dotenv().ok();
|
||||
|
||||
std::panic::set_hook(Box::new(|info| {
|
||||
let msg = format!("Rust panic: {}", info);
|
||||
|
||||
// Use blocking client so the process can't exit before sending
|
||||
let payload = serde_json::json!({
|
||||
"content": msg
|
||||
});
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let _ = client
|
||||
.post("https://discord.com/api/webhooks/1440912618205347891/Ekg89krDoPm41kA27LA3gXgNWmMWvCCtziYIUsjqaY22Jnw4a6IWhZOht0in5JjnPX-W")
|
||||
.json(&payload)
|
||||
.send();
|
||||
}));
|
||||
|
||||
panic!("crash-test");
|
||||
|
||||
let hotel_pools = HotelPool::new();
|
||||
let logs_manager = SqliteConnectionManager::file("db/auth.sqlite");
|
||||
let logs_pool = Pool::builder()
|
||||
|
||||
@@ -22,8 +22,6 @@ pub async fn hello_rooms() -> String {
|
||||
"hello from rooms".to_string()
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub async fn fake_db_update(
|
||||
State(state): State<AppState>,
|
||||
AuthClaims { user_id, hotel_id }: AuthClaims,
|
||||
@@ -85,6 +83,7 @@ pub async fn clean_db_update(
|
||||
}
|
||||
if let Some(hotel_users) = state.ws_map.get(&hotel_id) {
|
||||
let update_msg = json!({
|
||||
"event-type": "room-update",
|
||||
"room_id": room_id,
|
||||
"status": payload.status,
|
||||
"updated_by": user_id,
|
||||
@@ -131,13 +130,15 @@ pub async fn get_all_rooms(
|
||||
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Prepare failed: {}", e)),
|
||||
};
|
||||
|
||||
let room_iter = match stmt.query_map( params![],|row| {
|
||||
Ok(Room {
|
||||
id: row.get(0)?,
|
||||
number: row.get(1)?,
|
||||
status: row.get(2)?,
|
||||
})
|
||||
}) {
|
||||
let room_iter = match stmt.query_map(
|
||||
params![],|row| {
|
||||
Ok(Room {
|
||||
id: row.get(0)?,
|
||||
number: row.get(1)?,
|
||||
status: row.get(2)?,
|
||||
})
|
||||
}
|
||||
) {
|
||||
Ok(iter) => iter,
|
||||
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Query failed: {}", e)),
|
||||
};
|
||||
|
||||
@@ -4,3 +4,80 @@ docker run -p 8080:8080 \
|
||||
-v ${PWD}/db:/db \
|
||||
-e JWT_SECRET="my-dev-secret" \
|
||||
rust-api:1.0.0
|
||||
|
||||
GOOD
|
||||
|
||||
docker run
|
||||
--hostname=58ff54b2464c
|
||||
--env=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
--volume=/w/DEV/hotel-api-rs/db:/app/db
|
||||
--network=bridge
|
||||
--workdir=/app
|
||||
-p 8080:8080
|
||||
--restart=no
|
||||
--runtime=runc
|
||||
-d rust-api:1.0.0
|
||||
|
||||
|
||||
|
||||
docker run `
|
||||
--name hotel-api `
|
||||
-e JWT_SECRET=your_jwt_secret_key `
|
||||
-v "/w/DEV/hotel-api-rs/db:/app/db" `
|
||||
-p 8080:8080 `
|
||||
rust-api:1.0.1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BAD
|
||||
|
||||
"Mounts": [
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "/w/DEV/hotel-api-rs/db",
|
||||
"Destination": "/app/db ",
|
||||
"Mode": "",
|
||||
"RW": true,
|
||||
"Propagation": "rprivate"
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
"Mounts": [
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "/w/DEV/hotel-api-rs/db",
|
||||
"Destination": "/app/db",
|
||||
"Mode": "",
|
||||
"RW": true,
|
||||
"Propagation": "rprivate"
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
"Mounts": [
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "W:\\DEV\\hotel-api-rs\\db\\db.sqlite",
|
||||
"Destination": "/app/db/db.sqlite",
|
||||
"Mode": "",
|
||||
"RW": true,
|
||||
"Propagation": "rprivate"
|
||||
}
|
||||
],
|
||||
|
||||
GOOD
|
||||
|
||||
"Mounts": [
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "/w/DEV/hotel-api-rs/db",
|
||||
"Destination": "/app/db",
|
||||
"Mode": "",
|
||||
"RW": true,
|
||||
"Propagation": "rprivate"
|
||||
}
|
||||
],
|
||||
Reference in New Issue
Block a user