forked from mgl_crew/Mitgliederladen
Compare commits
No commits in common. "backend" and "main" have entirely different histories.
10 changed files with 55 additions and 323 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
||||||
.idea
|
.idea
|
||||||
db/*
|
db/*
|
||||||
|
backend/target/*
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "server"
|
|
||||||
version = "1.0.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
# rust
|
|
||||||
actix-web ="4"
|
|
||||||
actix-files = "*"
|
|
||||||
utoipa-swagger-ui = { version = "3", features = ["actix-web"] }
|
|
||||||
|
|
||||||
# db-connection
|
|
||||||
sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls", "sqlite"]}
|
|
||||||
tokio = { version = "1.20.0", features = ["macros"]}
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "webserver"
|
|
||||||
path = "src/main.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "db_access"
|
|
||||||
path = "src/main_db.rs"
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"openapi": "3.0.0",
|
|
||||||
"info": {
|
|
||||||
"title": "My API",
|
|
||||||
"version": "1.0"
|
|
||||||
},
|
|
||||||
"paths": {
|
|
||||||
"/example": {
|
|
||||||
"get": {
|
|
||||||
"summary": "Get example",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
# installation
|
|
||||||
|
|
||||||
Rustup gets you the ability to install rust in any version, from stable to cutting edge.
|
|
||||||
|
|
||||||
## Linux, macos (step 1)
|
|
||||||
|
|
||||||
use apt, pacman, curl, brew or whatever, to install _rustup_.
|
|
||||||
|
|
||||||
## windows (alternate step 1)
|
|
||||||
|
|
||||||
choco install -y rustup
|
|
||||||
|
|
||||||
## Always (steps 2 and so on)
|
|
||||||
|
|
||||||
- `rustup-init.sh` (Windows: rustup-init.ex, e.g. %AppData%\Local\Temp\chocolatey\rustup.install\1.25.1\rustup-init.exe)
|
|
||||||
- select a good match in the dialog of this CLI installer,
|
|
||||||
- i.e. stable and default amount of features should be fine
|
|
||||||
- rust comes with `cargo` as a ``crate'' manager for package installation
|
|
||||||
|
|
||||||
## Get dependencies and run
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cargo build # gets dependencies from Cargo.toml
|
|
||||||
cargo run # re-runs on (some?) changes
|
|
||||||
```
|
|
|
@ -1,30 +0,0 @@
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
|
||||||
use utoipa_swagger_ui::{get_swagger_ui, DefaultConfig};
|
|
||||||
|
|
||||||
#[actix_web::main]
|
|
||||||
async fn main() -> std::io::Result<()> {
|
|
||||||
HttpServer::new(|| {
|
|
||||||
let swagger_config = DefaultConfig::new("http://localhost:8080", "/openapi.json");
|
|
||||||
App::new()
|
|
||||||
.service(get_swagger_ui(&swagger_config))
|
|
||||||
.route("/openapi.json", web::get().to(get_openapi_spec))
|
|
||||||
})
|
|
||||||
.bind("0.0.0.0:8080")?
|
|
||||||
.run()
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_openapi_spec() -> HttpResponse {
|
|
||||||
let openapi_spec = r#"
|
|
||||||
{
|
|
||||||
"openapi": "3.0.0",
|
|
||||||
"info": {
|
|
||||||
"title": "Dummy API",
|
|
||||||
"version": "1.0"
|
|
||||||
},
|
|
||||||
"paths": {}
|
|
||||||
}
|
|
||||||
"#;
|
|
||||||
|
|
||||||
HttpResponse::Ok().body(openapi_spec)
|
|
||||||
}
|
|
|
@ -1,225 +0,0 @@
|
||||||
use sqlx::{migrate::MigrateDatabase, FromRow, Sqlite, SqlitePool};
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
const DB_URL: &str = "sqlite://db/test.db";
|
|
||||||
|
|
||||||
const COMMANDS :[(i32, &str, &str); 5] = [
|
|
||||||
(0, "createDB", "creates the database if not already."),
|
|
||||||
(1, "initDB", "initializes the data of the db with given file"),
|
|
||||||
(2, "connect", "connecting to the db."),
|
|
||||||
(3, "execute sql", "execute SQL that is entered"),
|
|
||||||
(4, "disconnect", "closing connection to db."),
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Clone, FromRow, Debug)]
|
|
||||||
struct User {
|
|
||||||
id: i64,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
// game loop
|
|
||||||
|
|
||||||
let mut db: Option<SqlitePool> = None;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
println!("What do you want to do?\n");
|
|
||||||
print_commands();
|
|
||||||
println!("");
|
|
||||||
|
|
||||||
let mut choice = String::new();
|
|
||||||
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut choice)
|
|
||||||
.expect("Failed to read line");
|
|
||||||
|
|
||||||
let choice: u32 = choice
|
|
||||||
.trim()
|
|
||||||
.parse()
|
|
||||||
.expect("Please type a number!");
|
|
||||||
|
|
||||||
match choice {
|
|
||||||
0 => create_db().await,
|
|
||||||
1 => init_db(),
|
|
||||||
2 => db = connect_db().await,
|
|
||||||
3 => execute_sql(&db).await,
|
|
||||||
4 => {
|
|
||||||
db.clone().unwrap().close().await;
|
|
||||||
db = None;
|
|
||||||
}
|
|
||||||
_ => println!("This Command does not exists")
|
|
||||||
}
|
|
||||||
println!("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_commands() {
|
|
||||||
|
|
||||||
for command in COMMANDS {
|
|
||||||
let (num, name, desc) = command;
|
|
||||||
|
|
||||||
println!("{num}. {name} \t{desc}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_db() {
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
if !Sqlite::database_exists(DB_URL).await.unwrap_or(false) {
|
|
||||||
println!("Creating database {}", DB_URL);
|
|
||||||
match Sqlite::create_database(DB_URL).await {
|
|
||||||
Ok(_) => println!("Create db success"),
|
|
||||||
Err(error) => panic!("error: {}", error),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("database already exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_db() {
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn connect_db() -> Option<SqlitePool>{
|
|
||||||
|
|
||||||
let db = Some(SqlitePool::connect(DB_URL).await.unwrap());
|
|
||||||
println!("Connected to DB.");
|
|
||||||
return db;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn execute_sql(opt_db: &Option<SqlitePool>) {
|
|
||||||
|
|
||||||
if opt_db.is_none() {
|
|
||||||
println!("There is no active connection to the db.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let db = opt_db.clone().unwrap();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut choice = String::new();
|
|
||||||
|
|
||||||
println!("0: freely (danger!)\n1: create \n2: insert\n3: query\n4: delete\n5: drop table");
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut choice)
|
|
||||||
.expect("Failed to read line");
|
|
||||||
|
|
||||||
let choice: u32 = choice
|
|
||||||
.trim()
|
|
||||||
.parse()
|
|
||||||
.expect("Please type a number!");
|
|
||||||
|
|
||||||
match choice {
|
|
||||||
0 => freely(&db).await,
|
|
||||||
1 => create(&db).await,
|
|
||||||
2 => insert(&db).await,
|
|
||||||
3 => query(&db).await,
|
|
||||||
4 => delete(&db).await,
|
|
||||||
5 => drop_table(&db).await,
|
|
||||||
_ => {
|
|
||||||
println!("This Command does not exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create(db : &SqlitePool) {
|
|
||||||
let result = sqlx::query(
|
|
||||||
"CREATE TABLE IF NOT EXISTS users (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
|
||||||
name WARCHAR(250) NOT NULL
|
|
||||||
);")
|
|
||||||
.execute(db)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("Create user table result: {:?}", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn insert(db : &SqlitePool) {
|
|
||||||
|
|
||||||
let mut name = String::new();
|
|
||||||
|
|
||||||
println!("insert what name?");
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut name)
|
|
||||||
.expect("Failed to read line");
|
|
||||||
|
|
||||||
let result = sqlx::query("INSERT INTO users (name) VALUES (?)")
|
|
||||||
.bind(name)
|
|
||||||
.execute(db)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("result: {:?}", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn query(db : &SqlitePool) {
|
|
||||||
|
|
||||||
let data = match sqlx::query_as::<_, User>("SELECT id, name FROM users")
|
|
||||||
.fetch_all(db)
|
|
||||||
.await {
|
|
||||||
Ok(d) => d,
|
|
||||||
Err(_) => {
|
|
||||||
println!("something went wrong.");
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for user in data {
|
|
||||||
println!("[{}] name: {}", user.id, &user.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete(db : &SqlitePool) {
|
|
||||||
|
|
||||||
let mut name = String::new();
|
|
||||||
|
|
||||||
println!("delete what name?");
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut name)
|
|
||||||
.expect("Failed to read line");
|
|
||||||
|
|
||||||
let result = match sqlx::query("DELETE FROM users WHERE name=$1")
|
|
||||||
.bind(name)
|
|
||||||
.execute(db)
|
|
||||||
.await {
|
|
||||||
Ok(r) => Some(r),
|
|
||||||
Err(_) => {
|
|
||||||
println!("user could not be deleted.");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if result.is_some() {
|
|
||||||
println!("result: {:?}", result.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn freely(db : &SqlitePool) {
|
|
||||||
|
|
||||||
let mut sql = String::new();
|
|
||||||
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut sql)
|
|
||||||
.expect("Failed to read line");
|
|
||||||
|
|
||||||
let result = sqlx::query(&sql)
|
|
||||||
.execute(db)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("result: {:?}", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn drop_table(db : &SqlitePool) {
|
|
||||||
let result = sqlx::query("DROP TABLE users;")
|
|
||||||
.execute(db)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("result: {:?}", result);
|
|
||||||
}
|
|
0
backend/.gitignore → server/.gitignore
vendored
0
backend/.gitignore → server/.gitignore
vendored
10
server/Cargo.toml
Normal file
10
server/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "server"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web ="4"
|
||||||
|
utoipa = { version = "3", features = ["actix_extras"] }
|
15
server/readme.md
Normal file
15
server/readme.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# installation
|
||||||
|
|
||||||
|
## windows (step 1)
|
||||||
|
|
||||||
|
choco install -y
|
||||||
|
|
||||||
|
## Linux, macos (alernate step 1)
|
||||||
|
|
||||||
|
use apt, pacman, curl, brew or whatever.
|
||||||
|
|
||||||
|
## Always (steps 2 and so on)
|
||||||
|
|
||||||
|
- `rustup-init.sh` (Windows: rustup-init.ex, e.g. %AppData%\Local\Temp\chocolatey\rustup.install\1.25.1\rustup-init.exe)
|
||||||
|
- select a good match in the dialog of this CLI installer
|
||||||
|
|
28
server/src/main.rs
Normal file
28
server/src/main.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
async fn hello() -> impl Responder {
|
||||||
|
HttpResponse::Ok().body("Hello world!")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/echo")]
|
||||||
|
async fn echo(req_body: String) -> impl Responder {
|
||||||
|
HttpResponse::Ok().body(req_body)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn manual_hello() -> impl Responder {
|
||||||
|
HttpResponse::Ok().body("Hey there!")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
HttpServer::new(|| {
|
||||||
|
App::new()
|
||||||
|
.service(hello)
|
||||||
|
.service(echo)
|
||||||
|
.route("/hey", web::get().to(manual_hello))
|
||||||
|
})
|
||||||
|
.bind(("127.0.0.1", 8080))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
Loading…
Reference in a new issue