forked from Roflin/gamenight
Initial commit
This commit is contained in:
58
src/api.rs
Normal file
58
src/api.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use crate::schema;
|
||||
use rocket::form::Form;
|
||||
use rocket::serde::json::{Json, json, Value};
|
||||
use rocket::http::Status;
|
||||
use rocket::request::{self, Request, FromRequest};
|
||||
use rocket::outcome::Outcome::{Success, Failure};
|
||||
use rocket::response::{Redirect, Flash};
|
||||
|
||||
pub struct Referer(String);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ReferrerError {
|
||||
Missing,
|
||||
MoreThanOne
|
||||
}
|
||||
|
||||
#[derive(Debug, Responder)]
|
||||
pub enum ApiResponse {
|
||||
Status(Status),
|
||||
Redirect(Redirect),
|
||||
Value(Value),
|
||||
Flash(Flash<Redirect>)
|
||||
}
|
||||
|
||||
#[rocket::async_trait]
|
||||
impl<'r> FromRequest<'r> for Referer {
|
||||
type Error = ReferrerError;
|
||||
|
||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||
let referers : Vec<_> = req.headers().get("Referer").collect();
|
||||
match referers.len() {
|
||||
0 => Failure((Status::BadRequest, ReferrerError::Missing)),
|
||||
1 => Success(Referer(referers[0].to_string())),
|
||||
_ => Failure((Status::BadRequest, ReferrerError::MoreThanOne)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/gamenights")]
|
||||
pub async fn gamenights(conn: schema::DbConn) -> ApiResponse {
|
||||
let gamenights = schema::get_all_gamenights(conn).await;
|
||||
ApiResponse::Value(json!(gamenights))
|
||||
}
|
||||
|
||||
#[post("/gamenight", format = "application/json", data = "<gamenight_json>")]
|
||||
pub async fn gamenight_post_json(conn: schema::DbConn, gamenight_json: Json<schema::GameNightNoId>) -> ApiResponse {
|
||||
schema::insert_gamenight(conn, gamenight_json.into_inner()).await;
|
||||
ApiResponse::Status(Status::Accepted)
|
||||
}
|
||||
|
||||
#[post("/gamenight", format = "application/x-www-form-urlencoded", data = "<gamenight_form>")]
|
||||
pub async fn gamenight_post_form(referer: Option<Referer>, conn: schema::DbConn, gamenight_form: Form<schema::GameNightNoId>) -> ApiResponse {
|
||||
schema::insert_gamenight(conn, gamenight_form.into_inner()).await;
|
||||
match referer {
|
||||
None => ApiResponse::Status(Status::Accepted),
|
||||
Some(referer) => ApiResponse::Flash(Flash::success(Redirect::to(referer.0), "Added Gamenight."))
|
||||
}
|
||||
}
|
||||
20
src/main.rs
Normal file
20
src/main.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
#[macro_use] extern crate rocket;
|
||||
#[macro_use] extern crate diesel_migrations;
|
||||
#[macro_use] extern crate diesel;
|
||||
|
||||
use rocket::fairing::AdHoc;
|
||||
use rocket_dyn_templates::Template;
|
||||
|
||||
mod api;
|
||||
pub mod schema;
|
||||
mod site;
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
rocket::build()
|
||||
.attach(schema::DbConn::fairing())
|
||||
.attach(Template::fairing())
|
||||
.attach(AdHoc::on_ignite("Run Migrations", schema::run_migrations))
|
||||
.mount("/", routes![site::index, site::gamenights, site::add_game_night])
|
||||
.mount("/api", routes![api::gamenights, api::gamenight_post_form, api::gamenight_post_json])
|
||||
}
|
||||
83
src/schema.rs
Normal file
83
src/schema.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use rocket_sync_db_pools::database;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use rocket::{Rocket, Build};
|
||||
use diesel::RunQueryDsl;
|
||||
|
||||
|
||||
#[database("gamenight_database")]
|
||||
pub struct DbConn(diesel::SqliteConnection);
|
||||
|
||||
table! {
|
||||
gamenight (id) {
|
||||
id -> Integer,
|
||||
game -> Text,
|
||||
datetime -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
known_games (game) {
|
||||
id -> Integer,
|
||||
game -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
gamenight,
|
||||
known_games,
|
||||
);
|
||||
|
||||
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 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(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,
|
||||
}
|
||||
|
||||
|
||||
57
src/site.rs
Normal file
57
src/site.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use rocket_dyn_templates::Template;
|
||||
use rocket::response::{Redirect};
|
||||
use rocket::request::{FlashMessage};
|
||||
use crate::schema;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct FlashData {
|
||||
has_data: bool,
|
||||
kind: String,
|
||||
message: String
|
||||
|
||||
}
|
||||
|
||||
#[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 { has_data: false, message: "".to_string(), kind: "".to_string() }
|
||||
};
|
||||
|
||||
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 { has_data: false, message: "".to_string(), kind: "".to_string() },
|
||||
Some(flash) => FlashData { has_data: true, message: flash.message().to_string(), kind: flash.kind().to_string() }
|
||||
};
|
||||
|
||||
let data = GameNightAddData {
|
||||
post_url: "/api/gamenight".to_string(),
|
||||
flash: flash_data
|
||||
};
|
||||
|
||||
Template::render("gamenight_add", &data)
|
||||
}
|
||||
Reference in New Issue
Block a user