aboutsummaryrefslogtreecommitdiff
path: root/src/db.rs
diff options
context:
space:
mode:
authorCurly Bryce <curlybryce@protonmail.com>2024-07-03 14:33:18 -0600
committerCurly Bryce <curlybryce@protonmail.com>2024-07-03 14:33:18 -0600
commit8c68b01bb9a28ada388187c17fa9b28a115e7cc7 (patch)
tree154296044638473e53d6d00141fb2d216fd619a3 /src/db.rs
parent5bd4ddc7627ae1114d15f6f0485b2cef571be1b7 (diff)
downloadpoko_server-8c68b01bb9a28ada388187c17fa9b28a115e7cc7.tar.gz
poko_server-8c68b01bb9a28ada388187c17fa9b28a115e7cc7.tar.bz2
poko_server-8c68b01bb9a28ada388187c17fa9b28a115e7cc7.zip
user login/logout
Diffstat (limited to 'src/db.rs')
-rw-r--r--src/db.rs253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/db.rs b/src/db.rs
new file mode 100644
index 0000000..43a2cc7
--- /dev/null
+++ b/src/db.rs
@@ -0,0 +1,253 @@
+use serde::{Serialize, Deserialize};
+use sha2::{Digest, Sha256};
+use std::collections::HashMap;
+use std::path::PathBuf;
+use std::{fs::File, io::Write};
+
+use crate::uid::{self, UID};
+
+#[derive(Serialize, Deserialize)]
+pub struct Config {
+ dbsave: PathBuf,
+ realm: String,
+}
+impl Config {
+ pub fn new() -> Config {
+ Config { dbsave: "db.json".into(), realm: "localhost".into() }
+ }
+}
+
+#[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)]
+pub struct User {
+ name: String,
+ hashed_password: String,
+ id: UID,
+ sessions: HashMap<String, String>,
+ tokovec: Vec<Token>,
+}
+impl User {
+ pub fn new(name: String, password: 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),
+ ];
+
+ let hashed_password = User::hash(&password);
+
+ User { name, hashed_password, id, tokovec: base_tokens, sessions: HashMap::new() }
+ }
+
+ fn hash(t: &String) -> String {
+ let hashed = Sha256::digest(&t);
+ let hashed = base16ct::lower::encode_string(&hashed);
+
+ hashed
+ }
+
+ fn new_session(&mut self, client: String) -> String {
+ let hash: [u8; 32] = rand::random();
+ let hash = User::hash(&hash.iter().map(|v| {format!("{}", v)}).collect());
+ self.sessions.insert(hash.clone(), client);
+ hash
+ }
+
+ fn rm_session(&mut self, session: &String) -> Result<(), String> {
+ match self.sessions.remove(session) {
+ Some(_) => Ok(()),
+ None => Err("Could not find sessoin".into()),
+ }
+ }
+
+ fn clear_sessions(&mut self) {
+ self.sessions.clear()
+ }
+
+ fn get_sessions(&mut self) -> Vec<(String, String)> {
+ self.sessions.iter().map(|(k, v)| {
+ (k.clone(), v.clone())
+ }).collect()
+ }
+
+ fn login(&mut self, password: &String, clientid: &String) -> Result<String, String> {
+ if self.hashed_password == User::hash(password) {
+ Ok(self.new_session(clientid.clone()))
+ } else {
+ Err("Could not login".into())
+ }
+ }
+
+ fn authenticate(&self, session: &String) -> bool {
+ match self.sessions.get(session) {
+ // Session authenticated/found
+ Some(_) => true,
+ // Session not found
+ None => false,
+ }
+
+ }
+
+ fn logout(&mut self, session: &String) -> Result<(), String> {
+ if self.authenticate(session) {
+ self.rm_session(session)
+ } else {
+ Err("Not Authenticated".into())
+ }
+ }
+
+ pub fn get_name(&self) -> String {
+ self.name.clone()
+ }
+ pub fn hex_id(&self) -> String {
+ self.id.to_hex()
+ }
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct DB {
+ pub uid_generator: uid::Generator,
+ users: Vec<User>,
+ config: Config,
+}
+impl DB {
+ async fn save(&self) -> Result<(), String> {
+ let mut f = match File::create(&self.config.dbsave) {
+ Ok(n) => n,
+ Err(n) => {
+ match n.kind() {
+ std::io::ErrorKind::PermissionDenied => panic!("{:?}: Permission Denied", &self.config.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(c: Config) -> Self {
+ match File::open(&c.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", &c.dbsave),
+ _ => DB::new(c),
+ },
+ }
+ }
+ pub fn new(config: Config) -> Self {
+ DB { uid_generator: uid::Generator::new(), users: vec![], config }
+ }
+
+ pub async fn get_user(&mut self, id: &str) -> Result<&User, String> {
+ match UID::from(id.to_string()) {
+ Ok(n) => {
+ for u in self.users.iter_mut() {
+ if u.id == n {
+ return Ok(u)
+ }
+ }
+ },
+ Err(_) => (),
+ }
+
+ Err("Not Found".into())
+ }
+ pub async fn get_mut_user(&mut self, id: &str) -> Result<&mut User, String> {
+ match UID::from(id.to_string()) {
+ Ok(n) => {
+ for u in self.users.iter_mut() {
+ if u.id == n {
+ return Ok(u)
+ }
+ }
+ },
+ Err(_) => (),
+ }
+
+ Err("Not Found".into())
+ }
+
+ pub async fn get_user_by_name(&self, name: &str) -> Result<Vec<User>, String> {
+ let mut vec = vec![];
+ for u in self.users.clone() {
+ if u.name == name {
+ vec.push(u)
+ }
+ }
+
+ if vec.len() == 0 {
+ Err("Not Found".into())
+ } else {
+ return Ok(vec)
+ }
+
+ }
+
+ pub async fn get_all_users(&self) -> Result<Vec<User>, String> {
+ if self.users.len() == 0 {
+ Err("No Users".into())
+ } else {
+ Ok(self.users.clone())
+ }
+ }
+
+ pub async fn new_user(&mut self, name: String, password: String, id: UID) -> Result<(), String> {
+ let user = User::new(name, password, id);
+ self.users.push(user);
+ self.save().await
+ }
+
+ pub async fn login(&mut self, id: &String, password: &String, clientid: &String) -> Result<String, String> {
+ let r = match self.get_mut_user(id).await {
+ Ok(n) => {
+ n.login(password, clientid)
+ },
+ Err(n) => Err(n)
+ };
+
+ let _ = self.save().await;
+ r
+ }
+ pub async fn logout(&mut self, id: &String, session: &String) -> Result<(), String> {
+ let r = match self.get_mut_user(id).await {
+ Ok(n) => {
+ n.logout(session)
+ },
+ Err(n) => Err(n)
+ };
+
+ let _ = self.save().await;
+ r
+ }
+}