From e48ed1f2dd19af8e62ad7b3868bf39b035f3073c Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Thu, 30 Dec 2021 00:05:35 -0500 Subject: [PATCH] =?UTF-8?q?Kreu=20a=C5=ADtentigo=20kaj=20rajtigo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ĉi tiuj modjuloj aŭtentigas uzanton kaj provas la rajtojn de la uzanto. --- Cargo.lock | 208 +-------------------------------------- aŭtentigo.db | 1 + servilo/Cargo.toml | 2 +- servilo/src/aŭtentigo.rs | 100 +++++++++++++++++++ servilo/src/main.rs | 103 ++++++++++--------- servilo/src/rajtigo.rs | 74 ++++++++++++++ shell.nix | 6 +- 7 files changed, 239 insertions(+), 255 deletions(-) create mode 100644 aŭtentigo.db create mode 100644 servilo/src/aŭtentigo.rs create mode 100644 servilo/src/rajtigo.rs diff --git a/Cargo.lock b/Cargo.lock index 67f0e1c..9ccaff9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,42 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - [[package]] name = "base64" version = "0.13.0" @@ -81,47 +51,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" -[[package]] -name = "cc" -version = "1.0.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "serde", - "time", - "winapi", -] - -[[package]] -name = "clap" -version = "2.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - [[package]] name = "common" version = "0.1.0" @@ -149,12 +84,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - [[package]] name = "fnv" version = "1.0.7" @@ -241,7 +170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ "typenum", - "version_check 0.9.3", + "version_check", ] [[package]] @@ -297,7 +226,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" dependencies = [ - "base64 0.13.0", + "base64", "bitflags", "bytes", "headers-core", @@ -422,42 +351,18 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "itertools" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" -[[package]] -name = "jsonwebtoken" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d438ea707d465c230305963b67f8357a1d56fcfad9434797d7cb1c46c2e41df" -dependencies = [ - "base64 0.9.3", - "chrono", - "ring", - "serde", - "serde_derive", - "serde_json", - "untrusted", -] - [[package]] name = "kampanja-kontrolada-servilo" version = "0.1.0" dependencies = [ - "orizentic", "tokio", + "uuid", "warp", ] @@ -473,12 +378,6 @@ version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - [[package]] name = "lock_api" version = "0.4.5" @@ -574,25 +473,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - [[package]] name = "num_cpus" version = "1.13.0" @@ -615,23 +495,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "orizentic" -version = "1.0.1" -dependencies = [ - "chrono", - "clap", - "itertools", - "jsonwebtoken", - "serde", - "serde_derive", - "serde_json", - "thiserror", - "uuid", - "version_check 0.1.5", - "yaml-rust", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -824,18 +687,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ring" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" -dependencies = [ - "cc", - "lazy_static", - "libc", - "untrusted", -] - [[package]] name = "ryu" version = "1.0.5" @@ -944,12 +795,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "syn" version = "1.0.77" @@ -975,15 +820,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.29" @@ -1137,7 +973,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" dependencies = [ - "base64 0.13.0", + "base64", "byteorder", "bytes", "http", @@ -1171,7 +1007,7 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.3", + "version_check", ] [[package]] @@ -1189,24 +1025,12 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" -[[package]] -name = "untrusted" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" - [[package]] name = "url" version = "2.2.2" @@ -1232,21 +1056,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ "getrandom 0.2.3", - "serde", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.3" @@ -1325,12 +1136,3 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] diff --git a/aŭtentigo.db b/aŭtentigo.db new file mode 100644 index 0000000..c505d4d --- /dev/null +++ b/aŭtentigo.db @@ -0,0 +1 @@ +[{"jti":"fa613049-e370-4576-b3f0-b7757c3e0cca","aud":"savanni","exp":1672379098,"iss":"savanni","iat":1640843098,"sub":"admin","perms":["admin"]}] \ No newline at end of file diff --git a/servilo/Cargo.toml b/servilo/Cargo.toml index 11810e5..94998d8 100644 --- a/servilo/Cargo.toml +++ b/servilo/Cargo.toml @@ -6,6 +6,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -orizentic = { path = "../../orizentic/" } tokio = { version = "1", features = ["full"] } +uuid = { version = "0.8.2", features = ["v4"] } warp = { version = "0.3.1" } diff --git a/servilo/src/aŭtentigo.rs b/servilo/src/aŭtentigo.rs new file mode 100644 index 0000000..4db1564 --- /dev/null +++ b/servilo/src/aŭtentigo.rs @@ -0,0 +1,100 @@ +use std::{ + collections::HashMap, + convert::Infallible, + str::FromStr, + sync::{Arc, RwLock}, +}; +use uuid::{adapter::Hyphenated, Uuid}; +use warp::{reject, reject::Reject, Filter, Rejection}; + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Ĵetono(String); + +impl From<&str> for Ĵetono { + fn from(s: &str) -> Self { + Ĵetono(s.to_owned()) + } +} + +impl FromStr for Ĵetono { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + Ok(Ĵetono(s.to_owned())) + } +} + +impl From<Ĵetono> for String { + fn from(s: Ĵetono) -> Self { + s.0.clone() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Uzantnomo(String); + +impl From<&str> for Uzantnomo { + fn from(s: &str) -> Self { + Uzantnomo(s.to_owned()) + } +} + +impl From for String { + fn from(s: Uzantnomo) -> Self { + s.0.clone() + } +} + +pub trait AŭtentigoDB: Clone + Send + Sync { + fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option; + + fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono; +} + +#[derive(Clone)] +pub struct MemAŭtentigo { + mem: HashMap<Ĵetono, Uzantnomo>, +} + +impl MemAŭtentigo { + pub fn new() -> Self { + Self { + mem: HashMap::new(), + } + } +} + +impl AŭtentigoDB for MemAŭtentigo { + fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option { + self.mem.get(&ĵetono).cloned() + } + + fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono { + let ĵetono = Ĵetono::from(format!("{}", Hyphenated::from_uuid(Uuid::new_v4())).as_str()); + self.mem.insert(ĵetono.clone(), uzantnomo); + ĵetono + } +} + +#[derive(Debug)] +pub struct AŭtentigoPostulas; + +impl Reject for AŭtentigoPostulas {} + +pub fn kun_aŭtentigo( + auth_ctx: Arc>, +) -> impl Filter + Clone { + let auth_ctx = auth_ctx.clone(); + warp::header("authentication").and_then({ + let auth_ctx = auth_ctx.clone(); + move |text| { + let auth_ctx = auth_ctx.clone(); + async move { + match auth_ctx.read().unwrap().aŭtentigu(text) { + Some(uzantnomo) => Ok(uzantnomo), + None => Err(reject::custom(AŭtentigoPostulas)), + } + } + } + }) +} diff --git a/servilo/src/main.rs b/servilo/src/main.rs index 1403614..47abd17 100644 --- a/servilo/src/main.rs +++ b/servilo/src/main.rs @@ -1,68 +1,79 @@ -use orizentic::{OrizenticCtx, Secret, Username}; +use std::convert::Infallible; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::{Arc, RwLock}; -use warp::{reject, Filter, Rejection}; +use warp::{Filter, Rejection}; -fn with_auth( - auth_ctx: Arc>, -) -> impl Filter + Clone { - let auth_ctx = auth_ctx.clone(); - warp::header("authentication").and_then({ - let auth_ctx = auth_ctx.clone(); - move |text| { - let auth_ctx = auth_ctx.clone(); - async move { - match auth_ctx.read().unwrap().decode_and_validate_text(text) { - Ok(token) => Ok(token.claims.audience), - Err(_) => Err(reject()), - } - } - } - }) +#[path = "aŭtentigo.rs"] +mod aŭtentigo; +use aŭtentigo::{kun_aŭtentigo, AŭtentigoDB, AŭtentigoPostulas, MemAŭtentigo, Uzantnomo}; + +use crate::rajtigo::{MemRajtigo, Rajtigo, Rajto}; +mod rajtigo; + +async fn traktilo_de_listigu_ludantojn( + uzantnomo: Uzantnomo, + rajtigo: Arc>, +) -> Result { + if rajtigo.read().unwrap().havas_rajton(uzantnomo, |rajtoj| { + rajtoj.fold(false, |acc, r| acc || *r == Rajto::from("admin")) + }) { + Ok(warp::reply::json(&vec!["Alice", "Betty", "Charles"])) + } else { + Err(warp::reject::not_found()) + } } -fn gm_routes( - auth_ctx: Arc>, -) -> impl Filter + Clone { - let base_route = with_auth(auth_ctx).and(warp::path("gm")); +async fn traktilu_erarojn(err: Rejection) -> Result { + let kodo; + let mesaĝo; + if let Some(_) = err.find::() { + kodo = warp::http::StatusCode::UNAUTHORIZED; + mesaĝo = "Ensalutu"; + } else { + kodo = warp::http::StatusCode::INTERNAL_SERVER_ERROR; + mesaĝo = "Netraktita mesaĝo"; + } - let character_sheet = { - let auth_ctx = auth_ctx.clone(); - with_auth(auth_ctx) - .and(warp::path!("gm" / "character" / String)) - .map(|auth: Username, name| format!("name: {} {}", String::from(auth), name)) - }; + Ok(warp::reply::with_status( + warp::reply::json(&mesaĝo.to_owned()), + kodo, + )) } #[tokio::main] pub async fn main() { - let auth_ctx = Arc::new(RwLock::new(OrizenticCtx::new( - Secret(Vec::from("abcdefg".as_bytes())), - vec![], - ))); + let auth_ctx = Arc::new(RwLock::new(MemAŭtentigo::new())); + let ĵetono = auth_ctx + .write() + .unwrap() + .kreu_ĵetono(Uzantnomo::from("Savanni")); + println!("ĵetono: {}", String::from(ĵetono)); + let rajtigo = Arc::new(RwLock::new(MemRajtigo::new())); + rajtigo.write().unwrap().aldonu_rajtoj( + Uzantnomo::from("Savanni"), + &mut (vec![Rajto::from("admin")].into_iter()), + ); - let send_item = { + let listigu_ludantojn = { let auth_ctx = auth_ctx.clone(); - with_auth(auth_ctx) - .and(warp::path!("gm" / "send_item")) - .map(|auth: Username| format!("send_item: {}", String::from(auth))) + kun_aŭtentigo(auth_ctx) + .and(warp::path!("api" / "ludantoj")) + .and_then({ + let rajtigo = rajtigo.clone(); + move |uzantnomo| { + let rajtigo = rajtigo.clone(); + traktilo_de_listigu_ludantojn(uzantnomo, rajtigo) + } + }) }; - let send_resource = warp::header("authentication") - .and(warp::path!("gm" / "send_resource")) - .map(|auth: String| format!("send_resource")); - - let pc_sheet = warp::header("authentication") - .and(warp::path!("player" / "character" / String)) - .map(|authentication: String, name: String| format!("name: {}", name)); - - let filter = character_sheet.or(send_item).or(send_resource).or(pc_sheet); + let filter = listigu_ludantojn.recover(traktilu_erarojn); let server = warp::serve(filter); server .run(SocketAddr::new( IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), - 8000, + 8001, )) .await; } diff --git a/servilo/src/rajtigo.rs b/servilo/src/rajtigo.rs new file mode 100644 index 0000000..e21f53b --- /dev/null +++ b/servilo/src/rajtigo.rs @@ -0,0 +1,74 @@ +use crate::aŭtentigo::Uzantnomo; +use std::collections::{HashMap, HashSet}; + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Rajto(String); + +impl From<&str> for Rajto { + fn from(s: &str) -> Self { + Rajto(s.to_owned()) + } +} + +impl From for String { + fn from(s: Rajto) -> Self { + s.0.clone() + } +} + +pub trait Rajtigo { + fn havas_rajton<'a, F>(&'a self, uzantnomo: Uzantnomo, provo: F) -> bool + where + F: FnOnce(&mut (dyn Iterator + 'a)) -> bool; + fn rajtoj(&self, uzantnomo: &Uzantnomo) -> Vec; + fn aldonu_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator)); + fn foriru_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator)); + fn foriru_uzanto(&mut self, uzantnomo: Uzantnomo); +} + +pub struct MemRajtigo { + rajtoj: HashMap>, +} + +impl MemRajtigo { + pub fn new() -> Self { + MemRajtigo { + rajtoj: HashMap::new(), + } + } +} + +impl Rajtigo for MemRajtigo { + fn havas_rajton<'a, F>(&'a self, uzantnomo: Uzantnomo, provo: F) -> bool + where + F: FnOnce(&mut (dyn Iterator + 'a)) -> bool, + { + match self.rajtoj.get(&uzantnomo) { + Some(rajtoj) => provo(&mut rajtoj.iter()), + None => false, + } + } + fn rajtoj(&self, uzantnomo: &Uzantnomo) -> Vec { + self.rajtoj + .get(&uzantnomo) + .map(|r| r.into_iter().cloned().collect::>()) + .unwrap_or(vec![]) + } + fn aldonu_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator)) { + let valoro = self.rajtoj.entry(uzantnomo).or_insert(HashSet::new()); + + while let Some(r) = rajtoj.next() { + valoro.insert(r); + } + } + fn foriru_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator)) { + let valoro = self.rajtoj.entry(uzantnomo).or_insert(HashSet::new()); + + while let Some(r) = rajtoj.next() { + valoro.remove(&r); + } + } + fn foriru_uzanto(&mut self, uzantnomo: Uzantnomo) { + let _ = self.rajtoj.remove(&uzantnomo); + } +} diff --git a/shell.nix b/shell.nix index 5335fe7..97fdfb8 100644 --- a/shell.nix +++ b/shell.nix @@ -10,17 +10,13 @@ in pkgs.mkShell { name = "kampanja-kontrolado"; nativeBuildInputs = [ - pkgs.gnome.webkitgtk - pkgs.glib - pkgs.gtk3 pkgs.libpng + pkgs.nodejs pkgs.openssl pkgs.pkg-config pkgs.wrapGAppsHook rust unstable.rust-analyzer - pkgs.nodejs - pkgs.hugo ]; shellHook = ''