forked from Roflin/gamenight
Compare commits
55 Commits
user-syste
...
main
Author | SHA1 | Date | |
---|---|---|---|
28f7306d57 | |||
3f51d52edf | |||
f0883a0ff0 | |||
fbe456a0f5 | |||
d11e31149b | |||
db6f55bc47 | |||
d1832bc794 | |||
f1d23cb495 | |||
156be1821a | |||
6950ac62e8 | |||
597a960bf1 | |||
|
3f7ed03973 | ||
c994321576 | |||
4e26d3cdcb | |||
fce0ebd76b | |||
6699dcf392 | |||
db25dc0aed | |||
02913c7b52 | |||
|
9e84a62c41 | ||
22f05c00c1 | |||
b2aba31264 | |||
|
1296f363af | ||
|
70ae15f655 | ||
3509a70a6a | |||
217e5ee64b | |||
5216f55a14 | |||
534e6867d8 | |||
1c8110cdb0 | |||
d961896242 | |||
7741c1dbae | |||
65d2dece55 | |||
34737bfb6b | |||
5ace39d820 | |||
b7f981e3a6 | |||
f7f9f7456b | |||
cfaa6ebdb1 | |||
8a318e877f | |||
bcfcf66df5 | |||
83a0b5ad9d | |||
9de8ffaa2d | |||
102a3e6082 | |||
639405bf9f | |||
2ba2026e21 | |||
86cdbedd41 | |||
836a4ab59f | |||
5c27be0191 | |||
1a6ead4760 | |||
5ffeea6553 | |||
cc26aed9a5 | |||
92e0257e74 | |||
0a214ca388 | |||
2cfaf2b4cc | |||
bf796201bf | |||
56d0889963 | |||
d80f705b5d |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,4 @@
|
|||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
.vscode
|
.vscode
|
||||||
|
3
backend-actix/.gitignore
vendored
Normal file
3
backend-actix/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target
|
||||||
|
src/models/
|
||||||
|
docs/
|
3031
backend/Cargo.lock → backend-actix/Cargo.lock
generated
3031
backend/Cargo.lock → backend-actix/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
20
backend-actix/Cargo.toml
Normal file
20
backend-actix/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "backend-actix"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gamenight-database = { path = "../gamenight-database"}
|
||||||
|
actix-web = "4"
|
||||||
|
actix-cors = "0.7"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
uuid = { version = "1.3.0", features = ["serde", "v4"] }
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
jsonwebtoken = "9.3"
|
||||||
|
validator = { version = "0.20", features = ["derive"] }
|
||||||
|
rand_core = { version = "0.9" }
|
||||||
|
env_logger = "0.11"
|
||||||
|
tracing-actix-web = "0.7"
|
30
backend-actix/build.rs
Normal file
30
backend-actix/build.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use std::{fs::{exists, read_dir, remove_dir_all, File}, io::Write, process::Command};
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo::rerun-if-changed=gamenight-api.yaml");
|
||||||
|
|
||||||
|
if exists("src/models").unwrap() {
|
||||||
|
remove_dir_all("src/models").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
Command::new("openapi-generator")
|
||||||
|
.args(["generate", "-i", "gamenight-api.yaml", "-g", "rust", "--global-property", "models"])
|
||||||
|
.output()
|
||||||
|
.expect("Failed to generate models sources for the gamenight API");
|
||||||
|
|
||||||
|
let mut file = File::create("src/models/mod.rs").unwrap();
|
||||||
|
let paths = read_dir("./src/models").unwrap();
|
||||||
|
for path in paths {
|
||||||
|
let path = path.unwrap();
|
||||||
|
let path = path.path();
|
||||||
|
let stem = path.file_stem().unwrap();
|
||||||
|
if stem == "mod" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
let line = format!("pub mod {};\n", stem.to_str().unwrap());
|
||||||
|
let _ = file.write(line.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
447
backend-actix/gamenight-api.yaml
Normal file
447
backend-actix/gamenight-api.yaml
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: Gamenight
|
||||||
|
version: '1.0'
|
||||||
|
contact:
|
||||||
|
name: Dennis Brentjes
|
||||||
|
email: dennis@brentj.es
|
||||||
|
url: 'https://brentj.es'
|
||||||
|
description: Api specifaction for a Gamenight server
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: 'http://localhost:8080'
|
||||||
|
description: Gamenight
|
||||||
|
paths:
|
||||||
|
/token:
|
||||||
|
get:
|
||||||
|
summary: ''
|
||||||
|
operationId: get-token
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/TokenResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/LoginRequest'
|
||||||
|
description: Submit your credentials to get a JWT-token to use with the rest of the api.
|
||||||
|
parameters: []
|
||||||
|
post:
|
||||||
|
summary: ''
|
||||||
|
operationId: post-token
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/TokenResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
description: Refresh your JWT-token without logging in again.
|
||||||
|
parameters: []
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
/user:
|
||||||
|
post:
|
||||||
|
summary: ''
|
||||||
|
operationId: post-register
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/RegisterRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: ''
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
description: 'Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.'
|
||||||
|
parameters: []
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
get:
|
||||||
|
description: 'Get a user from primary id'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/GetUserRequest'
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/UserResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'404':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
/gamenights:
|
||||||
|
get:
|
||||||
|
summary: Get a all gamenights
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/GamenightsResponse'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
operationId: get-gamenights
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
description: Retrieve the list of gamenights on this gamenight server. Requires authorization.
|
||||||
|
/participants:
|
||||||
|
get:
|
||||||
|
summary: Get all participants for a gamenight
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/ParticipantsResponse'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/GetParticipants'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
description: Retrieve the participants of a single gamenight by id.
|
||||||
|
/gamenight:
|
||||||
|
post:
|
||||||
|
summary: ''
|
||||||
|
operationId: post-gamenight
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/AddGamenight'
|
||||||
|
description: 'Add a gamenight by providing a name and a date, only available when providing an JWT token.'
|
||||||
|
get:
|
||||||
|
summary: ''
|
||||||
|
operationId: get-gamenight
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/GamenightResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/GetGamenight'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
/join:
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/JoinGamenight'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
/leave:
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "OK"
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/LeaveGamenight'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
/games:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/GamesResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
/game:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
$ref: '#/components/responses/GameResponse'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/GetGameRequest'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: "OK"
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
'422':
|
||||||
|
$ref: '#/components/responses/FailureResponse'
|
||||||
|
requestBody:
|
||||||
|
$ref: '#/components/requestBodies/AddGameRequest'
|
||||||
|
security:
|
||||||
|
- JWT-Auth: []
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Gamenight:
|
||||||
|
title: Gamenight
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
datetime:
|
||||||
|
type: string
|
||||||
|
owner_id:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- datetime
|
||||||
|
- owner_id
|
||||||
|
Participants:
|
||||||
|
title: participants
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
participants:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- participants
|
||||||
|
Failure:
|
||||||
|
title: Failure
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
description: 'Failure Reason'
|
||||||
|
Token:
|
||||||
|
title: Token
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
jwt_token:
|
||||||
|
type: string
|
||||||
|
Login:
|
||||||
|
title: Login
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- username
|
||||||
|
- password
|
||||||
|
Registration:
|
||||||
|
title: Registration
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
password_repeat:
|
||||||
|
type: string
|
||||||
|
registration_token:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- username
|
||||||
|
- email
|
||||||
|
- password
|
||||||
|
- password_repeat
|
||||||
|
- registration_token
|
||||||
|
UserId:
|
||||||
|
title: UserId
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
user_id:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- user_id
|
||||||
|
AddGamenightRequestBody:
|
||||||
|
title: AddGamenightRequestBody
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
datetime:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- datetime
|
||||||
|
GamenightId:
|
||||||
|
title: GamenightId
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
gamenight_id:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- gamenight_id
|
||||||
|
GameId:
|
||||||
|
title: GameId
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
game_id:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- game_id
|
||||||
|
GetGamenightRequestBody:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
User:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- username
|
||||||
|
Game:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
AddGameRequestBody:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
|
||||||
|
requestBodies:
|
||||||
|
LoginRequest:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Login'
|
||||||
|
RegisterRequest:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Registration'
|
||||||
|
GetUserRequest:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/UserId'
|
||||||
|
AddGamenight:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/AddGamenightRequestBody'
|
||||||
|
GetGamenight:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GetGamenightRequestBody'
|
||||||
|
GetParticipants:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GamenightId'
|
||||||
|
JoinGamenight:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GamenightId'
|
||||||
|
LeaveGamenight:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GamenightId'
|
||||||
|
GetGameRequest:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GameId'
|
||||||
|
AddGameRequest:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/AddGameRequestBody'
|
||||||
|
responses:
|
||||||
|
TokenResponse:
|
||||||
|
description: Example response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Token'
|
||||||
|
FailureResponse:
|
||||||
|
description: Example response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Failure'
|
||||||
|
ParticipantsResponse:
|
||||||
|
description: Response with a list of participant uuids
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Participants'
|
||||||
|
GamenightsResponse:
|
||||||
|
description: Example response
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Gamenight'
|
||||||
|
GamenightResponse:
|
||||||
|
description: A gamenight being hosted
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Gamenight'
|
||||||
|
UserResponse:
|
||||||
|
description: A user in the gamenight system
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
GamesResponse:
|
||||||
|
description: A list of Games in this gamenight instance.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Game'
|
||||||
|
GameResponse:
|
||||||
|
description: A game.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Game'
|
||||||
|
securitySchemes:
|
||||||
|
JWT-Auth:
|
||||||
|
type: http
|
||||||
|
scheme: bearer
|
||||||
|
bearerFormat: JWT
|
||||||
|
description: ''
|
||||||
|
|
57
backend-actix/src/main.rs
Normal file
57
backend-actix/src/main.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#[allow(unused_imports)]
|
||||||
|
pub mod models;
|
||||||
|
pub mod request;
|
||||||
|
|
||||||
|
use actix_cors::Cors;
|
||||||
|
use actix_web::middleware::Logger;
|
||||||
|
use actix_web::HttpServer;
|
||||||
|
use actix_web::App;
|
||||||
|
use actix_web::http;
|
||||||
|
use actix_web::web;
|
||||||
|
use request::{*, login, register, gamenights};
|
||||||
|
use tracing_actix_web::TracingLogger;
|
||||||
|
use gamenight_database::*;
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
let url = "postgres://root:root@127.0.0.1/gamenight";
|
||||||
|
|
||||||
|
let pool = get_connection_pool(url);
|
||||||
|
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
run_migration(&mut conn);
|
||||||
|
|
||||||
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||||
|
|
||||||
|
HttpServer::new(move || {
|
||||||
|
let cors = Cors::default()
|
||||||
|
.allowed_origin("0.0.0.0")
|
||||||
|
.allowed_origin_fn(|_origin, _req_head| { true })
|
||||||
|
.allowed_methods(vec!["GET", "POST"])
|
||||||
|
.allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
|
||||||
|
.allowed_header(http::header::CONTENT_TYPE)
|
||||||
|
.max_age(3600);
|
||||||
|
|
||||||
|
App::new()
|
||||||
|
.wrap(cors)
|
||||||
|
.wrap(Logger::default())
|
||||||
|
.wrap(TracingLogger::default())
|
||||||
|
.app_data(web::Data::new(pool.clone()))
|
||||||
|
.service(login)
|
||||||
|
.service(refresh)
|
||||||
|
.service(register)
|
||||||
|
.service(gamenights)
|
||||||
|
.service(gamenight_post)
|
||||||
|
.service(gamenight_get)
|
||||||
|
.service(get_user)
|
||||||
|
.service(get_user_unauthenticated)
|
||||||
|
.service(post_join_gamenight)
|
||||||
|
.service(post_leave_gamenight)
|
||||||
|
.service(get_get_participants)
|
||||||
|
.service(get_games)
|
||||||
|
.service(post_game)
|
||||||
|
})
|
||||||
|
.bind(("::1", 8080))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
77
backend-actix/src/request/authorization.rs
Normal file
77
backend-actix/src/request/authorization.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use std::future::{Ready, ready};
|
||||||
|
|
||||||
|
use actix_web::{FromRequest, http, HttpRequest, dev::Payload, web::Data};
|
||||||
|
use chrono::Utc;
|
||||||
|
use jsonwebtoken::{encode, Header, EncodingKey, decode, DecodingKey, Validation};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use gamenight_database::{user::{get_user, User}, DbPool};
|
||||||
|
|
||||||
|
use super::error::ApiError;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Claims {
|
||||||
|
exp: i64,
|
||||||
|
uid: Uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AuthUser(pub User);
|
||||||
|
|
||||||
|
// pub struct AuthUser {
|
||||||
|
// pub id: Uuid,
|
||||||
|
// pub username: String,
|
||||||
|
// pub email: String,
|
||||||
|
// pub role: Role,
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl From<User> for AuthUser {
|
||||||
|
fn from(value: User) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_claims(req: &HttpRequest) -> Result<Claims, ApiError> {
|
||||||
|
let token = req.headers()
|
||||||
|
.get(http::header::AUTHORIZATION)
|
||||||
|
.map(|h| h.to_str().unwrap().split_at(7).1.to_string());
|
||||||
|
|
||||||
|
let token = token.ok_or(ApiError{
|
||||||
|
status: 400,
|
||||||
|
message: "JWT-token was not specified in the Authorization header as Bearer: token".to_string()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let secret = "secret";
|
||||||
|
Ok(decode::<Claims>(token.as_str(), &DecodingKey::from_secret(secret.as_bytes()), &Validation::default())?.claims)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_token(user: &User) -> Result<String, ApiError> {
|
||||||
|
let claims = Claims {
|
||||||
|
exp: Utc::now().timestamp() + chrono::Duration::days(7).num_seconds(),
|
||||||
|
uid: user.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
let secret = "secret";
|
||||||
|
Ok(encode(
|
||||||
|
&Header::default(),
|
||||||
|
&claims,
|
||||||
|
&EncodingKey::from_secret(secret.as_bytes()))?)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRequest for AuthUser {
|
||||||
|
type Error = ApiError;
|
||||||
|
type Future = Ready<Result<Self, Self::Error>>;
|
||||||
|
|
||||||
|
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
|
||||||
|
ready(
|
||||||
|
(|| -> Result<AuthUser, ApiError>{
|
||||||
|
let pool = req.app_data::<Data<DbPool>>().expect("No database configured");
|
||||||
|
let mut conn = pool.get().expect("couldn't get db connection from pool");
|
||||||
|
let uid = get_claims(req)?.uid;
|
||||||
|
let user = get_user(&mut conn, uid)?;
|
||||||
|
|
||||||
|
Ok(user.into())
|
||||||
|
})()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
91
backend-actix/src/request/error.rs
Normal file
91
backend-actix/src/request/error.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
use actix_web::{ResponseError, error::BlockingError, HttpResponse, http::{header::ContentType, StatusCode}};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use validator::ValidationErrors;
|
||||||
|
|
||||||
|
use gamenight_database::error::DatabaseError;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct ApiError {
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
pub status: u16,
|
||||||
|
pub message: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ApiError {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
|
write!(f, "{}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseError for ApiError {
|
||||||
|
fn error_response(&self) -> HttpResponse {
|
||||||
|
HttpResponse::build(StatusCode::from_u16(self.status).unwrap())
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&self).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DatabaseError> for ApiError {
|
||||||
|
fn from(value: DatabaseError) -> Self {
|
||||||
|
ApiError {
|
||||||
|
//Todo, split this in unrecoverable and schema error
|
||||||
|
status: 500,
|
||||||
|
message: value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BlockingError> for ApiError {
|
||||||
|
fn from(value: BlockingError) -> Self {
|
||||||
|
ApiError {
|
||||||
|
status: 500,
|
||||||
|
message: value.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_json::Error> for ApiError {
|
||||||
|
fn from(value: serde_json::Error) -> Self {
|
||||||
|
ApiError {
|
||||||
|
status: 500,
|
||||||
|
message: value.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<jsonwebtoken::errors::Error> for ApiError {
|
||||||
|
fn from(value: jsonwebtoken::errors::Error) -> Self {
|
||||||
|
ApiError {
|
||||||
|
status: 500,
|
||||||
|
message: value.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ValidationErrors> for ApiError {
|
||||||
|
fn from(value: ValidationErrors) -> Self {
|
||||||
|
ApiError {
|
||||||
|
status: 422,
|
||||||
|
message: value.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<chrono::ParseError> for ApiError {
|
||||||
|
fn from(value: chrono::ParseError) -> Self {
|
||||||
|
ApiError {
|
||||||
|
status: 422,
|
||||||
|
message: value.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<uuid::Error> for ApiError {
|
||||||
|
fn from(value: uuid::Error) -> Self {
|
||||||
|
ApiError {
|
||||||
|
status: 422,
|
||||||
|
message: value.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
backend-actix/src/request/game.rs
Normal file
39
backend-actix/src/request/game.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use actix_web::{get, http::header::ContentType, post, web, HttpResponse, Responder};
|
||||||
|
use gamenight_database::{game::insert_game, DbPool, GetConnection};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::{models::{add_game_request_body::AddGameRequestBody, game::Game}, request::{authorization::AuthUser, error::ApiError}};
|
||||||
|
|
||||||
|
#[get("/games")]
|
||||||
|
pub async fn get_games(pool: web::Data<DbPool>, _user: AuthUser) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
let games: Vec<gamenight_database::game::Game> = gamenight_database::games(&mut conn)?;
|
||||||
|
let model: Vec<Game> = games.iter().map(|x| {
|
||||||
|
Game {
|
||||||
|
id: x.id.to_string(),
|
||||||
|
name: x.name.clone(),
|
||||||
|
}}
|
||||||
|
).collect();
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&model)?)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddGameRequestBody> for gamenight_database::game::Game {
|
||||||
|
fn from(value: AddGameRequestBody) -> Self {
|
||||||
|
Self {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
name: value.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/game")]
|
||||||
|
pub async fn post_game(pool: web::Data<DbPool>, _user: AuthUser, game_data: web::Json<AddGameRequestBody>) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
insert_game(&mut conn, game_data.0.into())?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
}
|
70
backend-actix/src/request/gamenight_handlers.rs
Normal file
70
backend-actix/src/request/gamenight_handlers.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use actix_web::{get, web, Responder, http::header::ContentType, HttpResponse, post};
|
||||||
|
use chrono::{DateTime, ParseError};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use gamenight_database::{gamenight, DbPool, GetConnection};
|
||||||
|
|
||||||
|
use crate::{models::{add_gamenight_request_body::AddGamenightRequestBody, gamenight::Gamenight, get_gamenight_request_body::GetGamenightRequestBody}, request::authorization::AuthUser};
|
||||||
|
use crate::request::error::ApiError;
|
||||||
|
|
||||||
|
|
||||||
|
impl AddGamenightRequestBody {
|
||||||
|
pub fn into_with_user(&self, user: AuthUser) -> Result<gamenight::Gamenight, ParseError> {
|
||||||
|
Ok(gamenight::Gamenight {
|
||||||
|
datetime: DateTime::parse_from_rfc3339(&self.datetime)?.with_timezone(&chrono::Utc),
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
name: self.name.clone(),
|
||||||
|
owner_id: user.0.id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<GetGamenightRequestBody> for Uuid {
|
||||||
|
fn from(value: GetGamenightRequestBody) -> Self {
|
||||||
|
Uuid::parse_str(value.id.unwrap().as_str()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/gamenights")]
|
||||||
|
pub async fn gamenights(pool: web::Data<DbPool>, _user: AuthUser) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
let gamenights: Vec<gamenight::Gamenight> = gamenight_database::gamenights(&mut conn)?;
|
||||||
|
let model: Vec<Gamenight> = gamenights.iter().map(|x| {
|
||||||
|
Gamenight {
|
||||||
|
id: x.id.to_string(),
|
||||||
|
name: x.name.clone(),
|
||||||
|
datetime: x.datetime.to_rfc3339(),
|
||||||
|
owner_id: x.owner_id.to_string()
|
||||||
|
}}
|
||||||
|
).collect();
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&model)?)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/gamenight")]
|
||||||
|
pub async fn gamenight_post(pool: web::Data<DbPool>, user: AuthUser, gamenight_data: web::Json<AddGamenightRequestBody>) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
|
||||||
|
gamenight::add_gamenight(&mut conn, gamenight_data.into_with_user(user)?)?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/gamenight")]
|
||||||
|
pub async fn gamenight_get(pool: web::Data<DbPool>, _user: AuthUser, gamenight_data: web::Json<GetGamenightRequestBody>) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
let gamenight = gamenight::get_gamenight(&mut conn, gamenight_data.into_inner().into())?;
|
||||||
|
let model = Gamenight{
|
||||||
|
id: gamenight.id.to_string(),
|
||||||
|
datetime: gamenight.datetime.to_rfc3339(),
|
||||||
|
name: gamenight.name,
|
||||||
|
owner_id: gamenight.owner_id.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&model)?))
|
||||||
|
}
|
37
backend-actix/src/request/join_gamenight.rs
Normal file
37
backend-actix/src/request/join_gamenight.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use actix_web::{post, web, HttpResponse, Responder};
|
||||||
|
use gamenight_database::{gamenight_participants::{delete_gamenight_participant, insert_gamenight_participant, GamenightParticipant}, DbPool, GetConnection};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::{models::gamenight_id::GamenightId, request::{authorization::AuthUser, error::ApiError}};
|
||||||
|
|
||||||
|
#[post("/join")]
|
||||||
|
pub async fn post_join_gamenight(pool: web::Data<DbPool>, user: AuthUser, gamenight_id: web::Json<GamenightId>) -> Result<impl Responder, ApiError> {
|
||||||
|
web::block(move || -> Result<usize, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
Ok(insert_gamenight_participant(&mut conn, GamenightParticipant {
|
||||||
|
gamenight_id: Uuid::parse_str(&gamenight_id.gamenight_id)?,
|
||||||
|
user_id: user.0.id
|
||||||
|
})?)
|
||||||
|
}).await??;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/leave")]
|
||||||
|
pub async fn post_leave_gamenight(pool: web::Data<DbPool>, user: AuthUser, gamenight_id: web::Json<GamenightId>) -> Result<impl Responder, ApiError> {
|
||||||
|
web::block(move || -> Result<usize, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
let participant = GamenightParticipant {
|
||||||
|
gamenight_id: Uuid::parse_str(&gamenight_id.gamenight_id)?,
|
||||||
|
user_id: user.0.id
|
||||||
|
};
|
||||||
|
println!("{:?}", participant);
|
||||||
|
let x = delete_gamenight_participant(&mut conn, participant)?;
|
||||||
|
|
||||||
|
println!("Amount of deleted rows: {:?}", x);
|
||||||
|
|
||||||
|
Ok(x)
|
||||||
|
}).await??;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
}
|
22
backend-actix/src/request/mod.rs
Normal file
22
backend-actix/src/request/mod.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
mod user_handlers;
|
||||||
|
mod gamenight_handlers;
|
||||||
|
mod error;
|
||||||
|
mod authorization;
|
||||||
|
mod join_gamenight;
|
||||||
|
mod participant_handlers;
|
||||||
|
mod game;
|
||||||
|
|
||||||
|
pub use user_handlers::login;
|
||||||
|
pub use user_handlers::refresh;
|
||||||
|
pub use user_handlers::register;
|
||||||
|
pub use gamenight_handlers::gamenights;
|
||||||
|
pub use gamenight_handlers::gamenight_post;
|
||||||
|
pub use gamenight_handlers::gamenight_get;
|
||||||
|
pub use user_handlers::get_user;
|
||||||
|
pub use user_handlers::get_user_unauthenticated;
|
||||||
|
pub use join_gamenight::post_join_gamenight;
|
||||||
|
pub use join_gamenight::post_leave_gamenight;
|
||||||
|
pub use participant_handlers::get_get_participants;
|
||||||
|
pub use game::get_games;
|
||||||
|
pub use game::post_game;
|
17
backend-actix/src/request/participant_handlers.rs
Normal file
17
backend-actix/src/request/participant_handlers.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use actix_web::{get, http::header::ContentType, web, HttpResponse, Responder};
|
||||||
|
use gamenight_database::{DbPool, GetConnection};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::{models::{gamenight_id::GamenightId, participants::Participants}, request::{authorization::AuthUser, error::ApiError}};
|
||||||
|
|
||||||
|
#[get("/participants")]
|
||||||
|
pub async fn get_get_participants(pool: web::Data<DbPool>, _user: AuthUser, gamenight_info: web::Json<GamenightId>) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
|
||||||
|
let users = gamenight_database::get_participants(&mut conn, &Uuid::parse_str(&gamenight_info.into_inner().gamenight_id)?)?
|
||||||
|
.iter().map(|x| x.to_string()).collect();
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&Participants{participants: users})?))
|
||||||
|
}
|
165
backend-actix/src/request/user_handlers.rs
Normal file
165
backend-actix/src/request/user_handlers.rs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
|
||||||
|
use actix_web::http::header::ContentType;
|
||||||
|
use actix_web::{get, post, web, HttpResponse, Responder};
|
||||||
|
use gamenight_database::user::{count_users_with_email, count_users_with_username};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
use validator::{Validate, ValidateArgs, ValidationError};
|
||||||
|
use crate::models::login::Login;
|
||||||
|
use crate::models::registration::Registration;
|
||||||
|
use crate::models::token::Token;
|
||||||
|
use crate::models::user::User;
|
||||||
|
use crate::models::user_id::UserId;
|
||||||
|
use crate::request::error::ApiError;
|
||||||
|
use crate::request::authorization::get_token;
|
||||||
|
use serde_json;
|
||||||
|
use gamenight_database::{DbPool, GetConnection};
|
||||||
|
|
||||||
|
use super::authorization::AuthUser;
|
||||||
|
|
||||||
|
impl From<Login> for gamenight_database::user::LoginUser {
|
||||||
|
fn from(val: Login) -> Self {
|
||||||
|
gamenight_database::user::LoginUser {
|
||||||
|
username: val.username,
|
||||||
|
password: val.password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Registration> for gamenight_database::user::Register {
|
||||||
|
fn from(val: Registration) -> Self {
|
||||||
|
gamenight_database::user::Register {
|
||||||
|
email: val.email,
|
||||||
|
username: val.username,
|
||||||
|
password: val.password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RegisterContext<'v_a> {
|
||||||
|
pub pool: &'v_a DbPool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unique_username(username: &String, context: &RegisterContext) -> Result<(), ValidationError> {
|
||||||
|
let mut conn = context.pool.get_conn();
|
||||||
|
|
||||||
|
match count_users_with_username(&mut conn, username)
|
||||||
|
{
|
||||||
|
Ok(0) => Ok(()),
|
||||||
|
Ok(_) => Err(ValidationError::new("User already exists")),
|
||||||
|
Err(_) => Err(ValidationError::new("Database error while validating user")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unique_email(email: &String, context: &RegisterContext) -> Result<(), ValidationError> {
|
||||||
|
let mut conn = context.pool.get_conn();
|
||||||
|
|
||||||
|
match count_users_with_email(&mut conn, email)
|
||||||
|
{
|
||||||
|
Ok(0) => Ok(()),
|
||||||
|
Ok(_) => Err(ValidationError::new("email already exists")),
|
||||||
|
Err(_) => Err(ValidationError::new("Database error while validating email"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Validate)]
|
||||||
|
#[validate(context = RegisterContext::<'v_a>)]
|
||||||
|
pub struct ValidatableRegistration {
|
||||||
|
#[validate(
|
||||||
|
length(min = 1),
|
||||||
|
custom(function = "unique_username", use_context)
|
||||||
|
)]
|
||||||
|
pub username: String,
|
||||||
|
#[validate(
|
||||||
|
email,
|
||||||
|
custom(function = "unique_email", use_context)
|
||||||
|
)]
|
||||||
|
pub email: String,
|
||||||
|
#[validate(length(min = 10), must_match(other = "password_repeat", ))]
|
||||||
|
pub password: String,
|
||||||
|
pub password_repeat: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Registration> for ValidatableRegistration {
|
||||||
|
fn from(value: Registration) -> Self {
|
||||||
|
Self {
|
||||||
|
username: value.username,
|
||||||
|
email: value.email,
|
||||||
|
password: value.password,
|
||||||
|
password_repeat: value.password_repeat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/token")]
|
||||||
|
pub async fn login(pool: web::Data<DbPool>, login_data: web::Json<Login>) -> Result<impl Responder, ApiError> {
|
||||||
|
let data = login_data.into_inner();
|
||||||
|
|
||||||
|
if let Ok(Some(user)) = web::block(move || {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
gamenight_database::login(&mut conn, data.into())
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
let token = get_token(&user)?;
|
||||||
|
let response = Token{ jwt_token: Some(token) };
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&response)?))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Err(ApiError{status: 401, message: "User doesn't exist or password doesn't match".to_string()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/token")]
|
||||||
|
pub async fn refresh(user: AuthUser) -> Result<impl Responder, ApiError> {
|
||||||
|
let new_token = get_token(&user.0)?;
|
||||||
|
let response = Token{ jwt_token: Some(new_token) };
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&response)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/user")]
|
||||||
|
pub async fn register(pool: web::Data<DbPool>, register_data: web::Json<Registration>) -> Result<impl Responder, ApiError> {
|
||||||
|
web::block(move || -> Result<(), ApiError> {
|
||||||
|
let validatable_registration: ValidatableRegistration = register_data.clone().into();
|
||||||
|
validatable_registration.validate_with_args(&RegisterContext{pool: &pool})?;
|
||||||
|
let register_request = register_data.into_inner().into();
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
gamenight_database::register(&mut conn, register_request)?;
|
||||||
|
Ok(())
|
||||||
|
}).await??;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gamenight_database::user::User> for User {
|
||||||
|
fn from(value: gamenight_database::user::User) -> Self {
|
||||||
|
Self {
|
||||||
|
id: value.id.to_string(),
|
||||||
|
username: value.username,
|
||||||
|
email: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/user")]
|
||||||
|
pub async fn get_user(pool: web::Data<DbPool>, _user: AuthUser, user_info: web::Json<UserId>) -> Result<impl Responder, ApiError> {
|
||||||
|
let mut conn = pool.get_conn();
|
||||||
|
|
||||||
|
let user = gamenight_database::user::get_user(&mut conn, Uuid::parse_str(&user_info.into_inner().user_id)?)?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type(ContentType::json())
|
||||||
|
.body(serde_json::to_string(&user)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/user")]
|
||||||
|
pub async fn get_user_unauthenticated(_path: web::Path<UserId>) -> Result<impl Responder, ApiError> {
|
||||||
|
Ok(HttpResponse::Forbidden())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
6
backend/.gitignore
vendored
6
backend/.gitignore
vendored
@ -1,6 +0,0 @@
|
|||||||
/target
|
|
||||||
.vscode
|
|
||||||
App.toml
|
|
||||||
*.sqlite
|
|
||||||
*.sqlite-shm
|
|
||||||
*.sqlite-wal
|
|
@ -1,8 +0,0 @@
|
|||||||
#Copy this file over to Rocket.toml after changing all relevant values.
|
|
||||||
|
|
||||||
[default]
|
|
||||||
jwt_secret = "some really good secret"
|
|
||||||
|
|
||||||
[global.databases]
|
|
||||||
gamenight_database = { url = "gamenight.sqlite" }
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "gamenight"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Dennis Brentjes <d.brentjes@gmail.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
rocket = { version = "0.5.0-rc.1", features = ["default", "json"] }
|
|
||||||
libsqlite3-sys = { version = ">=0.8.0, <0.19.0", features = ["bundled"] }
|
|
||||||
rocket_sync_db_pools = { version = "0.1.0-rc.1", features = ["diesel_sqlite_pool"] }
|
|
||||||
diesel = { version = "1.4.8", features = ["sqlite"] }
|
|
||||||
diesel_migrations = "1.4.0"
|
|
||||||
rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["handlebars"] }
|
|
||||||
chrono = "0.4.19"
|
|
||||||
serde = "1.0.136"
|
|
||||||
password-hash = "0.4"
|
|
||||||
argon2 = "0.4"
|
|
||||||
rand_core = { version = "0.6", features = ["std"] }
|
|
||||||
diesel-derive-enum = { version = "1.1", features = ["sqlite"] }
|
|
||||||
jsonwebtoken = "8.1"
|
|
||||||
validator = { version = "0.14", features = ["derive"] }
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
-- Your SQL goes here
|
|
||||||
|
|
||||||
CREATE TABLE gamenight (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
game text TEXT NOT NULL,
|
|
||||||
datetime TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE known_games (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
game TEXT UNIQUE NOT NULL
|
|
||||||
);
|
|
@ -1,12 +0,0 @@
|
|||||||
CREATE TABLE user (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
username TEXT UNIQUE NOT NULL,
|
|
||||||
email TEXT UNIQUE NOT NULL,
|
|
||||||
role TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE pwd (
|
|
||||||
user_id INTEGER NOT NULL PRIMARY KEY,
|
|
||||||
password TEXT NOT NULL,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
|
|
||||||
);
|
|
@ -1,3 +0,0 @@
|
|||||||
echo $JWT
|
|
||||||
|
|
||||||
curl -v -X GET -H "Authorization: Bearer ${JWT}" localhost:8000/api/gamenights
|
|
@ -1 +0,0 @@
|
|||||||
curl -v -X POST -H "Content-Type: application/json" -d '{"username": "roflin", "password": "oreokoekje123"}' localhost:8000/api/login
|
|
@ -1 +0,0 @@
|
|||||||
curl -v -X POST -H "Content-Type: application/json" -d '{"username": "roflin", "email": "user@example.com", "password": "oreokoekje123", "password_repeat": "oreokoekje123"}' localhost:8000/api/register
|
|
@ -1,215 +0,0 @@
|
|||||||
use crate::schema;
|
|
||||||
use crate::schema::DbConn;
|
|
||||||
use crate::AppConfig;
|
|
||||||
use chrono::Utc;
|
|
||||||
use jsonwebtoken::decode;
|
|
||||||
use jsonwebtoken::encode;
|
|
||||||
use jsonwebtoken::DecodingKey;
|
|
||||||
use jsonwebtoken::Validation;
|
|
||||||
use jsonwebtoken::{EncodingKey, Header};
|
|
||||||
use rocket::http::Status;
|
|
||||||
use rocket::request::Outcome;
|
|
||||||
use rocket::request::{FromRequest, Request};
|
|
||||||
use rocket::response;
|
|
||||||
use rocket::serde::json;
|
|
||||||
use rocket::serde::json::{json, Json};
|
|
||||||
use rocket::State;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde::ser::{SerializeStruct, Serializer};
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fmt;
|
|
||||||
use validator::{ValidateArgs, ValidationErrors};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct ApiResponse {
|
|
||||||
ok: bool,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
message: Option<Cow<'static, str>>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
jwt: Option<Cow<'static, str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ApiResponse {
|
|
||||||
const SUCCES: Self = Self {
|
|
||||||
ok: true,
|
|
||||||
message: None,
|
|
||||||
jwt: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn login_response(jwt: String) -> Self {
|
|
||||||
Self {
|
|
||||||
ok: true,
|
|
||||||
message: None,
|
|
||||||
jwt: Some(Cow::Owned(jwt)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ApiError {
|
|
||||||
RequestError(String),
|
|
||||||
ValidationErrors(ValidationErrors),
|
|
||||||
Unauthorized,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for ApiError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
use ApiError::*;
|
|
||||||
write!(f, "{}", match &self {
|
|
||||||
RequestError(e) => e,
|
|
||||||
ValidationErrors(_) => "???",
|
|
||||||
Unauthorized => "username and password didn't match",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<schema::DatabaseError> for ApiError {
|
|
||||||
fn from(e: schema::DatabaseError) -> Self {
|
|
||||||
ApiError::RequestError(e.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ValidationErrors> for ApiError {
|
|
||||||
fn from(e: ValidationErrors) -> Self {
|
|
||||||
ApiError::ValidationErrors(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for ApiError {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let mut state = serializer.serialize_struct("ApiError", 2)?;
|
|
||||||
state.serialize_field("ok", &false)?;
|
|
||||||
state.serialize_field("message", &self.to_string())?;
|
|
||||||
state.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'r> response::Responder<'r, 'static> for ApiError {
|
|
||||||
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
|
|
||||||
use ApiError::*;
|
|
||||||
let status = match self {
|
|
||||||
RequestError(_) => Status::BadRequest,
|
|
||||||
ValidationErrors(_) => Status::BadRequest,
|
|
||||||
Unauthorized => Status::Unauthorized,
|
|
||||||
};
|
|
||||||
|
|
||||||
response::Response::build()
|
|
||||||
.merge(json!(self).respond_to(req)?)
|
|
||||||
.status(status)
|
|
||||||
.ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AUTH_HEADER: &str = "Authorization";
|
|
||||||
const BEARER: &str = "Bearer ";
|
|
||||||
|
|
||||||
#[rocket::async_trait]
|
|
||||||
impl<'r> FromRequest<'r> for schema::User {
|
|
||||||
type Error = ApiError;
|
|
||||||
|
|
||||||
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
|
||||||
let header = match req.headers().get_one(AUTH_HEADER) {
|
|
||||||
Some(header) => header,
|
|
||||||
None => {
|
|
||||||
return Outcome::Forward(())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if !header.starts_with(BEARER) {
|
|
||||||
return Outcome::Forward(());
|
|
||||||
};
|
|
||||||
|
|
||||||
let app_config = req.guard::<&State<AppConfig>>().await.unwrap().inner();
|
|
||||||
let jwt = header.trim_start_matches(BEARER).to_owned();
|
|
||||||
let token = match decode::<Claims>(
|
|
||||||
&jwt,
|
|
||||||
&DecodingKey::from_secret(app_config.jwt_secret.as_bytes()),
|
|
||||||
&Validation::default(),
|
|
||||||
) {
|
|
||||||
Ok(token) => token,
|
|
||||||
Err(_) => {
|
|
||||||
return Outcome::Forward(())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let id = token.claims.uid;
|
|
||||||
|
|
||||||
let conn = req.guard::<DbConn>().await.unwrap();
|
|
||||||
return Outcome::Success(schema::get_user(conn, id).await);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/gamenights")]
|
|
||||||
pub async fn gamenights(conn: DbConn, _user: schema::User) -> json::Value {
|
|
||||||
json!(schema::get_all_gamenights(conn).await)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/gamenights", rank = 2)]
|
|
||||||
pub async fn gamenights_unauthorized() -> Status {
|
|
||||||
Status::Unauthorized
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/gamenight", format = "application/json", data = "<gamenight_json>")]
|
|
||||||
pub async fn gamenight_post_json(
|
|
||||||
conn: DbConn,
|
|
||||||
user: Option<schema::User>,
|
|
||||||
gamenight_json: Json<schema::GameNightNoId>,
|
|
||||||
) -> Result<json::Value, Status> {
|
|
||||||
if user.is_some() {
|
|
||||||
schema::insert_gamenight(conn, gamenight_json.into_inner()).await;
|
|
||||||
Ok(json!(ApiResponse::SUCCES))
|
|
||||||
} else {
|
|
||||||
Err(Status::Unauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/register", format = "application/json", data = "<register_json>")]
|
|
||||||
pub async fn register_post_json(
|
|
||||||
conn: DbConn,
|
|
||||||
register_json: Json<schema::Register>,
|
|
||||||
) -> Result<json::Value, ApiError> {
|
|
||||||
let register = register_json.into_inner();
|
|
||||||
let register_clone = register.clone();
|
|
||||||
conn.run(move |c| register_clone.validate_args((c, c)))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
schema::insert_user(conn, register).await?;
|
|
||||||
Ok(json!(ApiResponse::SUCCES))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
struct Claims {
|
|
||||||
exp: i64,
|
|
||||||
uid: i32,
|
|
||||||
role: schema::Role,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/login", format = "application/json", data = "<login_json>")]
|
|
||||||
pub async fn login_post_json(
|
|
||||||
conn: DbConn,
|
|
||||||
config: &State<AppConfig>,
|
|
||||||
login_json: Json<schema::Login>,
|
|
||||||
) -> Result<json::Value, ApiError> {
|
|
||||||
let login_result = schema::login(conn, login_json.into_inner()).await?;
|
|
||||||
if !login_result.result {
|
|
||||||
return Err(ApiError::Unauthorized);
|
|
||||||
}
|
|
||||||
|
|
||||||
let my_claims = Claims {
|
|
||||||
exp: Utc::now().timestamp() + chrono::Duration::days(7).num_seconds(),
|
|
||||||
uid: login_result.id.unwrap(),
|
|
||||||
role: login_result.role.unwrap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let secret = &config.inner().jwt_secret;
|
|
||||||
match encode(
|
|
||||||
&Header::default(),
|
|
||||||
&my_claims,
|
|
||||||
&EncodingKey::from_secret(secret.as_bytes()),
|
|
||||||
) {
|
|
||||||
Ok(token) => Ok(json!(ApiResponse::login_response(token))),
|
|
||||||
Err(error) => Err(ApiError::RequestError(error.to_string())),
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate rocket;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate diesel_migrations;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate diesel;
|
|
||||||
|
|
||||||
use rocket::{
|
|
||||||
fairing::AdHoc,
|
|
||||||
figment::{
|
|
||||||
providers::{Env, Format, Serialized, Toml},
|
|
||||||
Figment, Profile,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use rocket_dyn_templates::Template;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
mod api;
|
|
||||||
pub mod schema;
|
|
||||||
mod site;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
pub struct AppConfig {
|
|
||||||
jwt_secret: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for AppConfig {
|
|
||||||
fn default() -> AppConfig {
|
|
||||||
AppConfig {
|
|
||||||
jwt_secret: String::from("secret"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[launch]
|
|
||||||
fn rocket() -> _ {
|
|
||||||
let figment = Figment::from(rocket::Config::default())
|
|
||||||
.merge(Serialized::defaults(AppConfig::default()))
|
|
||||||
.merge(Toml::file("App.toml").nested())
|
|
||||||
.merge(Env::prefixed("APP_").global())
|
|
||||||
.select(Profile::from_env_or("APP_PROFILE", "default"));
|
|
||||||
|
|
||||||
let rocket = rocket::custom(figment)
|
|
||||||
.attach(schema::DbConn::fairing())
|
|
||||||
.attach(Template::fairing())
|
|
||||||
.attach(AdHoc::on_ignite("Run Migrations", schema::run_migrations))
|
|
||||||
.attach(AdHoc::config::<AppConfig>())
|
|
||||||
.mount(
|
|
||||||
"/",
|
|
||||||
routes![
|
|
||||||
site::index,
|
|
||||||
site::gamenights,
|
|
||||||
site::add_game_night,
|
|
||||||
site::register
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.mount(
|
|
||||||
"/api",
|
|
||||||
routes![
|
|
||||||
api::gamenights,
|
|
||||||
api::gamenights_unauthorized,
|
|
||||||
api::gamenight_post_json,
|
|
||||||
api::register_post_json,
|
|
||||||
api::login_post_json
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
rocket
|
|
||||||
}
|
|
@ -1,319 +0,0 @@
|
|||||||
use crate::diesel::BoolExpressionMethods;
|
|
||||||
use crate::diesel::Connection;
|
|
||||||
use crate::diesel::ExpressionMethods;
|
|
||||||
use crate::diesel::QueryDsl;
|
|
||||||
use argon2::password_hash::SaltString;
|
|
||||||
use argon2::PasswordHash;
|
|
||||||
use argon2::PasswordVerifier;
|
|
||||||
use argon2::{
|
|
||||||
password_hash::{rand_core::OsRng, PasswordHasher},
|
|
||||||
Argon2,
|
|
||||||
};
|
|
||||||
use diesel::dsl::count;
|
|
||||||
use diesel::RunQueryDsl;
|
|
||||||
use diesel_derive_enum::DbEnum;
|
|
||||||
use rocket::{Build, Rocket};
|
|
||||||
use rocket_sync_db_pools::database;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::ops::Deref;
|
|
||||||
use validator::{Validate, ValidationError};
|
|
||||||
|
|
||||||
#[database("gamenight_database")]
|
|
||||||
pub struct DbConn(diesel::SqliteConnection);
|
|
||||||
|
|
||||||
impl Deref for DbConn {
|
|
||||||
type Target = rocket_sync_db_pools::Connection<DbConn, diesel::SqliteConnection>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
gamenight (id) {
|
|
||||||
id -> Integer,
|
|
||||||
game -> Text,
|
|
||||||
datetime -> Text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
known_games (game) {
|
|
||||||
id -> Integer,
|
|
||||||
game -> Text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
use diesel::sql_types::Integer;
|
|
||||||
use diesel::sql_types::Text;
|
|
||||||
use super::RoleMapping;
|
|
||||||
user(id) {
|
|
||||||
id -> Integer,
|
|
||||||
username -> Text,
|
|
||||||
email -> Text,
|
|
||||||
role -> RoleMapping,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
pwd(user_id) {
|
|
||||||
user_id -> Integer,
|
|
||||||
password -> Text,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allow_tables_to_appear_in_same_query!(gamenight, known_games,);
|
|
||||||
|
|
||||||
pub enum DatabaseError {
|
|
||||||
Hash(password_hash::Error),
|
|
||||||
Query(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for DatabaseError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
|
||||||
match self {
|
|
||||||
DatabaseError::Hash(err) => write!(f, "{}", err),
|
|
||||||
DatabaseError::Query(err) => write!(f, "{}", err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_all_gamenights(conn: DbConn) -> Vec<GameNight> {
|
|
||||||
conn.run(|c| gamenight::table.load::<GameNight>(c).unwrap())
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn insert_gamenight(conn: DbConn, new_gamenight: GameNightNoId) -> () {
|
|
||||||
conn.run(|c| {
|
|
||||||
diesel::insert_into(gamenight::table)
|
|
||||||
.values(new_gamenight)
|
|
||||||
.execute(c)
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn insert_user(conn: DbConn, new_user: Register) -> Result<(), DatabaseError> {
|
|
||||||
let salt = SaltString::generate(&mut OsRng);
|
|
||||||
|
|
||||||
let argon2 = Argon2::default();
|
|
||||||
|
|
||||||
let password_hash = match argon2.hash_password(new_user.password.as_bytes(), &salt) {
|
|
||||||
Ok(hash) => hash.to_string(),
|
|
||||||
Err(error) => return Err(DatabaseError::Hash(error)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let user_insert_result = conn
|
|
||||||
.run(move |c| {
|
|
||||||
c.transaction(|| {
|
|
||||||
diesel::insert_into(user::table)
|
|
||||||
.values((
|
|
||||||
user::username.eq(&new_user.username),
|
|
||||||
user::email.eq(&new_user.email),
|
|
||||||
user::role.eq(Role::User),
|
|
||||||
))
|
|
||||||
.execute(c)?;
|
|
||||||
|
|
||||||
let ids: Vec<i32> = match user::table
|
|
||||||
.filter(
|
|
||||||
user::username
|
|
||||||
.eq(&new_user.username)
|
|
||||||
.and(user::email.eq(&new_user.email)),
|
|
||||||
)
|
|
||||||
.select(user::id)
|
|
||||||
.get_results(c)
|
|
||||||
{
|
|
||||||
Ok(id) => id,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
diesel::insert_into(pwd::table)
|
|
||||||
.values((pwd::user_id.eq(ids[0]), pwd::password.eq(&password_hash)))
|
|
||||||
.execute(c)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match user_insert_result {
|
|
||||||
Err(e) => Err(DatabaseError::Query(e.to_string())),
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn login(conn: DbConn, login: Login) -> Result<LoginResult, DatabaseError> {
|
|
||||||
conn.run(move |c| -> Result<LoginResult, DatabaseError> {
|
|
||||||
let id: i32 = match user::table
|
|
||||||
.filter(user::username.eq(&login.username))
|
|
||||||
.or_filter(user::email.eq(&login.username))
|
|
||||||
.select(user::id)
|
|
||||||
.first(c)
|
|
||||||
{
|
|
||||||
Ok(id) => id,
|
|
||||||
Err(error) => return Err(DatabaseError::Query(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
let pwd: String = match pwd::table
|
|
||||||
.filter(pwd::user_id.eq(id))
|
|
||||||
.select(pwd::password)
|
|
||||||
.first(c)
|
|
||||||
{
|
|
||||||
Ok(pwd) => pwd,
|
|
||||||
Err(error) => return Err(DatabaseError::Query(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
let parsed_hash = match PasswordHash::new(&pwd) {
|
|
||||||
Ok(hash) => hash,
|
|
||||||
Err(error) => return Err(DatabaseError::Hash(error)),
|
|
||||||
};
|
|
||||||
|
|
||||||
if Argon2::default()
|
|
||||||
.verify_password(&login.password.as_bytes(), &parsed_hash)
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
let role: Role = match user::table
|
|
||||||
.filter(user::id.eq(id))
|
|
||||||
.select(user::role)
|
|
||||||
.first(c)
|
|
||||||
{
|
|
||||||
Ok(role) => role,
|
|
||||||
Err(error) => return Err(DatabaseError::Query(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(LoginResult {
|
|
||||||
result: true,
|
|
||||||
id: Some(id),
|
|
||||||
role: Some(role),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(LoginResult {
|
|
||||||
result: false,
|
|
||||||
id: None,
|
|
||||||
role: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_user(conn: DbConn, id: i32) -> User {
|
|
||||||
conn.run(move |c| user::table.filter(user::id.eq(id)).first(c).unwrap())
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unique_username(
|
|
||||||
username: &String,
|
|
||||||
conn: &diesel::SqliteConnection,
|
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
match user::table
|
|
||||||
.select(count(user::username))
|
|
||||||
.filter(user::username.eq(username))
|
|
||||||
.execute(conn)
|
|
||||||
{
|
|
||||||
Ok(0) => Ok(()),
|
|
||||||
Ok(_) => Err(ValidationError::new("User already exists")),
|
|
||||||
Err(_) => Err(ValidationError::new("Database error while validating user")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unique_email(
|
|
||||||
email: &String,
|
|
||||||
conn: &diesel::SqliteConnection,
|
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
match user::table
|
|
||||||
.select(count(user::email))
|
|
||||||
.filter(user::email.eq(email))
|
|
||||||
.execute(conn)
|
|
||||||
{
|
|
||||||
Ok(0) => Ok(()),
|
|
||||||
Ok(_) => Err(ValidationError::new("email already exists")),
|
|
||||||
Err(_) => Err(ValidationError::new(
|
|
||||||
"Database error while validating email",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {
|
|
||||||
// This macro from `diesel_migrations` defines an `embedded_migrations`
|
|
||||||
// module containing a function named `run`. This allows the example to be
|
|
||||||
// run and tested without any outside setup of the database.
|
|
||||||
embed_migrations!();
|
|
||||||
|
|
||||||
let conn = DbConn::get_one(&rocket).await.expect("database connection");
|
|
||||||
conn.run(|c| embedded_migrations::run(c))
|
|
||||||
.await
|
|
||||||
.expect("can run migrations");
|
|
||||||
|
|
||||||
rocket
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, DbEnum, Clone)]
|
|
||||||
pub enum Role {
|
|
||||||
Admin,
|
|
||||||
User,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Insertable, Queryable)]
|
|
||||||
#[table_name = "user"]
|
|
||||||
pub struct User {
|
|
||||||
pub id: i32,
|
|
||||||
pub username: String,
|
|
||||||
pub email: String,
|
|
||||||
pub role: Role,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, FromForm, Insertable)]
|
|
||||||
#[table_name = "known_games"]
|
|
||||||
pub struct GameNoId {
|
|
||||||
pub game: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, FromForm, Queryable)]
|
|
||||||
pub struct Game {
|
|
||||||
pub id: i32,
|
|
||||||
pub game: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, FromForm, Insertable)]
|
|
||||||
#[table_name = "gamenight"]
|
|
||||||
pub struct GameNightNoId {
|
|
||||||
pub game: String,
|
|
||||||
pub datetime: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, FromForm, Queryable)]
|
|
||||||
pub struct GameNight {
|
|
||||||
pub id: i32,
|
|
||||||
pub game: String,
|
|
||||||
pub datetime: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Validate, Clone)]
|
|
||||||
pub struct Register {
|
|
||||||
#[validate(
|
|
||||||
length(min = 1),
|
|
||||||
custom(function = "unique_username", arg = "&'v_a diesel::SqliteConnection")
|
|
||||||
)]
|
|
||||||
pub username: String,
|
|
||||||
#[validate(
|
|
||||||
email,
|
|
||||||
custom(function = "unique_email", arg = "&'v_a diesel::SqliteConnection")
|
|
||||||
)]
|
|
||||||
pub email: String,
|
|
||||||
#[validate(length(min = 10), must_match = "password_repeat")]
|
|
||||||
pub password: String,
|
|
||||||
pub password_repeat: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct Login {
|
|
||||||
pub username: String,
|
|
||||||
pub password: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct LoginResult {
|
|
||||||
pub result: bool,
|
|
||||||
pub id: Option<i32>,
|
|
||||||
pub role: Option<Role>,
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
use crate::schema;
|
|
||||||
use rocket::request::FlashMessage;
|
|
||||||
use rocket::response::Redirect;
|
|
||||||
use rocket_dyn_templates::Template;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct FlashData {
|
|
||||||
has_data: bool,
|
|
||||||
kind: Cow<'static, str>,
|
|
||||||
message: Cow<'static, str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FlashData {
|
|
||||||
const EMPTY: Self = Self {
|
|
||||||
has_data: false,
|
|
||||||
message: Cow::Borrowed(""),
|
|
||||||
kind: Cow::Borrowed(""),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct GameNightsData {
|
|
||||||
gamenights: Vec<schema::GameNight>,
|
|
||||||
flash: FlashData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/gamenights")]
|
|
||||||
pub async fn gamenights(conn: schema::DbConn) -> Template {
|
|
||||||
let gamenights = schema::get_all_gamenights(conn).await;
|
|
||||||
|
|
||||||
let data = GameNightsData {
|
|
||||||
gamenights: gamenights,
|
|
||||||
flash: FlashData::EMPTY,
|
|
||||||
};
|
|
||||||
|
|
||||||
Template::render("gamenights", &data)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/")]
|
|
||||||
pub async fn index() -> Redirect {
|
|
||||||
Redirect::to(uri!(gamenights))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct GameNightAddData {
|
|
||||||
post_url: String,
|
|
||||||
flash: FlashData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/gamenight/add")]
|
|
||||||
pub async fn add_game_night(flash: Option<FlashMessage<'_>>) -> Template {
|
|
||||||
let flash_data = match flash {
|
|
||||||
None => FlashData::EMPTY,
|
|
||||||
Some(flash) => FlashData {
|
|
||||||
has_data: true,
|
|
||||||
message: Cow::Owned(flash.message().to_string()),
|
|
||||||
kind: Cow::Owned(flash.kind().to_string()),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let data = GameNightAddData {
|
|
||||||
post_url: "/api/gamenight".to_string(),
|
|
||||||
flash: flash_data,
|
|
||||||
};
|
|
||||||
|
|
||||||
Template::render("gamenight_add", &data)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct RegisterData {
|
|
||||||
flash: FlashData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/register")]
|
|
||||||
pub async fn register(flash: Option<FlashMessage<'_>>) -> Template {
|
|
||||||
let flash_data = match flash {
|
|
||||||
None => FlashData::EMPTY,
|
|
||||||
Some(flash) => FlashData {
|
|
||||||
has_data: true,
|
|
||||||
message: Cow::Owned(flash.message().to_string()),
|
|
||||||
kind: Cow::Owned(flash.kind().to_string()),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let data = RegisterData { flash: flash_data };
|
|
||||||
|
|
||||||
Template::render("register", &data)
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
{{#if has_data}}
|
|
||||||
<div>
|
|
||||||
<p>{{kind}}: {{message}}</p>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
@ -1,16 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
{{> flash flash }}
|
|
||||||
|
|
||||||
<form action="{{post_url}}" method="post">
|
|
||||||
<label for="game">Game:</label><br>
|
|
||||||
<input type="text" id="game" name="game"><br>
|
|
||||||
<label for="datetime">Wanneer:</label><br>
|
|
||||||
<input type="text" id="datetime" name="datetime">
|
|
||||||
<input type="submit" value="Submit">
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{{> flash flash }}
|
|
||||||
|
|
||||||
{{#each gamenights}}
|
|
||||||
<div>
|
|
||||||
<span>game: {{this.game}}</span>
|
|
||||||
<span>when: {{this.datetime}}</span>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,19 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{{> flash flash }}
|
|
||||||
|
|
||||||
<form action="/api/register" method="post">
|
|
||||||
<label for="username">Username:</label><br>
|
|
||||||
<input type="text" id="username" name="username" required><br>
|
|
||||||
<label for="email">Email:</label><br>
|
|
||||||
<input type="text" id="email" name="email" required><br>
|
|
||||||
<label for="password">Password:</label><br>
|
|
||||||
<input type="password" id="password" name="password" required><br>
|
|
||||||
<label for="password_repeat">Repeat password:</label><br>
|
|
||||||
<input type="password" id="password_repeat" name="password_repeat" required><br>
|
|
||||||
<input type="submit">
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
container_name: pg_container
|
||||||
|
image: postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: root
|
||||||
|
POSTGRES_PASSWORD: root
|
||||||
|
POSTGRES_DB: gamenight
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
pgadmin:
|
||||||
|
container_name: pgadmin4_container
|
||||||
|
image: dpage/pgadmin4
|
||||||
|
environment:
|
||||||
|
PGADMIN_DEFAULT_EMAIL: admin@admin.com
|
||||||
|
PGADMIN_DEFAULT_PASSWORD: root
|
||||||
|
ports:
|
||||||
|
- "5050:80"
|
23
frontend/.gitignore
vendored
23
frontend/.gitignore
vendored
@ -1,23 +0,0 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
# testing
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
.env.local
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
@ -1,70 +0,0 @@
|
|||||||
# Getting Started with Create React App
|
|
||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
|
||||||
|
|
||||||
## Available Scripts
|
|
||||||
|
|
||||||
In the project directory, you can run:
|
|
||||||
|
|
||||||
### `npm start`
|
|
||||||
|
|
||||||
Runs the app in the development mode.\
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
|
||||||
|
|
||||||
The page will reload when you make changes.\
|
|
||||||
You may also see any lint errors in the console.
|
|
||||||
|
|
||||||
### `npm test`
|
|
||||||
|
|
||||||
Launches the test runner in the interactive watch mode.\
|
|
||||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
||||||
|
|
||||||
### `npm run build`
|
|
||||||
|
|
||||||
Builds the app for production to the `build` folder.\
|
|
||||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
||||||
|
|
||||||
The build is minified and the filenames include the hashes.\
|
|
||||||
Your app is ready to be deployed!
|
|
||||||
|
|
||||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
||||||
|
|
||||||
### `npm run eject`
|
|
||||||
|
|
||||||
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
|
||||||
|
|
||||||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
||||||
|
|
||||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
|
||||||
|
|
||||||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
||||||
|
|
||||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
|
||||||
|
|
||||||
### Code Splitting
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
|
||||||
|
|
||||||
### Analyzing the Bundle Size
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
|
||||||
|
|
||||||
### Making a Progressive Web App
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
|
||||||
|
|
||||||
### Advanced Configuration
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
|
||||||
|
|
||||||
### Deployment
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
|
||||||
|
|
||||||
### `npm run build` fails to minify
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
|
27260
frontend/package-lock.json
generated
27260
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "frontend",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
|
||||||
"@testing-library/react": "^13.0.1",
|
|
||||||
"@testing-library/user-event": "^13.5.0",
|
|
||||||
"react": "^18.0.0",
|
|
||||||
"react-dom": "^18.0.0",
|
|
||||||
"react-scripts": "5.0.1",
|
|
||||||
"web-vitals": "^2.1.4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "react-scripts start",
|
|
||||||
"build": "react-scripts build",
|
|
||||||
"test": "react-scripts test",
|
|
||||||
"eject": "react-scripts eject"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"extends": [
|
|
||||||
"react-app",
|
|
||||||
"react-app/jest"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"browserslist": {
|
|
||||||
"production": [
|
|
||||||
">0.2%",
|
|
||||||
"not dead",
|
|
||||||
"not op_mini all"
|
|
||||||
],
|
|
||||||
"development": [
|
|
||||||
"last 1 chrome version",
|
|
||||||
"last 1 firefox version",
|
|
||||||
"last 1 safari version"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB |
@ -1,43 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="Web site created using create-react-app"
|
|
||||||
/>
|
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
||||||
<!--
|
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<!--
|
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
|
||||||
-->
|
|
||||||
<title>React App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"short_name": "React App",
|
|
||||||
"name": "Create React App Sample",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
|
||||||
"type": "image/x-icon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo192.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "192x192"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo512.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "512x512"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"start_url": ".",
|
|
||||||
"display": "standalone",
|
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff"
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
# https://www.robotstxt.org/robotstxt.html
|
|
||||||
User-agent: *
|
|
||||||
Disallow:
|
|
@ -1,38 +0,0 @@
|
|||||||
.App {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-logo {
|
|
||||||
height: 40vmin;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
.App-logo {
|
|
||||||
animation: App-logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-header {
|
|
||||||
background-color: #282c34;
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: calc(10px + 2vmin);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-link {
|
|
||||||
color: #61dafb;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes App-logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
import logo from './logo.svg';
|
|
||||||
import './App.css';
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
<header className="App-header">
|
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
|
||||||
<p>
|
|
||||||
Edit <code>src/App.js</code> and save to reload.
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
className="App-link"
|
|
||||||
href="https://reactjs.org"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Learn React
|
|
||||||
</a>
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
@ -1,8 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
test('renders learn react link', () => {
|
|
||||||
render(<App />);
|
|
||||||
const linkElement = screen.getByText(/learn react/i);
|
|
||||||
expect(linkElement).toBeInTheDocument();
|
|
||||||
});
|
|
@ -1,13 +0,0 @@
|
|||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
||||||
monospace;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import './index.css';
|
|
||||||
import App from './App';
|
|
||||||
import reportWebVitals from './reportWebVitals';
|
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
||||||
root.render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<App />
|
|
||||||
</React.StrictMode>
|
|
||||||
);
|
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
|
||||||
// to log results (for example: reportWebVitals(console.log))
|
|
||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
||||||
reportWebVitals();
|
|
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
|
Before Width: | Height: | Size: 2.6 KiB |
@ -1,13 +0,0 @@
|
|||||||
const reportWebVitals = onPerfEntry => {
|
|
||||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
|
||||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
|
||||||
getCLS(onPerfEntry);
|
|
||||||
getFID(onPerfEntry);
|
|
||||||
getFCP(onPerfEntry);
|
|
||||||
getLCP(onPerfEntry);
|
|
||||||
getTTFB(onPerfEntry);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default reportWebVitals;
|
|
@ -1,5 +0,0 @@
|
|||||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
|
||||||
// allows you to do things like:
|
|
||||||
// expect(element).toHaveTextContent(/react/i)
|
|
||||||
// learn more: https://github.com/testing-library/jest-dom
|
|
||||||
import '@testing-library/jest-dom';
|
|
3
gamenight-api-client-rs/.gitignore
vendored
Normal file
3
gamenight-api-client-rs/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
23
gamenight-api-client-rs/.openapi-generator-ignore
Normal file
23
gamenight-api-client-rs/.openapi-generator-ignore
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# OpenAPI Generator Ignore
|
||||||
|
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||||
|
|
||||||
|
# Use this file to prevent files from being overwritten by the generator.
|
||||||
|
# The patterns follow closely to .gitignore or .dockerignore.
|
||||||
|
|
||||||
|
# As an example, the C# client generator defines ApiClient.cs.
|
||||||
|
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||||
|
#ApiClient.cs
|
||||||
|
|
||||||
|
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||||
|
#foo/*/qux
|
||||||
|
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||||
|
#foo/**/qux
|
||||||
|
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can also negate patterns with an exclamation (!).
|
||||||
|
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||||
|
#docs/*.md
|
||||||
|
# Then explicitly reverse the ignore rule for a single file:
|
||||||
|
#!docs/README.md
|
39
gamenight-api-client-rs/.openapi-generator/FILES
Normal file
39
gamenight-api-client-rs/.openapi-generator/FILES
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
.gitignore
|
||||||
|
.travis.yml
|
||||||
|
Cargo.toml
|
||||||
|
README.md
|
||||||
|
docs/AddGameRequestBody.md
|
||||||
|
docs/AddGamenightRequestBody.md
|
||||||
|
docs/DefaultApi.md
|
||||||
|
docs/Failure.md
|
||||||
|
docs/Game.md
|
||||||
|
docs/GameId.md
|
||||||
|
docs/Gamenight.md
|
||||||
|
docs/GamenightId.md
|
||||||
|
docs/GetGamenightRequestBody.md
|
||||||
|
docs/Login.md
|
||||||
|
docs/Participants.md
|
||||||
|
docs/Registration.md
|
||||||
|
docs/Token.md
|
||||||
|
docs/User.md
|
||||||
|
docs/UserId.md
|
||||||
|
git_push.sh
|
||||||
|
src/apis/configuration.rs
|
||||||
|
src/apis/default_api.rs
|
||||||
|
src/apis/mod.rs
|
||||||
|
src/lib.rs
|
||||||
|
src/models/add_game_request_body.rs
|
||||||
|
src/models/add_gamenight_request_body.rs
|
||||||
|
src/models/failure.rs
|
||||||
|
src/models/game.rs
|
||||||
|
src/models/game_id.rs
|
||||||
|
src/models/gamenight.rs
|
||||||
|
src/models/gamenight_id.rs
|
||||||
|
src/models/get_gamenight_request_body.rs
|
||||||
|
src/models/login.rs
|
||||||
|
src/models/mod.rs
|
||||||
|
src/models/participants.rs
|
||||||
|
src/models/registration.rs
|
||||||
|
src/models/token.rs
|
||||||
|
src/models/user.rs
|
||||||
|
src/models/user_id.rs
|
1
gamenight-api-client-rs/.openapi-generator/VERSION
Normal file
1
gamenight-api-client-rs/.openapi-generator/VERSION
Normal file
@ -0,0 +1 @@
|
|||||||
|
7.13.0
|
1
gamenight-api-client-rs/.travis.yml
Normal file
1
gamenight-api-client-rs/.travis.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
language: rust
|
14
gamenight-api-client-rs/Cargo.toml
Normal file
14
gamenight-api-client-rs/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "gamenight-api-client-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["dennis@brentj.es"]
|
||||||
|
description = "Api specifaction for a Gamenight server"
|
||||||
|
license = "MIT"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
|
serde_json = "^1.0"
|
||||||
|
serde_repr = "^0.1"
|
||||||
|
url = "^2.5"
|
||||||
|
reqwest = { version = "^0.12", default-features = false, features = ["json", "multipart"] }
|
72
gamenight-api-client-rs/README.md
Normal file
72
gamenight-api-client-rs/README.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# Rust API client for gamenight-api-client-rs
|
||||||
|
|
||||||
|
Api specifaction for a Gamenight server
|
||||||
|
|
||||||
|
For more information, please visit [https://brentj.es](https://brentj.es)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://openapis.org) from a remote server, you can easily generate an API client.
|
||||||
|
|
||||||
|
- API version: 1.0
|
||||||
|
- Package version: 0.1.0
|
||||||
|
- Generator version: 7.13.0
|
||||||
|
- Build package: `org.openapitools.codegen.languages.RustClientCodegen`
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Put the package under your project folder in a directory named `gamenight-api-client-rs` and add the following to `Cargo.toml` under `[dependencies]`:
|
||||||
|
|
||||||
|
```
|
||||||
|
gamenight-api-client-rs = { path = "./gamenight-api-client-rs" }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation for API Endpoints
|
||||||
|
|
||||||
|
All URIs are relative to *http://localhost:8080*
|
||||||
|
|
||||||
|
Class | Method | HTTP request | Description
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
*DefaultApi* | [**game_get**](docs/DefaultApi.md#game_get) | **GET** /game |
|
||||||
|
*DefaultApi* | [**game_post**](docs/DefaultApi.md#game_post) | **POST** /game |
|
||||||
|
*DefaultApi* | [**games_get**](docs/DefaultApi.md#games_get) | **GET** /games |
|
||||||
|
*DefaultApi* | [**get_gamenight**](docs/DefaultApi.md#get_gamenight) | **GET** /gamenight |
|
||||||
|
*DefaultApi* | [**get_gamenights**](docs/DefaultApi.md#get_gamenights) | **GET** /gamenights | Get a all gamenights
|
||||||
|
*DefaultApi* | [**get_token**](docs/DefaultApi.md#get_token) | **GET** /token |
|
||||||
|
*DefaultApi* | [**join_post**](docs/DefaultApi.md#join_post) | **POST** /join |
|
||||||
|
*DefaultApi* | [**leave_post**](docs/DefaultApi.md#leave_post) | **POST** /leave |
|
||||||
|
*DefaultApi* | [**participants_get**](docs/DefaultApi.md#participants_get) | **GET** /participants | Get all participants for a gamenight
|
||||||
|
*DefaultApi* | [**post_gamenight**](docs/DefaultApi.md#post_gamenight) | **POST** /gamenight |
|
||||||
|
*DefaultApi* | [**post_register**](docs/DefaultApi.md#post_register) | **POST** /user |
|
||||||
|
*DefaultApi* | [**post_token**](docs/DefaultApi.md#post_token) | **POST** /token |
|
||||||
|
*DefaultApi* | [**user_get**](docs/DefaultApi.md#user_get) | **GET** /user |
|
||||||
|
|
||||||
|
|
||||||
|
## Documentation For Models
|
||||||
|
|
||||||
|
- [AddGameRequestBody](docs/AddGameRequestBody.md)
|
||||||
|
- [AddGamenightRequestBody](docs/AddGamenightRequestBody.md)
|
||||||
|
- [Failure](docs/Failure.md)
|
||||||
|
- [Game](docs/Game.md)
|
||||||
|
- [GameId](docs/GameId.md)
|
||||||
|
- [Gamenight](docs/Gamenight.md)
|
||||||
|
- [GamenightId](docs/GamenightId.md)
|
||||||
|
- [GetGamenightRequestBody](docs/GetGamenightRequestBody.md)
|
||||||
|
- [Login](docs/Login.md)
|
||||||
|
- [Participants](docs/Participants.md)
|
||||||
|
- [Registration](docs/Registration.md)
|
||||||
|
- [Token](docs/Token.md)
|
||||||
|
- [User](docs/User.md)
|
||||||
|
- [UserId](docs/UserId.md)
|
||||||
|
|
||||||
|
|
||||||
|
To get access to the crate's generated documentation, use:
|
||||||
|
|
||||||
|
```
|
||||||
|
cargo doc --open
|
||||||
|
```
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
dennis@brentj.es
|
||||||
|
|
10
gamenight-api-client-rs/build.rs
Normal file
10
gamenight-api-client-rs/build.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo::rerun-if-changed=../backend-actix/gamenight-api.yaml");
|
||||||
|
let _ =
|
||||||
|
Command::new("openapi-generator")
|
||||||
|
.args(["generate", "-i", "../backend-actix/gamenight-api.yaml", "-g", "rust", "--additional-properties=withSeparateModelsAndApi=true,modelPackage=gamenight_model,apiPackage=gamenight_api,packageName=gamenight-api-client-rs,packageVersion=0.1.0"])
|
||||||
|
.output()
|
||||||
|
.expect("Failed to generate models sources for the gamenight API");
|
||||||
|
}
|
11
gamenight-api-client-rs/docs/AddGame.md
Normal file
11
gamenight-api-client-rs/docs/AddGame.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# AddGame
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**name** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/AddGameRequestBody.md
Normal file
11
gamenight-api-client-rs/docs/AddGameRequestBody.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# AddGameRequestBody
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**name** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
12
gamenight-api-client-rs/docs/AddGamenightRequestBody.md
Normal file
12
gamenight-api-client-rs/docs/AddGamenightRequestBody.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# AddGamenightRequestBody
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**name** | **String** | |
|
||||||
|
**datetime** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
390
gamenight-api-client-rs/docs/DefaultApi.md
Normal file
390
gamenight-api-client-rs/docs/DefaultApi.md
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
# \DefaultApi
|
||||||
|
|
||||||
|
All URIs are relative to *http://localhost:8080*
|
||||||
|
|
||||||
|
Method | HTTP request | Description
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
[**game_get**](DefaultApi.md#game_get) | **GET** /game |
|
||||||
|
[**game_post**](DefaultApi.md#game_post) | **POST** /game |
|
||||||
|
[**games_get**](DefaultApi.md#games_get) | **GET** /games |
|
||||||
|
[**get_gamenight**](DefaultApi.md#get_gamenight) | **GET** /gamenight |
|
||||||
|
[**get_gamenights**](DefaultApi.md#get_gamenights) | **GET** /gamenights | Get a all gamenights
|
||||||
|
[**get_token**](DefaultApi.md#get_token) | **GET** /token |
|
||||||
|
[**join_post**](DefaultApi.md#join_post) | **POST** /join |
|
||||||
|
[**leave_post**](DefaultApi.md#leave_post) | **POST** /leave |
|
||||||
|
[**participants_get**](DefaultApi.md#participants_get) | **GET** /participants | Get all participants for a gamenight
|
||||||
|
[**post_gamenight**](DefaultApi.md#post_gamenight) | **POST** /gamenight |
|
||||||
|
[**post_register**](DefaultApi.md#post_register) | **POST** /user |
|
||||||
|
[**post_token**](DefaultApi.md#post_token) | **POST** /token |
|
||||||
|
[**user_get**](DefaultApi.md#user_get) | **GET** /user |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## game_get
|
||||||
|
|
||||||
|
> models::Game game_get(game_id)
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**game_id** | Option<[**GameId**](GameId.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**models::Game**](Game.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## game_post
|
||||||
|
|
||||||
|
> game_post(add_game_request_body)
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**add_game_request_body** | Option<[**AddGameRequestBody**](AddGameRequestBody.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## games_get
|
||||||
|
|
||||||
|
> Vec<models::Game> games_get()
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**Vec<models::Game>**](Game.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## get_gamenight
|
||||||
|
|
||||||
|
> models::Gamenight get_gamenight(get_gamenight_request_body)
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**get_gamenight_request_body** | Option<[**GetGamenightRequestBody**](GetGamenightRequestBody.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**models::Gamenight**](Gamenight.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## get_gamenights
|
||||||
|
|
||||||
|
> Vec<models::Gamenight> get_gamenights()
|
||||||
|
Get a all gamenights
|
||||||
|
|
||||||
|
Retrieve the list of gamenights on this gamenight server. Requires authorization.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**Vec<models::Gamenight>**](Gamenight.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## get_token
|
||||||
|
|
||||||
|
> models::Token get_token(login)
|
||||||
|
|
||||||
|
|
||||||
|
Submit your credentials to get a JWT-token to use with the rest of the api.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**login** | Option<[**Login**](Login.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**models::Token**](Token.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
No authorization required
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## join_post
|
||||||
|
|
||||||
|
> join_post(gamenight_id)
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**gamenight_id** | Option<[**GamenightId**](GamenightId.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## leave_post
|
||||||
|
|
||||||
|
> leave_post(gamenight_id)
|
||||||
|
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**gamenight_id** | Option<[**GamenightId**](GamenightId.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## participants_get
|
||||||
|
|
||||||
|
> models::Participants participants_get(gamenight_id)
|
||||||
|
Get all participants for a gamenight
|
||||||
|
|
||||||
|
Retrieve the participants of a single gamenight by id.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**gamenight_id** | Option<[**GamenightId**](GamenightId.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**models::Participants**](Participants.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## post_gamenight
|
||||||
|
|
||||||
|
> post_gamenight(add_gamenight_request_body)
|
||||||
|
|
||||||
|
|
||||||
|
Add a gamenight by providing a name and a date, only available when providing an JWT token.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**add_gamenight_request_body** | Option<[**AddGamenightRequestBody**](AddGamenightRequestBody.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## post_register
|
||||||
|
|
||||||
|
> post_register(registration)
|
||||||
|
|
||||||
|
|
||||||
|
Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**registration** | Option<[**Registration**](Registration.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
(empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## post_token
|
||||||
|
|
||||||
|
> models::Token post_token()
|
||||||
|
|
||||||
|
|
||||||
|
Refresh your JWT-token without logging in again.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**models::Token**](Token.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
|
## user_get
|
||||||
|
|
||||||
|
> models::User user_get(user_id)
|
||||||
|
|
||||||
|
|
||||||
|
Get a user from primary id
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
|
||||||
|
Name | Type | Description | Required | Notes
|
||||||
|
------------- | ------------- | ------------- | ------------- | -------------
|
||||||
|
**user_id** | Option<[**UserId**](UserId.md)> | | |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**models::User**](User.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[JWT-Auth](../README.md#JWT-Auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
11
gamenight-api-client-rs/docs/Failure.md
Normal file
11
gamenight-api-client-rs/docs/Failure.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Failure
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**message** | Option<**String**> | | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
12
gamenight-api-client-rs/docs/Game.md
Normal file
12
gamenight-api-client-rs/docs/Game.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Game
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | **String** | |
|
||||||
|
**name** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/GameId.md
Normal file
11
gamenight-api-client-rs/docs/GameId.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# GameId
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**game_id** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
14
gamenight-api-client-rs/docs/Gamenight.md
Normal file
14
gamenight-api-client-rs/docs/Gamenight.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Gamenight
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | **String** | |
|
||||||
|
**name** | **String** | |
|
||||||
|
**datetime** | **String** | |
|
||||||
|
**owner_id** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/GamenightId.md
Normal file
11
gamenight-api-client-rs/docs/GamenightId.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# GamenightId
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**gamenight_id** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/GetGamenightRequest.md
Normal file
11
gamenight-api-client-rs/docs/GetGamenightRequest.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# GetGamenightRequest
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | Option<**String**> | | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/GetGamenightRequestBody.md
Normal file
11
gamenight-api-client-rs/docs/GetGamenightRequestBody.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# GetGamenightRequestBody
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | Option<**String**> | | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/GetToken401Response.md
Normal file
11
gamenight-api-client-rs/docs/GetToken401Response.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# GetToken401Response
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**message** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
12
gamenight-api-client-rs/docs/Login.md
Normal file
12
gamenight-api-client-rs/docs/Login.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Login
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**username** | **String** | |
|
||||||
|
**password** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/Participants.md
Normal file
11
gamenight-api-client-rs/docs/Participants.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Participants
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**participants** | **Vec<String>** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
15
gamenight-api-client-rs/docs/Registration.md
Normal file
15
gamenight-api-client-rs/docs/Registration.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Registration
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**username** | **String** | |
|
||||||
|
**email** | **String** | |
|
||||||
|
**password** | **String** | |
|
||||||
|
**password_repeat** | **String** | |
|
||||||
|
**registration_token** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/Token.md
Normal file
11
gamenight-api-client-rs/docs/Token.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Token
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**jwt_token** | Option<**String**> | | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
13
gamenight-api-client-rs/docs/User.md
Normal file
13
gamenight-api-client-rs/docs/User.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# User
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | **String** | |
|
||||||
|
**username** | **String** | |
|
||||||
|
**email** | Option<**String**> | | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
11
gamenight-api-client-rs/docs/UserId.md
Normal file
11
gamenight-api-client-rs/docs/UserId.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# UserId
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**user_id** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
57
gamenight-api-client-rs/git_push.sh
Normal file
57
gamenight-api-client-rs/git_push.sh
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
|
||||||
|
#
|
||||||
|
# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
|
||||||
|
|
||||||
|
git_user_id=$1
|
||||||
|
git_repo_id=$2
|
||||||
|
release_note=$3
|
||||||
|
git_host=$4
|
||||||
|
|
||||||
|
if [ "$git_host" = "" ]; then
|
||||||
|
git_host="github.com"
|
||||||
|
echo "[INFO] No command line input provided. Set \$git_host to $git_host"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$git_user_id" = "" ]; then
|
||||||
|
git_user_id="GIT_USER_ID"
|
||||||
|
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$git_repo_id" = "" ]; then
|
||||||
|
git_repo_id="GIT_REPO_ID"
|
||||||
|
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$release_note" = "" ]; then
|
||||||
|
release_note="Minor update"
|
||||||
|
echo "[INFO] No command line input provided. Set \$release_note to $release_note"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize the local directory as a Git repository
|
||||||
|
git init
|
||||||
|
|
||||||
|
# Adds the files in the local repository and stages them for commit.
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Commits the tracked changes and prepares them to be pushed to a remote repository.
|
||||||
|
git commit -m "$release_note"
|
||||||
|
|
||||||
|
# Sets the new remote
|
||||||
|
git_remote=$(git remote)
|
||||||
|
if [ "$git_remote" = "" ]; then # git remote not defined
|
||||||
|
|
||||||
|
if [ "$GIT_TOKEN" = "" ]; then
|
||||||
|
echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
|
||||||
|
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
|
||||||
|
else
|
||||||
|
git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
git pull origin master
|
||||||
|
|
||||||
|
# Pushes (Forces) the changes in the local repository up to the remote repository
|
||||||
|
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
|
||||||
|
git push origin master 2>&1 | grep -v 'To https'
|
51
gamenight-api-client-rs/src/apis/configuration.rs
Normal file
51
gamenight-api-client-rs/src/apis/configuration.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Configuration {
|
||||||
|
pub base_path: String,
|
||||||
|
pub user_agent: Option<String>,
|
||||||
|
pub client: reqwest::Client,
|
||||||
|
pub basic_auth: Option<BasicAuth>,
|
||||||
|
pub oauth_access_token: Option<String>,
|
||||||
|
pub bearer_access_token: Option<String>,
|
||||||
|
pub api_key: Option<ApiKey>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type BasicAuth = (String, Option<String>);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ApiKey {
|
||||||
|
pub prefix: Option<String>,
|
||||||
|
pub key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Configuration {
|
||||||
|
pub fn new() -> Configuration {
|
||||||
|
Configuration::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Configuration {
|
||||||
|
fn default() -> Self {
|
||||||
|
Configuration {
|
||||||
|
base_path: "http://localhost:8080".to_owned(),
|
||||||
|
user_agent: Some("OpenAPI-Generator/1.0/rust".to_owned()),
|
||||||
|
client: reqwest::Client::new(),
|
||||||
|
basic_auth: None,
|
||||||
|
oauth_access_token: None,
|
||||||
|
bearer_access_token: None,
|
||||||
|
api_key: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
593
gamenight-api-client-rs/src/apis/default_api.rs
Normal file
593
gamenight-api-client-rs/src/apis/default_api.rs
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
use reqwest;
|
||||||
|
use serde::{Deserialize, Serialize, de::Error as _};
|
||||||
|
use crate::{apis::ResponseContent, models};
|
||||||
|
use super::{Error, configuration, ContentType};
|
||||||
|
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`game_get`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GameGetError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`game_post`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GamePostError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`games_get`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GamesGetError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`get_gamenight`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GetGamenightError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`get_gamenights`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GetGamenightsError {
|
||||||
|
Status400(models::Failure),
|
||||||
|
Status401(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`get_token`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GetTokenError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`join_post`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum JoinPostError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`leave_post`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum LeavePostError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`participants_get`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ParticipantsGetError {
|
||||||
|
Status400(models::Failure),
|
||||||
|
Status401(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`post_gamenight`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum PostGamenightError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`post_register`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum PostRegisterError {
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`post_token`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum PostTokenError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// struct for typed errors of method [`user_get`]
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum UserGetError {
|
||||||
|
Status401(models::Failure),
|
||||||
|
Status404(models::Failure),
|
||||||
|
Status422(models::Failure),
|
||||||
|
UnknownValue(serde_json::Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn game_get(configuration: &configuration::Configuration, game_id: Option<models::GameId>) -> Result<models::Game, Error<GameGetError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_game_id = game_id;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/game", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_game_id);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Game`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Game`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<GameGetError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn game_post(configuration: &configuration::Configuration, add_game_request_body: Option<models::AddGameRequestBody>) -> Result<(), Error<GamePostError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_add_game_request_body = add_game_request_body;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/game", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_add_game_request_body);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<GamePostError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn games_get(configuration: &configuration::Configuration, ) -> Result<Vec<models::Game>, Error<GamesGetError>> {
|
||||||
|
|
||||||
|
let uri_str = format!("{}/games", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `Vec<models::Game>`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `Vec<models::Game>`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<GamesGetError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_gamenight(configuration: &configuration::Configuration, get_gamenight_request_body: Option<models::GetGamenightRequestBody>) -> Result<models::Gamenight, Error<GetGamenightError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_get_gamenight_request_body = get_gamenight_request_body;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/gamenight", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_get_gamenight_request_body);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Gamenight`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Gamenight`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<GetGamenightError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the list of gamenights on this gamenight server. Requires authorization.
|
||||||
|
pub async fn get_gamenights(configuration: &configuration::Configuration, ) -> Result<Vec<models::Gamenight>, Error<GetGamenightsError>> {
|
||||||
|
|
||||||
|
let uri_str = format!("{}/gamenights", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `Vec<models::Gamenight>`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `Vec<models::Gamenight>`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<GetGamenightsError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Submit your credentials to get a JWT-token to use with the rest of the api.
|
||||||
|
pub async fn get_token(configuration: &configuration::Configuration, login: Option<models::Login>) -> Result<models::Token, Error<GetTokenError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_login = login;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/token", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
req_builder = req_builder.json(&p_login);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Token`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Token`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<GetTokenError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn join_post(configuration: &configuration::Configuration, gamenight_id: Option<models::GamenightId>) -> Result<(), Error<JoinPostError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_gamenight_id = gamenight_id;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/join", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_gamenight_id);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<JoinPostError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn leave_post(configuration: &configuration::Configuration, gamenight_id: Option<models::GamenightId>) -> Result<(), Error<LeavePostError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_gamenight_id = gamenight_id;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/leave", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_gamenight_id);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<LeavePostError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the participants of a single gamenight by id.
|
||||||
|
pub async fn participants_get(configuration: &configuration::Configuration, gamenight_id: Option<models::GamenightId>) -> Result<models::Participants, Error<ParticipantsGetError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_gamenight_id = gamenight_id;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/participants", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_gamenight_id);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Participants`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Participants`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<ParticipantsGetError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a gamenight by providing a name and a date, only available when providing an JWT token.
|
||||||
|
pub async fn post_gamenight(configuration: &configuration::Configuration, add_gamenight_request_body: Option<models::AddGamenightRequestBody>) -> Result<(), Error<PostGamenightError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_add_gamenight_request_body = add_gamenight_request_body;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/gamenight", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_add_gamenight_request_body);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<PostGamenightError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.
|
||||||
|
pub async fn post_register(configuration: &configuration::Configuration, registration: Option<models::Registration>) -> Result<(), Error<PostRegisterError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_registration = registration;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/user", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_registration);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<PostRegisterError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Refresh your JWT-token without logging in again.
|
||||||
|
pub async fn post_token(configuration: &configuration::Configuration, ) -> Result<models::Token, Error<PostTokenError>> {
|
||||||
|
|
||||||
|
let uri_str = format!("{}/token", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Token`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Token`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<PostTokenError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a user from primary id
|
||||||
|
pub async fn user_get(configuration: &configuration::Configuration, user_id: Option<models::UserId>) -> Result<models::User, Error<UserGetError>> {
|
||||||
|
// add a prefix to parameters to efficiently prevent name collisions
|
||||||
|
let p_user_id = user_id;
|
||||||
|
|
||||||
|
let uri_str = format!("{}/user", configuration.base_path);
|
||||||
|
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
|
||||||
|
|
||||||
|
if let Some(ref user_agent) = configuration.user_agent {
|
||||||
|
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||||
|
}
|
||||||
|
if let Some(ref token) = configuration.bearer_access_token {
|
||||||
|
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||||
|
};
|
||||||
|
req_builder = req_builder.json(&p_user_id);
|
||||||
|
|
||||||
|
let req = req_builder.build()?;
|
||||||
|
let resp = configuration.client.execute(req).await?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let content_type = resp
|
||||||
|
.headers()
|
||||||
|
.get("content-type")
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("application/octet-stream");
|
||||||
|
let content_type = super::ContentType::from(content_type);
|
||||||
|
|
||||||
|
if !status.is_client_error() && !status.is_server_error() {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||||
|
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::User`"))),
|
||||||
|
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::User`")))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let content = resp.text().await?;
|
||||||
|
let entity: Option<UserGetError> = serde_json::from_str(&content).ok();
|
||||||
|
Err(Error::ResponseError(ResponseContent { status, content, entity }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
116
gamenight-api-client-rs/src/apis/mod.rs
Normal file
116
gamenight-api-client-rs/src/apis/mod.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ResponseContent<T> {
|
||||||
|
pub status: reqwest::StatusCode,
|
||||||
|
pub content: String,
|
||||||
|
pub entity: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error<T> {
|
||||||
|
Reqwest(reqwest::Error),
|
||||||
|
Serde(serde_json::Error),
|
||||||
|
Io(std::io::Error),
|
||||||
|
ResponseError(ResponseContent<T>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T> fmt::Display for Error<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let (module, e) = match self {
|
||||||
|
Error::Reqwest(e) => ("reqwest", e.to_string()),
|
||||||
|
Error::Serde(e) => ("serde", e.to_string()),
|
||||||
|
Error::Io(e) => ("IO", e.to_string()),
|
||||||
|
Error::ResponseError(e) => ("response", format!("status code {}", e.status)),
|
||||||
|
};
|
||||||
|
write!(f, "error in {}: {}", module, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: fmt::Debug> error::Error for Error<T> {
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
Some(match self {
|
||||||
|
Error::Reqwest(e) => e,
|
||||||
|
Error::Serde(e) => e,
|
||||||
|
Error::Io(e) => e,
|
||||||
|
Error::ResponseError(_) => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T> From<reqwest::Error> for Error<T> {
|
||||||
|
fn from(e: reqwest::Error) -> Self {
|
||||||
|
Error::Reqwest(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T> From<serde_json::Error> for Error<T> {
|
||||||
|
fn from(e: serde_json::Error) -> Self {
|
||||||
|
Error::Serde(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T> From<std::io::Error> for Error<T> {
|
||||||
|
fn from(e: std::io::Error) -> Self {
|
||||||
|
Error::Io(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn urlencode<T: AsRef<str>>(s: T) -> String {
|
||||||
|
::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> {
|
||||||
|
if let serde_json::Value::Object(object) = value {
|
||||||
|
let mut params = vec![];
|
||||||
|
|
||||||
|
for (key, value) in object {
|
||||||
|
match value {
|
||||||
|
serde_json::Value::Object(_) => params.append(&mut parse_deep_object(
|
||||||
|
&format!("{}[{}]", prefix, key),
|
||||||
|
value,
|
||||||
|
)),
|
||||||
|
serde_json::Value::Array(array) => {
|
||||||
|
for (i, value) in array.iter().enumerate() {
|
||||||
|
params.append(&mut parse_deep_object(
|
||||||
|
&format!("{}[{}][{}]", prefix, key, i),
|
||||||
|
value,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())),
|
||||||
|
_ => params.push((format!("{}[{}]", prefix, key), value.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
unimplemented!("Only objects are supported with style=deepObject")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal use only
|
||||||
|
/// A content type supported by this client.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
enum ContentType {
|
||||||
|
Json,
|
||||||
|
Text,
|
||||||
|
Unsupported(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for ContentType {
|
||||||
|
fn from(content_type: &str) -> Self {
|
||||||
|
if content_type.starts_with("application") && content_type.contains("json") {
|
||||||
|
return Self::Json;
|
||||||
|
} else if content_type.starts_with("text/plain") {
|
||||||
|
return Self::Text;
|
||||||
|
} else {
|
||||||
|
return Self::Unsupported(content_type.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod default_api;
|
||||||
|
|
||||||
|
pub mod configuration;
|
11
gamenight-api-client-rs/src/lib.rs
Normal file
11
gamenight-api-client-rs/src/lib.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#![allow(unused_imports)]
|
||||||
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
|
extern crate serde_repr;
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
extern crate url;
|
||||||
|
extern crate reqwest;
|
||||||
|
|
||||||
|
pub mod apis;
|
||||||
|
pub mod models;
|
27
gamenight-api-client-rs/src/models/add_game.rs
Normal file
27
gamenight-api-client-rs/src/models/add_game.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct AddGame {
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddGame {
|
||||||
|
pub fn new(name: String) -> AddGame {
|
||||||
|
AddGame {
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/add_game_request_body.rs
Normal file
27
gamenight-api-client-rs/src/models/add_game_request_body.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct AddGameRequestBody {
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddGameRequestBody {
|
||||||
|
pub fn new(name: String) -> AddGameRequestBody {
|
||||||
|
AddGameRequestBody {
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct AddGamenightRequestBody {
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
pub name: String,
|
||||||
|
#[serde(rename = "datetime")]
|
||||||
|
pub datetime: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddGamenightRequestBody {
|
||||||
|
pub fn new(name: String, datetime: String) -> AddGamenightRequestBody {
|
||||||
|
AddGamenightRequestBody {
|
||||||
|
name,
|
||||||
|
datetime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
29
gamenight-api-client-rs/src/models/failure.rs
Normal file
29
gamenight-api-client-rs/src/models/failure.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Failure : Failure Reason
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Failure {
|
||||||
|
#[serde(rename = "message", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Failure {
|
||||||
|
/// Failure Reason
|
||||||
|
pub fn new() -> Failure {
|
||||||
|
Failure {
|
||||||
|
message: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
30
gamenight-api-client-rs/src/models/game.rs
Normal file
30
gamenight-api-client-rs/src/models/game.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Game {
|
||||||
|
#[serde(rename = "id")]
|
||||||
|
pub id: String,
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
pub fn new(id: String, name: String) -> Game {
|
||||||
|
Game {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/game_id.rs
Normal file
27
gamenight-api-client-rs/src/models/game_id.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GameId {
|
||||||
|
#[serde(rename = "game_id")]
|
||||||
|
pub game_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameId {
|
||||||
|
pub fn new(game_id: String) -> GameId {
|
||||||
|
GameId {
|
||||||
|
game_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
gamenight-api-client-rs/src/models/gamenight.rs
Normal file
36
gamenight-api-client-rs/src/models/gamenight.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Gamenight {
|
||||||
|
#[serde(rename = "id")]
|
||||||
|
pub id: String,
|
||||||
|
#[serde(rename = "name")]
|
||||||
|
pub name: String,
|
||||||
|
#[serde(rename = "datetime")]
|
||||||
|
pub datetime: String,
|
||||||
|
#[serde(rename = "owner_id")]
|
||||||
|
pub owner_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gamenight {
|
||||||
|
pub fn new(id: String, name: String, datetime: String, owner_id: String) -> Gamenight {
|
||||||
|
Gamenight {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
datetime,
|
||||||
|
owner_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/gamenight_id.rs
Normal file
27
gamenight-api-client-rs/src/models/gamenight_id.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GamenightId {
|
||||||
|
#[serde(rename = "gamenight_id")]
|
||||||
|
pub gamenight_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GamenightId {
|
||||||
|
pub fn new(gamenight_id: String) -> GamenightId {
|
||||||
|
GamenightId {
|
||||||
|
gamenight_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/get_gamenight_request.rs
Normal file
27
gamenight-api-client-rs/src/models/get_gamenight_request.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GetGamenightRequest {
|
||||||
|
#[serde(rename = "id", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetGamenightRequest {
|
||||||
|
pub fn new() -> GetGamenightRequest {
|
||||||
|
GetGamenightRequest {
|
||||||
|
id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GetGamenightRequestBody {
|
||||||
|
#[serde(rename = "id", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetGamenightRequestBody {
|
||||||
|
pub fn new() -> GetGamenightRequestBody {
|
||||||
|
GetGamenightRequestBody {
|
||||||
|
id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/get_token_401_response.rs
Normal file
27
gamenight-api-client-rs/src/models/get_token_401_response.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GetToken401Response {
|
||||||
|
#[serde(rename = "message")]
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetToken401Response {
|
||||||
|
pub fn new(message: String) -> GetToken401Response {
|
||||||
|
GetToken401Response {
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
30
gamenight-api-client-rs/src/models/login.rs
Normal file
30
gamenight-api-client-rs/src/models/login.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Login {
|
||||||
|
#[serde(rename = "username")]
|
||||||
|
pub username: String,
|
||||||
|
#[serde(rename = "password")]
|
||||||
|
pub password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Login {
|
||||||
|
pub fn new(username: String, password: String) -> Login {
|
||||||
|
Login {
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
28
gamenight-api-client-rs/src/models/mod.rs
Normal file
28
gamenight-api-client-rs/src/models/mod.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
pub mod add_game_request_body;
|
||||||
|
pub use self::add_game_request_body::AddGameRequestBody;
|
||||||
|
pub mod add_gamenight_request_body;
|
||||||
|
pub use self::add_gamenight_request_body::AddGamenightRequestBody;
|
||||||
|
pub mod failure;
|
||||||
|
pub use self::failure::Failure;
|
||||||
|
pub mod game;
|
||||||
|
pub use self::game::Game;
|
||||||
|
pub mod game_id;
|
||||||
|
pub use self::game_id::GameId;
|
||||||
|
pub mod gamenight;
|
||||||
|
pub use self::gamenight::Gamenight;
|
||||||
|
pub mod gamenight_id;
|
||||||
|
pub use self::gamenight_id::GamenightId;
|
||||||
|
pub mod get_gamenight_request_body;
|
||||||
|
pub use self::get_gamenight_request_body::GetGamenightRequestBody;
|
||||||
|
pub mod login;
|
||||||
|
pub use self::login::Login;
|
||||||
|
pub mod participants;
|
||||||
|
pub use self::participants::Participants;
|
||||||
|
pub mod registration;
|
||||||
|
pub use self::registration::Registration;
|
||||||
|
pub mod token;
|
||||||
|
pub use self::token::Token;
|
||||||
|
pub mod user;
|
||||||
|
pub use self::user::User;
|
||||||
|
pub mod user_id;
|
||||||
|
pub use self::user_id::UserId;
|
27
gamenight-api-client-rs/src/models/participants.rs
Normal file
27
gamenight-api-client-rs/src/models/participants.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Participants {
|
||||||
|
#[serde(rename = "participants")]
|
||||||
|
pub participants: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Participants {
|
||||||
|
pub fn new(participants: Vec<String>) -> Participants {
|
||||||
|
Participants {
|
||||||
|
participants,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
39
gamenight-api-client-rs/src/models/registration.rs
Normal file
39
gamenight-api-client-rs/src/models/registration.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Registration {
|
||||||
|
#[serde(rename = "username")]
|
||||||
|
pub username: String,
|
||||||
|
#[serde(rename = "email")]
|
||||||
|
pub email: String,
|
||||||
|
#[serde(rename = "password")]
|
||||||
|
pub password: String,
|
||||||
|
#[serde(rename = "password_repeat")]
|
||||||
|
pub password_repeat: String,
|
||||||
|
#[serde(rename = "registration_token")]
|
||||||
|
pub registration_token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Registration {
|
||||||
|
pub fn new(username: String, email: String, password: String, password_repeat: String, registration_token: String) -> Registration {
|
||||||
|
Registration {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
password_repeat,
|
||||||
|
registration_token,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/token.rs
Normal file
27
gamenight-api-client-rs/src/models/token.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Token {
|
||||||
|
#[serde(rename = "jwt_token", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub jwt_token: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Token {
|
||||||
|
pub fn new() -> Token {
|
||||||
|
Token {
|
||||||
|
jwt_token: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
33
gamenight-api-client-rs/src/models/user.rs
Normal file
33
gamenight-api-client-rs/src/models/user.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct User {
|
||||||
|
#[serde(rename = "id")]
|
||||||
|
pub id: String,
|
||||||
|
#[serde(rename = "username")]
|
||||||
|
pub username: String,
|
||||||
|
#[serde(rename = "email", skip_serializing_if = "Option::is_none")]
|
||||||
|
pub email: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
pub fn new(id: String, username: String) -> User {
|
||||||
|
User {
|
||||||
|
id,
|
||||||
|
username,
|
||||||
|
email: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
gamenight-api-client-rs/src/models/user_id.rs
Normal file
27
gamenight-api-client-rs/src/models/user_id.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Gamenight
|
||||||
|
*
|
||||||
|
* Api specifaction for a Gamenight server
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0
|
||||||
|
* Contact: dennis@brentj.es
|
||||||
|
* Generated by: https://openapi-generator.tech
|
||||||
|
*/
|
||||||
|
|
||||||
|
use crate::models;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct UserId {
|
||||||
|
#[serde(rename = "user_id")]
|
||||||
|
pub user_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserId {
|
||||||
|
pub fn new(user_id: String) -> UserId {
|
||||||
|
UserId {
|
||||||
|
user_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
gamenight-cli/.gitignore
vendored
Normal file
1
gamenight-cli/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
target
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user