Aldonu datumbazon kaj sesia-administradon
This commit is contained in:
parent
e48ed1f2dd
commit
823a701a2f
|
@ -1,2 +1,3 @@
|
||||||
node_modules
|
node_modules
|
||||||
target
|
target
|
||||||
|
*.db
|
||||||
|
|
|
@ -2,6 +2,23 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.2.3",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.52"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -84,6 +101,18 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-iterator"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-streaming-iterator"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -219,6 +248,18 @@ name = "hashbrown"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashlink"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "headers"
|
name = "headers"
|
||||||
|
@ -361,6 +402,10 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||||
name = "kampanja-kontrolada-servilo"
|
name = "kampanja-kontrolada-servilo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"rusqlite",
|
||||||
|
"tempfile",
|
||||||
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
"warp",
|
"warp",
|
||||||
|
@ -378,6 +423,16 @@ version = "0.2.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libsqlite3-sys"
|
||||||
|
version = "0.23.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58"
|
||||||
|
dependencies = [
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
@ -558,6 +613,12 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
|
@ -687,6 +748,21 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusqlite"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ba4d3462c8b2e4d7f4fcfcf2b296dc6b65404fbbc7b63daa37fd485c149daf7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"fallible-iterator",
|
||||||
|
"fallible-streaming-iterator",
|
||||||
|
"hashlink",
|
||||||
|
"libsqlite3-sys",
|
||||||
|
"memchr",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
@ -1058,6 +1134,12 @@ dependencies = [
|
||||||
"getrandom 0.2.3",
|
"getrandom 0.2.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
|
|
|
@ -6,6 +6,12 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
anyhow = { version = "1" }
|
||||||
uuid = { version = "0.8.2", features = ["v4"] }
|
rusqlite = { version = "0.26" }
|
||||||
warp = { version = "0.3.1" }
|
thiserror = { version = "1" }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
warp = { version = "0.3" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempfile = { version = "3" }
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::datumbazo::Datumbazo;
|
||||||
|
use rusqlite::OptionalExtension;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
|
@ -30,6 +32,21 @@ impl From<Ĵetono> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct UzantIdentigilo(String);
|
||||||
|
|
||||||
|
impl From<&str> for UzantIdentigilo {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
UzantIdentigilo(s.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UzantIdentigilo> for String {
|
||||||
|
fn from(s: UzantIdentigilo) -> Self {
|
||||||
|
s.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Uzantnomo(String);
|
pub struct Uzantnomo(String);
|
||||||
|
|
||||||
|
@ -45,33 +62,95 @@ impl From<Uzantnomo> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AŭtentigoDB: Clone + Send + Sync {
|
pub trait AŭtentigoDB: Send {
|
||||||
fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option<Uzantnomo>;
|
fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option<(UzantIdentigilo, Uzantnomo)>;
|
||||||
|
|
||||||
fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono;
|
fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct MemAŭtentigo {
|
pub struct MemAŭtentigo {
|
||||||
mem: HashMap<Ĵetono, Uzantnomo>,
|
sesioj: HashMap<Ĵetono, UzantIdentigilo>,
|
||||||
|
uzantoj: HashMap<UzantIdentigilo, Uzantnomo>,
|
||||||
|
inversa_uzantoj: HashMap<Uzantnomo, UzantIdentigilo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemAŭtentigo {
|
impl MemAŭtentigo {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
mem: HashMap::new(),
|
sesioj: HashMap::new(),
|
||||||
|
uzantoj: HashMap::new(),
|
||||||
|
inversa_uzantoj: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AŭtentigoDB for MemAŭtentigo {
|
impl AŭtentigoDB for MemAŭtentigo {
|
||||||
fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option<Uzantnomo> {
|
fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option<(UzantIdentigilo, Uzantnomo)> {
|
||||||
self.mem.get(&ĵetono).cloned()
|
let identigilo = self.sesioj.get(&ĵetono).cloned()?;
|
||||||
|
let uzantnomo = self.uzantoj.get(&identigilo).cloned()?;
|
||||||
|
Some((identigilo, uzantnomo))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono {
|
||||||
|
let identigilo = self.inversa_uzantoj.get(&uzantnomo).cloned().unwrap();
|
||||||
|
let ĵetono = Ĵetono::from(format!("{}", Hyphenated::from_uuid(Uuid::new_v4())).as_str());
|
||||||
|
self.sesioj.insert(ĵetono.clone(), identigilo);
|
||||||
|
ĵetono
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DBAŭtentigo {
|
||||||
|
pool: Datumbazo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DBAŭtentigo {
|
||||||
|
pub fn kreu(pool: Datumbazo) -> Self {
|
||||||
|
DBAŭtentigo { pool }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AŭtentigoDB for DBAŭtentigo {
|
||||||
|
fn aŭtentigu(&self, ĵetono: Ĵetono) -> Option<(UzantIdentigilo, Uzantnomo)> {
|
||||||
|
let konekto = self.pool.konektu().unwrap();
|
||||||
|
konekto
|
||||||
|
.query_row(
|
||||||
|
"SELECT uzantoj.id, uzantoj.nomo FROM sesioj INNER JOIN uzantoj on sesioj.uzanto == uzantoj.id WHERE sesioj.id = ?",
|
||||||
|
[String::from(ĵetono)],
|
||||||
|
|row| {
|
||||||
|
let identigilo = row.get("id")
|
||||||
|
.map(|s: String| UzantIdentigilo::from(s.as_str())).unwrap();
|
||||||
|
let nomo = row.get("nomo")
|
||||||
|
.map(|s: String| Uzantnomo::from(s.as_str())).unwrap();
|
||||||
|
Ok((identigilo, nomo))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.optional()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono {
|
fn kreu_ĵetono(&mut self, uzantnomo: Uzantnomo) -> Ĵetono {
|
||||||
let ĵetono = Ĵetono::from(format!("{}", Hyphenated::from_uuid(Uuid::new_v4())).as_str());
|
let ĵetono = Ĵetono::from(format!("{}", Hyphenated::from_uuid(Uuid::new_v4())).as_str());
|
||||||
self.mem.insert(ĵetono.clone(), uzantnomo);
|
let mut konekto = self.pool.konektu().unwrap();
|
||||||
|
let tr = konekto.transaction().unwrap();
|
||||||
|
let uzanta_id: Option<String> = tr
|
||||||
|
.query_row(
|
||||||
|
"SELECT id FROM uzantoj WHERE nomo = ?",
|
||||||
|
[String::from(uzantnomo.clone())],
|
||||||
|
|row| row.get("id"),
|
||||||
|
)
|
||||||
|
.optional()
|
||||||
|
.unwrap();
|
||||||
|
match uzanta_id {
|
||||||
|
None => panic!("uzanto ne ekzistas"),
|
||||||
|
Some(id) => {
|
||||||
|
tr.execute(
|
||||||
|
"INSERT INTO sesioj VALUES(?, ?)",
|
||||||
|
[String::from(ĵetono.clone()), id],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tr.commit().unwrap();
|
||||||
ĵetono
|
ĵetono
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,8 +161,8 @@ pub struct AŭtentigoPostulas;
|
||||||
impl Reject for AŭtentigoPostulas {}
|
impl Reject for AŭtentigoPostulas {}
|
||||||
|
|
||||||
pub fn kun_aŭtentigo(
|
pub fn kun_aŭtentigo(
|
||||||
auth_ctx: Arc<RwLock<impl AŭtentigoDB>>,
|
auth_ctx: Arc<RwLock<impl AŭtentigoDB + Sync>>,
|
||||||
) -> impl Filter<Extract = (Uzantnomo,), Error = Rejection> + Clone {
|
) -> impl Filter<Extract = ((UzantIdentigilo, Uzantnomo),), Error = Rejection> + Clone {
|
||||||
let auth_ctx = auth_ctx.clone();
|
let auth_ctx = auth_ctx.clone();
|
||||||
warp::header("authentication").and_then({
|
warp::header("authentication").and_then({
|
||||||
let auth_ctx = auth_ctx.clone();
|
let auth_ctx = auth_ctx.clone();
|
||||||
|
@ -91,7 +170,7 @@ pub fn kun_aŭtentigo(
|
||||||
let auth_ctx = auth_ctx.clone();
|
let auth_ctx = auth_ctx.clone();
|
||||||
async move {
|
async move {
|
||||||
match auth_ctx.read().unwrap().aŭtentigu(text) {
|
match auth_ctx.read().unwrap().aŭtentigu(text) {
|
||||||
Some(uzantnomo) => Ok(uzantnomo),
|
Some(salutiloj) => Ok(salutiloj),
|
||||||
None => Err(reject::custom(AŭtentigoPostulas)),
|
None => Err(reject::custom(AŭtentigoPostulas)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
use rusqlite::{params, Connection};
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ManagedConnection<'a> {
|
||||||
|
pool: &'a Datumbazo,
|
||||||
|
konekto: Option<Connection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Datumbazo {
|
||||||
|
dosierindiko: PathBuf,
|
||||||
|
pool: Arc<Mutex<Vec<Connection>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Datumbazo {
|
||||||
|
pub fn kreu(dosierindiko: PathBuf) -> Result<Datumbazo, anyhow::Error> {
|
||||||
|
let mut konekto = Connection::open(dosierindiko.clone())?;
|
||||||
|
|
||||||
|
let tx = konekto.transaction()?;
|
||||||
|
let versio: i32 = tx.pragma_query_value(None, "user_version", |r| r.get(0))?;
|
||||||
|
println!("versio: {}", versio);
|
||||||
|
if versio == 0 {
|
||||||
|
tx.execute_batch(
|
||||||
|
"CREATE TABLE uzantoj (id string primary key, nomo text);
|
||||||
|
CREATE TABLE rajtoj (uzanto string, rajto string, foreign key(uzanto) references uzanto(id));
|
||||||
|
CREATE TABLE sesioj (id string primary key not null, uzanto string, foreign key(uzanto) references uzantoj(id));
|
||||||
|
PRAGMA user_version = 1;",
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
let versio: i32 = tx.pragma_query_value(None, "user_version", |r| r.get(0))?;
|
||||||
|
println!("versio: {}", versio);
|
||||||
|
|
||||||
|
tx.commit()?;
|
||||||
|
|
||||||
|
Ok(Datumbazo {
|
||||||
|
dosierindiko,
|
||||||
|
pool: Arc::new(Mutex::new(vec![konekto])),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn konektu<'a>(&'a self) -> Result<ManagedConnection<'a>, anyhow::Error> {
|
||||||
|
let mut pool = self.pool.lock().unwrap();
|
||||||
|
match pool.pop() {
|
||||||
|
Some(konekto) => Ok(ManagedConnection {
|
||||||
|
pool: &self,
|
||||||
|
konekto: Some(konekto),
|
||||||
|
}),
|
||||||
|
None => {
|
||||||
|
let konekto = Connection::open(self.dosierindiko.clone())?;
|
||||||
|
Ok(ManagedConnection {
|
||||||
|
pool: &self,
|
||||||
|
konekto: Some(konekto),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn revenu(&self, konekto: Connection) {
|
||||||
|
let mut pool = self.pool.lock().unwrap();
|
||||||
|
pool.push(konekto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ManagedConnection<'_> {
|
||||||
|
type Target = Connection;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Connection {
|
||||||
|
self.konekto.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for ManagedConnection<'_> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Connection {
|
||||||
|
self.konekto.as_mut().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ManagedConnection<'_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.pool.revenu(self.konekto.take().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn povas_krei_uzanton() {
|
||||||
|
let vojo = NamedTempFile::new().unwrap().into_temp_path();
|
||||||
|
let datumbazo = Datumbazo::kreu(vojo.to_path_buf()).unwrap();
|
||||||
|
let mut konekto = datumbazo.konektu().unwrap();
|
||||||
|
let tr = konekto.transaction().unwrap();
|
||||||
|
tr.execute(
|
||||||
|
"INSERT INTO uzantoj VALUES(?, ?)",
|
||||||
|
params![1, String::from("mia-uzantnomo")],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
tr.commit().unwrap();
|
||||||
|
|
||||||
|
let konekto = datumbazo.konektu().unwrap();
|
||||||
|
let id: Option<u32> = konekto
|
||||||
|
.query_row(
|
||||||
|
"SELECT id FROM uzantoj WHERE nomo = ?",
|
||||||
|
[String::from("mia-uzantnomo")],
|
||||||
|
|row| row.get("id"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(id, Some(1));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,27 @@
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use warp::{Filter, Rejection};
|
use warp::{Filter, Rejection};
|
||||||
|
|
||||||
#[path = "aŭtentigo.rs"]
|
#[path = "aŭtentigo.rs"]
|
||||||
mod aŭtentigo;
|
mod aŭtentigo;
|
||||||
use aŭtentigo::{kun_aŭtentigo, AŭtentigoDB, AŭtentigoPostulas, MemAŭtentigo, Uzantnomo};
|
use aŭtentigo::{kun_aŭtentigo, AŭtentigoDB, AŭtentigoPostulas, Uzantnomo};
|
||||||
|
|
||||||
|
mod datumbazo;
|
||||||
|
use datumbazo::Datumbazo;
|
||||||
|
|
||||||
use crate::rajtigo::{MemRajtigo, Rajtigo, Rajto};
|
|
||||||
mod rajtigo;
|
mod rajtigo;
|
||||||
|
use rajtigo::{DBRajtigo, Rajtigo, Rajto};
|
||||||
|
|
||||||
|
use crate::aŭtentigo::{DBAŭtentigo, UzantIdentigilo};
|
||||||
|
|
||||||
async fn traktilo_de_listigu_ludantojn(
|
async fn traktilo_de_listigu_ludantojn(
|
||||||
uzantnomo: Uzantnomo,
|
identigilo: UzantIdentigilo,
|
||||||
rajtigo: Arc<RwLock<impl Rajtigo>>,
|
rajtigo: Arc<RwLock<impl Rajtigo>>,
|
||||||
) -> Result<impl warp::Reply, Rejection> {
|
) -> Result<impl warp::Reply, Rejection> {
|
||||||
if rajtigo.read().unwrap().havas_rajton(uzantnomo, |rajtoj| {
|
if rajtigo.read().unwrap().havas_rajton(identigilo, |rajtoj| {
|
||||||
rajtoj.fold(false, |acc, r| acc || *r == Rajto::from("admin"))
|
rajtoj.fold(false, |acc, r| acc || r == Rajto::from("admin"))
|
||||||
}) {
|
}) {
|
||||||
Ok(warp::reply::json(&vec!["Alice", "Betty", "Charles"]))
|
Ok(warp::reply::json(&vec!["Alice", "Betty", "Charles"]))
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,17 +48,15 @@ async fn traktilu_erarojn(err: Rejection) -> Result<impl warp::Reply, Infallible
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn main() {
|
pub async fn main() {
|
||||||
let auth_ctx = Arc::new(RwLock::new(MemAŭtentigo::new()));
|
let db = Datumbazo::kreu(PathBuf::from("../servilo.db")).unwrap();
|
||||||
|
|
||||||
|
let auth_ctx = Arc::new(RwLock::new(DBAŭtentigo::kreu(db.clone())));
|
||||||
let ĵetono = auth_ctx
|
let ĵetono = auth_ctx
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.kreu_ĵetono(Uzantnomo::from("Savanni"));
|
.kreu_ĵetono(Uzantnomo::from("savanni"));
|
||||||
println!("ĵetono: {}", String::from(ĵetono));
|
println!("ĵetono: {}", String::from(ĵetono));
|
||||||
let rajtigo = Arc::new(RwLock::new(MemRajtigo::new()));
|
let rajtigo = Arc::new(RwLock::new(DBRajtigo::kreu(db)));
|
||||||
rajtigo.write().unwrap().aldonu_rajtoj(
|
|
||||||
Uzantnomo::from("Savanni"),
|
|
||||||
&mut (vec![Rajto::from("admin")].into_iter()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let listigu_ludantojn = {
|
let listigu_ludantojn = {
|
||||||
let auth_ctx = auth_ctx.clone();
|
let auth_ctx = auth_ctx.clone();
|
||||||
|
@ -60,9 +64,14 @@ pub async fn main() {
|
||||||
.and(warp::path!("api" / "ludantoj"))
|
.and(warp::path!("api" / "ludantoj"))
|
||||||
.and_then({
|
.and_then({
|
||||||
let rajtigo = rajtigo.clone();
|
let rajtigo = rajtigo.clone();
|
||||||
move |uzantnomo| {
|
move |(identigilo, uzantnomo): (UzantIdentigilo, Uzantnomo)| {
|
||||||
|
println!(
|
||||||
|
"[{}] {}",
|
||||||
|
String::from(identigilo.clone()),
|
||||||
|
String::from(uzantnomo.clone())
|
||||||
|
);
|
||||||
let rajtigo = rajtigo.clone();
|
let rajtigo = rajtigo.clone();
|
||||||
traktilo_de_listigu_ludantojn(uzantnomo, rajtigo)
|
traktilo_de_listigu_ludantojn(identigilo, rajtigo)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::aŭtentigo::Uzantnomo;
|
use crate::{aŭtentigo::UzantIdentigilo, datumbazo::Datumbazo};
|
||||||
|
use rusqlite::OptionalExtension;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -17,58 +18,124 @@ impl From<Rajto> for String {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Rajtigo {
|
pub trait Rajtigo {
|
||||||
fn havas_rajton<'a, F>(&'a self, uzantnomo: Uzantnomo, provo: F) -> bool
|
fn havas_rajton<'a, F>(&'a self, identigilo: UzantIdentigilo, provo: F) -> bool
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut (dyn Iterator<Item = &'a Rajto> + 'a)) -> bool;
|
F: FnOnce(&mut (dyn Iterator<Item = Rajto>)) -> bool;
|
||||||
fn rajtoj(&self, uzantnomo: &Uzantnomo) -> Vec<Rajto>;
|
fn rajtoj(&self, identigilo: &UzantIdentigilo) -> Vec<Rajto>;
|
||||||
fn aldonu_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator<Item = Rajto>));
|
fn aldonu_rajtoj(
|
||||||
fn foriru_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator<Item = Rajto>));
|
&mut self,
|
||||||
fn foriru_uzanto(&mut self, uzantnomo: Uzantnomo);
|
identigilo: UzantIdentigilo,
|
||||||
|
rajtoj: &mut (dyn Iterator<Item = Rajto>),
|
||||||
|
);
|
||||||
|
fn foriru_rajtoj(
|
||||||
|
&mut self,
|
||||||
|
identigilo: UzantIdentigilo,
|
||||||
|
rajtoj: &mut (dyn Iterator<Item = Rajto>),
|
||||||
|
);
|
||||||
|
fn foriru_uzanto(&mut self, identigilo: UzantIdentigilo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
pub struct MemRajtigo {
|
pub struct MemRajtigo {
|
||||||
rajtoj: HashMap<Uzantnomo, HashSet<Rajto>>,
|
rajtoj: HashMap<UzantIdentigilo, HashSet<Rajto>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemRajtigo {
|
impl MemRajtigo {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
MemRajtigo {
|
MemRajtigo {
|
||||||
rajtoj: HashMap::new(),
|
rajtoj: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rajtigo for MemRajtigo {
|
impl Rajtigo for MemRajtigo {
|
||||||
fn havas_rajton<'a, F>(&'a self, uzantnomo: Uzantnomo, provo: F) -> bool
|
fn havas_rajton<'a, F>(&'a self, identigilo: UzantIdentigilo, provo: F) -> bool
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut (dyn Iterator<Item = &'a Rajto> + 'a)) -> bool,
|
F: FnOnce(&mut (dyn Iterator<Item = Rajto> + 'a)) -> bool,
|
||||||
{
|
{
|
||||||
match self.rajtoj.get(&uzantnomo) {
|
match self.rajtoj.get(&identigilo) {
|
||||||
Some(rajtoj) => provo(&mut rajtoj.iter()),
|
Some(rajtoj) => provo(&mut rajtoj.clone().into_iter()),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn rajtoj(&self, uzantnomo: &Uzantnomo) -> Vec<Rajto> {
|
fn rajtoj(&self, identigilo: &UzantIdentigilo) -> Vec<Rajto> {
|
||||||
self.rajtoj
|
self.rajtoj
|
||||||
.get(&uzantnomo)
|
.get(&identigilo)
|
||||||
.map(|r| r.into_iter().cloned().collect::<Vec<Rajto>>())
|
.map(|r| r.into_iter().cloned().collect::<Vec<Rajto>>())
|
||||||
.unwrap_or(vec![])
|
.unwrap_or(vec![])
|
||||||
}
|
}
|
||||||
fn aldonu_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator<Item = Rajto>)) {
|
fn aldonu_rajtoj(
|
||||||
let valoro = self.rajtoj.entry(uzantnomo).or_insert(HashSet::new());
|
&mut self,
|
||||||
|
identigilo: UzantIdentigilo,
|
||||||
|
rajtoj: &mut (dyn Iterator<Item = Rajto>),
|
||||||
|
) {
|
||||||
|
let valoro = self.rajtoj.entry(identigilo).or_insert(HashSet::new());
|
||||||
|
|
||||||
while let Some(r) = rajtoj.next() {
|
while let Some(r) = rajtoj.next() {
|
||||||
valoro.insert(r);
|
valoro.insert(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn foriru_rajtoj(&mut self, uzantnomo: Uzantnomo, rajtoj: &mut (dyn Iterator<Item = Rajto>)) {
|
fn foriru_rajtoj(
|
||||||
let valoro = self.rajtoj.entry(uzantnomo).or_insert(HashSet::new());
|
&mut self,
|
||||||
|
identigilo: UzantIdentigilo,
|
||||||
|
rajtoj: &mut (dyn Iterator<Item = Rajto>),
|
||||||
|
) {
|
||||||
|
let valoro = self.rajtoj.entry(identigilo).or_insert(HashSet::new());
|
||||||
|
|
||||||
while let Some(r) = rajtoj.next() {
|
while let Some(r) = rajtoj.next() {
|
||||||
valoro.remove(&r);
|
valoro.remove(&r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn foriru_uzanto(&mut self, uzantnomo: Uzantnomo) {
|
fn foriru_uzanto(&mut self, identigilo: UzantIdentigilo) {
|
||||||
let _ = self.rajtoj.remove(&uzantnomo);
|
let _ = self.rajtoj.remove(&identigilo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub struct DBRajtigo {
|
||||||
|
pool: Datumbazo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DBRajtigo {
|
||||||
|
pub fn kreu(pool: Datumbazo) -> Self {
|
||||||
|
DBRajtigo { pool }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rajtigo for DBRajtigo {
|
||||||
|
fn havas_rajton<'a, F>(&'a self, identigilo: UzantIdentigilo, provo: F) -> bool
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut (dyn Iterator<Item = Rajto>)) -> bool,
|
||||||
|
{
|
||||||
|
let konekto = self.pool.konektu().unwrap();
|
||||||
|
let mut stmt = konekto
|
||||||
|
.prepare("SELECT rajto FROM rajtoj WHERE uzanto = ?")
|
||||||
|
.unwrap();
|
||||||
|
let mut rajtoj = stmt
|
||||||
|
.query_map([String::from(identigilo)], |row| {
|
||||||
|
row.get("rajto").map(|s: String| Rajto::from(s.as_ref()))
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.map(|r| r.unwrap());
|
||||||
|
provo(&mut rajtoj)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rajtoj(&self, identigilo: &UzantIdentigilo) -> Vec<Rajto> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn aldonu_rajtoj(
|
||||||
|
&mut self,
|
||||||
|
identigilo: UzantIdentigilo,
|
||||||
|
rajtoj: &mut (dyn Iterator<Item = Rajto>),
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foriru_rajtoj(
|
||||||
|
&mut self,
|
||||||
|
identigilo: UzantIdentigilo,
|
||||||
|
rajtoj: &mut (dyn Iterator<Item = Rajto>),
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
fn foriru_uzanto(&mut self, identigilo: UzantIdentigilo) {}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue