aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs195
1 files changed, 195 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..c3fcf91
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,195 @@
+#[macro_use] extern crate rocket;
+
+use std::{fs::File, io::Write};
+
+use rocket::{serde::json::Json, State};
+use serde::{Deserialize, Serialize};
+
+mod uid;
+use tokio::sync::Mutex;
+use uid::UID;
+
+#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
+enum Color {
+ White,
+ Red,
+ Blue,
+ Green,
+ Yellow,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+struct Token {
+ color: Color,
+ amount: usize,
+}
+impl Token {
+ pub fn new(color: Color, amount: usize) -> Token {
+ Token { color, amount }
+ }
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+struct User {
+ name: String,
+ id: UID,
+ tokovec: Vec<Token>
+}
+impl User {
+ pub fn new(name: String, id: UID) -> User {
+ let base_tokens = vec![
+ Token::new(Color::White, 2),
+ Token::new(Color::Red, 2),
+ Token::new(Color::Blue, 2),
+ Token::new(Color::Green, 2),
+ Token::new(Color::Yellow, 2),
+ ];
+ User { name: name, id: id, tokovec: base_tokens }
+ }
+}
+
+const DBSAVE: &str = "db.json";
+
+#[derive(Serialize, Deserialize)]
+struct DB {
+ uid_generator: uid::Generator,
+ users: Vec<User>,
+}
+impl DB {
+ async fn save(&self) -> Result<(), String> {
+ let mut f = match File::create(DBSAVE) {
+ Ok(n) => n,
+ Err(n) => {
+ match n.kind() {
+ std::io::ErrorKind::PermissionDenied => panic!("{}: Permission Denied", DBSAVE),
+ n => return Err(n.to_string()),
+ }
+ },
+ };
+ let s = match serde_json::to_string(self) {
+ Ok(n) => n,
+ Err(n) => return Err(n.to_string()),
+ };
+ match f.write(s.as_bytes()) {
+ Ok(_) => return Ok(()),
+ Err(n) => return Err(n.to_string()),
+ };
+ }
+ pub fn load() -> Self {
+ match File::open(DBSAVE) {
+ Ok(n) => {
+ match serde_json::from_reader(n) {
+ Ok(n) => n,
+ Err(n) => panic!("{}", n),
+ }
+ },
+ Err(n) => match n.kind() {
+ std::io::ErrorKind::PermissionDenied => panic!("{}: Permission Denied", DBSAVE),
+ _ => DB::new(),
+ },
+ }
+ }
+ pub fn new() -> Self {
+ DB { uid_generator: uid::Generator::new(), users: vec![] }
+ }
+
+ async fn get_user(&self, name: &str) -> Result<User, String> {
+ for u in self.users.clone() {
+ if u.name == name {
+ return Ok(u)
+ }
+ }
+
+ Err("Not Found".into())
+ }
+
+ async fn new_user(&mut self, name: String, id: UID) -> Result<(), String> {
+ let user = User::new(name, id);
+ self.users.push(user);
+ self.save().await
+ }
+}
+
+#[derive(Debug, Serialize)]
+struct TextResponse {
+ message: String
+}
+impl From<&'static str> for TextResponse {
+ fn from(value: &'static str) -> Self {
+ TextResponse{message: value.into()}
+ }
+}
+
+#[derive(Debug, Deserialize)]
+struct InputForm {
+ user: String,
+ password: String,
+}
+impl InputForm {
+ pub fn login(&self) -> bool {
+ self.user == self.password
+ }
+}
+
+#[get("/")]
+async fn index() -> &'static str {
+ "This is a POKO server"
+}
+
+#[get("/user/<user>")]
+async fn get_user(user: &str, db: &State<Mutex<DB>>) -> Json<Result<User, String>> {
+ let db = db.lock().await;
+ db.get_user(user).await.into()
+}
+
+fn default_id() -> String {
+ "random".into()
+}
+#[derive(Deserialize)]
+struct UserForm {
+ name: String,
+ #[serde(default = "default_id")]
+ id: String,
+}
+#[post("/user", data="<data>", format="json")]
+async fn new_user(data: Json<UserForm>, db: &State<Mutex<DB>>) -> Json<Result<(), String>> {
+ let mut db = db.lock().await;
+ if data.id == "random".to_string() {
+ match db.uid_generator.new_uid() {
+ Ok(n) => return db.new_user(data.name.clone(), n).await.into(),
+ Err(n) => return Err(n.clone()).into(),
+ }
+ } else {
+ match UID::from(data.id.clone()) {
+ Err(n) => Err(n).into(),
+ Ok(n) => {
+ if db.uid_generator.is_taken(n) {
+ return Err("UID is taken".to_string()).into();
+ } else {
+ // UID is not taken
+ match db.uid_generator.add_uid(n) {
+ Err(n) => return Err(n).into(),
+ Ok(n) => {
+ return db.new_user(data.name.clone(), n).await.into();
+ },
+ }
+ }
+ },
+ }
+ }
+}
+
+#[post("/", data="<body>", format="json")]
+async fn posttest(body: Json<InputForm>) -> Json<TextResponse> {
+ println!("{:?}", body);
+ if body.login() {
+ TextResponse::from("Equal").into()
+ } else {
+ TextResponse::from("Not Equal").into()
+ }
+}
+
+#[launch]
+fn rocket() -> _ {
+ rocket::build().manage(Mutex::new(DB::load())).mount("/", routes![index, posttest, new_user, get_user])
+} \ No newline at end of file