Browse Source

Refactoring Api

main
therealchfkch 4 years ago
parent
commit
079e47324d
  1. 2
      .gitignore
  2. 15
      Cargo.toml
  3. 29
      Dockerfile
  4. 5
      src/api/mod.rs
  5. 58
      src/api/user.rs
  6. 44
      src/db/mod.rs
  7. 153
      src/main.rs
  8. 10
      test.json

2
.gitignore

@ -1 +1,3 @@
/target
*.db
*.lock

15
Cargo.toml

@ -1,8 +1,21 @@
[package]
name = "FreeID"
name = "free_id"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[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
]

29
Dockerfile

@ -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"]

5
src/api/mod.rs

@ -0,0 +1,5 @@
mod user;
pub use crate::api::user::{
routes as user_routes
};

58
src/api/user.rs

@ -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)
}
}
}

44
src/db/mod.rs

@ -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(())
}

153
src/main.rs

@ -1,44 +1,137 @@
use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;
#[macro_use]
extern crate rocket;
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
/* use rocket::response::Responder;
use rocket::http::{ContentType, Header}; */
for stream in listener.incoming() {
let stream = stream.unwrap();
use rusqlite::Connection;
handle_connection(stream);
}
}
mod api;
mod db;
fn getit(slice: &[u8]) -> String {
let value = format!("{}{}{}{}{}{}", slice[8]-48, slice[9]-48, slice[10]-48, slice[11]-48, slice[12]-48, slice[13]-48);
value
#[derive(Debug)]
struct AuthToken {
id: i32,
account_id: i32,
valid_from: String,
valid_until: String
}
fn handle_connection(mut stream: TcpStream) {
let mut buffer = [0; 1024];
/* #[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("")
};
stream.read(&mut buffer).unwrap();
let conn = Connection::open("freeid.db");
println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
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);
}
}
let get_id = b"GET /id/";
let get_auth = b"GET /auth/";
let mut response = "";
result
}
if buffer.starts_with(get_id) {
response = "HTTP/1.1 200 OK\r\n\r\n";
//req_id = buffer[8 .. 13];
println!("ID Requested: {}", getit(&buffer));
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 if buffer.starts_with(get_auth) {
response = "HTTP/1.1 404 NOT FOUND\r\n\r\n";
println!("Auth Requested");
else {
value
}
}
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
#[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)
}
#[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)
}
#[get("/health")]
fn health() -> String {
String::from("200 OK")
}
stream.write(response.as_bytes()).unwrap();
stream.flush().unwrap();
}
#[launch]
fn rocket() -> _ {
match db::init_db() {
Ok(_) => {
println!("Database initiated");
},
Err(err) => {
println!("Error {}", err);
}
}
rocket::build().
mount("/", routes![index, id, id_options, health]).
mount("/api", api::user_routes())
}

10
test.json

@ -0,0 +1,10 @@
{
"user": "12345",
"firstname": "Test",
"lastname": "User",
"email": [
{ "address": "test@test.com" },
{ "address": "another@test.com" }
]
}
Loading…
Cancel
Save