8 changed files with 285 additions and 31 deletions
@ -1 +1,3 @@ |
|||||
/target |
/target |
||||
|
*.db |
||||
|
*.lock |
||||
|
|||||
@ -1,8 +1,21 @@ |
|||||
[package] |
[package] |
||||
name = "FreeID" |
name = "free_id" |
||||
version = "0.1.0" |
version = "0.1.0" |
||||
edition = "2021" |
edition = "2021" |
||||
|
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||
|
|
||||
[dependencies] |
[dependencies] |
||||
|
#httparse = "1.7.0" |
||||
|
serde = "1.0.136" |
||||
|
serde_json = "1.0" |
||||
|
rusqlite = { version = "0.27.0", features = ["bundled"] } |
||||
|
rocket = "0.5.0-rc.1" |
||||
|
|
||||
|
[dependencies.uuid] |
||||
|
version = "1.0.0" |
||||
|
features = [ |
||||
|
"v4", # Lets you generate random UUIDs |
||||
|
"fast-rng", # Use a faster (but still sufficiently random) RNG |
||||
|
"macro-diagnostics", # Enable better diagnostics for compile-time UUIDs |
||||
|
] |
||||
|
|||||
@ -0,0 +1,29 @@ |
|||||
|
ARG BUILD_TAG=1.56.1 |
||||
|
ARG RUN_TAG=alpine |
||||
|
#$BUILD_TAG |
||||
|
|
||||
|
FROM rust:$BUILD_TAG as builder |
||||
|
|
||||
|
WORKDIR /usr/src/ |
||||
|
RUN USER=root cargo new --bin free_id |
||||
|
WORKDIR /usr/src/free_id |
||||
|
|
||||
|
# Compile dependencies |
||||
|
COPY Cargo.toml Cargo.lock ./ |
||||
|
RUN cargo build --locked --release |
||||
|
|
||||
|
# Remove bins to make sure we rebuild |
||||
|
# hadolint ignore=DL3059 |
||||
|
RUN rm ./target/release/deps/free_id* |
||||
|
|
||||
|
COPY src ./src |
||||
|
RUN cargo build --release |
||||
|
|
||||
|
FROM rust:$RUN_TAG |
||||
|
WORKDIR /app |
||||
|
COPY --from=builder /usr/src/free_id/target/release/free_id /usr/local/bin/ |
||||
|
|
||||
|
EXPOSE 8000 |
||||
|
ENV ROCKET_ADDRESS=0.0.0.0 |
||||
|
|
||||
|
CMD ["/usr/local/bin/free_id"] |
||||
@ -0,0 +1,5 @@ |
|||||
|
mod user; |
||||
|
|
||||
|
pub use crate::api::user::{ |
||||
|
routes as user_routes |
||||
|
}; |
||||
@ -0,0 +1,58 @@ |
|||||
|
use rocket::Route; |
||||
|
use serde::Deserialize; |
||||
|
use rusqlite::Connection; |
||||
|
use uuid::Uuid; |
||||
|
|
||||
|
#[derive(Debug, Deserialize)] |
||||
|
struct NewAccount { |
||||
|
firstname: String, |
||||
|
lastname: String |
||||
|
} |
||||
|
|
||||
|
pub fn routes() -> Vec<Route> { |
||||
|
routes![delete_user, add_user] |
||||
|
} |
||||
|
|
||||
|
#[delete("/user/<id>/delete")] |
||||
|
fn delete_user(id: &str) -> String { |
||||
|
format!("Preparing deletion for user {}", id) |
||||
|
} |
||||
|
|
||||
|
#[post("/user", format = "application/json", data = "<data>")] |
||||
|
fn add_user(data: &str) -> String { |
||||
|
|
||||
|
match serde_json::from_str(data) { |
||||
|
Ok(acc) => { |
||||
|
let account: NewAccount = acc; |
||||
|
println!("User {} {} prepared for creation", account.firstname, account.lastname); |
||||
|
|
||||
|
match Connection::open("freeid.db") { |
||||
|
Ok(connection) => { |
||||
|
let id = Uuid::new_v4().hyphenated().to_string(); |
||||
|
match connection.execute("INSERT INTO accounts (id, firstname, lastname) VALUES (:id, :firstname, :lastname)",
|
||||
|
&[(":id", &id), (":firstname", &account.firstname), (":lastname", &account.lastname)] |
||||
|
) { |
||||
|
Ok(updated) => { |
||||
|
println!("Account with ID {} created", id); |
||||
|
println!("{} accounts were updated", updated); |
||||
|
format!("Account with ID {} created", id) |
||||
|
}, |
||||
|
Err(err) => { |
||||
|
println!("update on accounts failed: {}", err); |
||||
|
format!("Error {}", err) |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
Err(err) => { |
||||
|
println!("{}", err); |
||||
|
format!("Error {}", err) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
Err(err) => { |
||||
|
println!("{}", err); |
||||
|
format!("Error {}", err) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
use rusqlite::{Connection, Result}; |
||||
|
|
||||
|
pub fn init_db() -> Result<()>{ |
||||
|
let conn = Connection::open("freeid.db")?; |
||||
|
println!("DB opened"); |
||||
|
//let conn = Connection::open_in_memory()?;
|
||||
|
conn.execute( |
||||
|
"CREATE TABLE IF NOT EXISTS accounts ( |
||||
|
id TEXT primary key, |
||||
|
firstname TEXT , |
||||
|
lastname TEXT
|
||||
|
)", |
||||
|
[] |
||||
|
)?; |
||||
|
|
||||
|
conn.execute( |
||||
|
"CREATE TABLE IF NOT EXISTS authtokens ( |
||||
|
id TEXT primary key, |
||||
|
accountID TEXT references accounts(id), |
||||
|
validFrom TEXT , |
||||
|
validUntil TEXT
|
||||
|
)", |
||||
|
[] |
||||
|
)?; |
||||
|
|
||||
|
println!("Created tables"); |
||||
|
|
||||
|
match conn.execute("INSERT INTO accounts (id, firstname, lastname) VALUES (:id, :firstname, :lastname)",
|
||||
|
&[(":id", "4711"), (":firstname", "Klaus"), (":lastname", "Mustermann")] //, &"Test", &"User"]
|
||||
|
) { |
||||
|
Ok(updated) => println!("{} accounts were updated", updated), |
||||
|
Err(err) => println!("update on accounts failed: {}", err), |
||||
|
} |
||||
|
|
||||
|
match conn.execute("INSERT INTO authtokens (id, accountID, validFrom, validUntil) VALUES (?1, ?2, ?3, ?4)",
|
||||
|
&[&"992756", &"4711", &"2022-04-25 14:30:00.000", &"2023-04-25 14:30:00.000"] |
||||
|
) { |
||||
|
Ok(updated) => println!("{} authtokens were updated", updated), |
||||
|
Err(err) => println!("update on authtokens failed: {}", err), |
||||
|
} |
||||
|
|
||||
|
Ok(()) |
||||
|
|
||||
|
} |
||||
@ -1,44 +1,137 @@ |
|||||
use std::io::prelude::*; |
#[macro_use] |
||||
use std::net::TcpListener; |
extern crate rocket; |
||||
use std::net::TcpStream; |
|
||||
|
|
||||
fn main() { |
/* use rocket::response::Responder;
|
||||
let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); |
use rocket::http::{ContentType, Header}; */ |
||||
|
|
||||
for stream in listener.incoming() { |
use rusqlite::Connection; |
||||
let stream = stream.unwrap(); |
|
||||
|
|
||||
handle_connection(stream); |
mod api; |
||||
|
mod db; |
||||
|
|
||||
|
#[derive(Debug)] |
||||
|
struct AuthToken { |
||||
|
id: i32, |
||||
|
account_id: i32, |
||||
|
valid_from: String, |
||||
|
valid_until: String |
||||
|
} |
||||
|
|
||||
|
/* #[derive(Debug, Deserialize)]
|
||||
|
struct Account { |
||||
|
id: i32, |
||||
|
firstname: String, |
||||
|
lastname: String |
||||
|
} */ |
||||
|
|
||||
|
/* #[derive(Debug)]
|
||||
|
struct EMail { |
||||
|
address: String, |
||||
|
description: String |
||||
|
} */ |
||||
|
|
||||
|
fn get_auth_token(token: &str) -> AuthToken { |
||||
|
let mut result: AuthToken = AuthToken { |
||||
|
id: 0, |
||||
|
account_id: 0, |
||||
|
valid_from: String::from(""), |
||||
|
valid_until: String::from("") |
||||
|
}; |
||||
|
|
||||
|
let conn = Connection::open("freeid.db"); |
||||
|
|
||||
|
match conn { |
||||
|
Ok(connection) => { |
||||
|
let stmt = connection.prepare("SELECT id, accountID, validFrom, validUntil FROM authtokens WHERE id = :id"); |
||||
|
match stmt { |
||||
|
Ok(mut statement) => { |
||||
|
let auth_tokens = statement.query_map(&[(":id", token)], |row| { |
||||
|
Ok(AuthToken { |
||||
|
id: row.get(0)?, |
||||
|
account_id: row.get(1)?, |
||||
|
valid_from: row.get(2)?, |
||||
|
valid_until: row.get(3)? |
||||
|
}) |
||||
|
}); |
||||
|
match auth_tokens { |
||||
|
Ok(auth_tokens_iter) => { |
||||
|
for auth_token_res in auth_tokens_iter { |
||||
|
match auth_token_res { |
||||
|
Ok(auth_token) => { |
||||
|
result = auth_token; |
||||
|
} |
||||
|
Err(err) => { |
||||
|
println!("Error: {}", err); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
Err(err) => { |
||||
|
println!("Error: {}", err); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
Err(err) => { |
||||
|
println!("Error: {}", err); |
||||
|
} |
||||
|
} |
||||
|
}
|
||||
|
Err(err) => { |
||||
|
println!("Error: {}", err); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
fn getit(slice: &[u8]) -> String { |
result |
||||
let value = format!("{}{}{}{}{}{}", slice[8]-48, slice[9]-48, slice[10]-48, slice[11]-48, slice[12]-48, slice[13]-48); |
} |
||||
|
|
||||
|
fn remove_brackets(value: &str) -> &str { |
||||
|
if value.starts_with('[') && value.ends_with(']') { |
||||
|
let mut chars = value.chars(); |
||||
|
chars.next(); |
||||
|
chars.next_back(); |
||||
|
chars.as_str() |
||||
|
} |
||||
|
else { |
||||
value |
value |
||||
} |
} |
||||
|
} |
||||
|
|
||||
fn handle_connection(mut stream: TcpStream) { |
#[get("/")] |
||||
let mut buffer = [0; 1024]; |
fn index() -> &'static str { |
||||
|
"Hello, world!" |
||||
|
} |
||||
|
|
||||
stream.read(&mut buffer).unwrap(); |
#[get("/id/<token>/options/<options>", rank = 1)] |
||||
|
fn id_options(token: &str, options: &str) -> String { |
||||
|
println!("Route: Id -> {}", token); |
||||
|
let auth_token = get_auth_token(token); |
||||
|
let options = remove_brackets(options); |
||||
|
format!("Auth Token {} for Account {} with options [{}]", auth_token.id, auth_token.account_id, options) |
||||
|
} |
||||
|
|
||||
println!("Request: {}", String::from_utf8_lossy(&buffer[..])); |
#[get("/id/<token>", rank = 2)] |
||||
|
fn id(token: &str) -> String { |
||||
|
println!("Route: Id -> {}", token); |
||||
|
let auth_token = get_auth_token(token); |
||||
|
format!("Auth Token {} for Account {}", auth_token.id, auth_token.account_id) |
||||
|
} |
||||
|
|
||||
let get_id = b"GET /id/"; |
#[get("/health")] |
||||
let get_auth = b"GET /auth/"; |
fn health() -> String { |
||||
let mut response = ""; |
String::from("200 OK") |
||||
|
} |
||||
|
|
||||
if buffer.starts_with(get_id) { |
#[launch] |
||||
response = "HTTP/1.1 200 OK\r\n\r\n"; |
fn rocket() -> _ { |
||||
//req_id = buffer[8 .. 13];
|
match db::init_db() { |
||||
println!("ID Requested: {}", getit(&buffer)); |
Ok(_) => { |
||||
|
println!("Database initiated"); |
||||
|
}, |
||||
|
Err(err) => { |
||||
|
println!("Error {}", err); |
||||
} |
} |
||||
else if buffer.starts_with(get_auth) { |
|
||||
response = "HTTP/1.1 404 NOT FOUND\r\n\r\n"; |
|
||||
println!("Auth Requested"); |
|
||||
} |
} |
||||
|
rocket::build(). |
||||
|
mount("/", routes![index, id, id_options, health]). |
||||
stream.write(response.as_bytes()).unwrap(); |
mount("/api", api::user_routes()) |
||||
stream.flush().unwrap(); |
|
||||
} |
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
{ |
||||
|
"user": "12345", |
||||
|
"firstname": "Test", |
||||
|
"lastname": "User", |
||||
|
|
||||
|
"email": [ |
||||
|
{ "address": "test@test.com" }, |
||||
|
{ "address": "another@test.com" } |
||||
|
] |
||||
|
} |
||||
Loading…
Reference in new issue