Bläddra i källkod

Updates to schema.

Kestrel 2 år sedan
förälder
incheckning
00d4e91ed0
6 ändrade filer med 179 tillägg och 136 borttagningar
  1. 34 75
      Cargo.lock
  2. 1 1
      Cargo.toml
  3. 30 13
      src/cert.rs
  4. 31 19
      src/cli.rs
  5. 4 4
      src/main.rs
  6. 79 24
      src/schema.rs

+ 34 - 75
Cargo.lock

@@ -56,17 +56,6 @@ dependencies = [
  "opaque-debug",
 ]
 
-[[package]]
-name = "ahash"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
-dependencies = [
- "getrandom 0.2.6",
- "once_cell",
- "version_check",
-]
-
 [[package]]
 name = "anyhow"
 version = "1.0.57"
@@ -649,18 +638,6 @@ version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
 
-[[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]]
 name = "fastrand"
 version = "1.7.0"
@@ -822,18 +799,6 @@ name = "hashbrown"
 version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 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]]
 name = "heck"
@@ -993,16 +958,6 @@ version = "0.2.125"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
 
-[[package]]
-name = "libsqlite3-sys"
-version = "0.24.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14"
-dependencies = [
- "pkg-config",
- "vcpkg",
-]
-
 [[package]]
 name = "log"
 version = "0.4.17"
@@ -1028,19 +983,20 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
 name = "microrm"
-version = "0.1.0"
+version = "0.1.2"
 dependencies = [
  "base64 0.13.0",
  "microrm-macros",
- "rusqlite",
  "serde",
  "serde_bytes",
+ "serde_json",
  "sha2 0.10.2",
+ "sqlite",
 ]
 
 [[package]]
 name = "microrm-macros"
-version = "0.1.0"
+version = "0.1.2"
 dependencies = [
  "convert_case",
  "proc-macro2",
@@ -1321,21 +1277,6 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e"
 
-[[package]]
-name = "rusqlite"
-version = "0.27.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85127183a999f7db96d1a976a309eebbfb6ea3b0b400ddd8340190129de6eb7a"
-dependencies = [
- "bitflags",
- "fallible-iterator",
- "fallible-streaming-iterator",
- "hashlink",
- "libsqlite3-sys",
- "memchr",
- "smallvec",
-]
-
 [[package]]
 name = "rustc_version"
 version = "0.2.3"
@@ -1511,12 +1452,6 @@ version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
 
-[[package]]
-name = "smallvec"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
-
 [[package]]
 name = "socket2"
 version = "0.4.4"
@@ -1533,6 +1468,36 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
+[[package]]
+name = "sqlite"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fb1a534c07ec276fbbe0e55a1c00814d8563da3a2f4d9d9d4c802bd1278db6a"
+dependencies = [
+ "libc",
+ "sqlite3-sys",
+]
+
+[[package]]
+name = "sqlite3-src"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a260b07ce75a0644c6f5891f34f46db9869e731838e95293469ab17999abcfa3"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
+name = "sqlite3-sys"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04d2f028faeb14352df7934b4771806f60d61ce61be1928ec92396d7492e2e54"
+dependencies = [
+ "libc",
+ "sqlite3-src",
+]
+
 [[package]]
 name = "standback"
 version = "0.2.17"
@@ -1815,12 +1780,6 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
 [[package]]
 name = "version_check"
 version = "0.9.4"

+ 1 - 1
Cargo.toml

@@ -16,7 +16,7 @@ sha2 = { version = "0.10.2" }
 base64 = { version = "0.13.0" }
 
 # Data storage dependencies
-microrm = { path = "../microrm/microrm" }
+microrm = { path = "../microrm/microrm", version = "0.1.2" }
 
 # Public API dependencies
 tide = { version = "0.16.0" }

+ 30 - 13
src/cert.rs

@@ -1,20 +1,27 @@
-use std::collections::HashMap;
+use crate::schema;
 use ring::signature::Ed25519KeyPair;
 use sha2::Digest;
-use crate::schema;
+use std::collections::HashMap;
 
 pub struct CertStore<'a> {
-    db: &'a crate::DB,
+    db: &'a microrm::DB,
+    qi: microrm::QueryInterface<'a>,
     keys: HashMap<String, Ed25519KeyPair>,
 }
 
 impl<'a> CertStore<'a> {
-    pub fn new(db: &'a crate::DB) -> Self {
-        Self { db, keys: HashMap::new() }
+    pub fn new(db: &'a microrm::DB) -> Self {
+        Self {
+            db,
+            qi: db.query_interface(),
+            keys: HashMap::new(),
+        }
     }
 
     fn realm_id(&self, realm_name: &str) -> Option<schema::RealmID> {
-        microrm::query::get_one_by(self.db, schema::RealmColumns::Shortname, realm_name).map(|x| x.id())
+        self.qi
+            .get_one_by(schema::RealmColumns::Shortname, realm_name)
+            .map(|x| x.id())
     }
 
     pub fn generate_in(&self, realm_name: &str) -> Result<String, &'static str> {
@@ -24,7 +31,7 @@ impl<'a> CertStore<'a> {
         let realm_id = self.realm_id(realm_name).ok_or("Failed to find realm")?;
 
         if let Err(_) = sign_generated {
-            return Err("Failed to generate key")
+            return Err("Failed to generate key");
         }
         let sign_generated = sign_generated.unwrap();
 
@@ -35,30 +42,40 @@ impl<'a> CertStore<'a> {
         let mut key_id = base64::encode(key_hasher.finalize());
         key_id.truncate(16);
 
-        microrm::query::add(self.db, &schema::Key { realm: realm_id, key_id: key_id.clone(), keydata }).expect("Couldn't add key");
+        self.qi
+            .add(&schema::Key {
+                realm: realm_id,
+                key_id: key_id.clone(),
+                keydata,
+            })
+            .expect("Couldn't add key");
 
         Ok(key_id)
     }
 }
 
-pub fn inspect(db: &crate::DB, realm_name: &str) {
+pub fn inspect(db: &microrm::DB, realm_name: &str) {
+    let qi = db.query_interface();
     let cs = CertStore::new(db);
     println!("Certstore loaded.");
-    let realm = microrm::query::get_one_by(db, schema::RealmColumns::Shortname, realm_name);
+    let realm = qi.get_one_by(schema::RealmColumns::Shortname, realm_name);
     if realm.is_none() {
         println!("No such realm {}", realm_name);
-        return
+        return;
     }
     let realm = realm.unwrap();
 
     println!("Retrieving keys for {} realm...", realm_name);
-    let keys = microrm::query::get_all_by(db, schema::KeyColumns::Realm, realm.id()).expect("Can get keys");
+    let keys = qi
+        .get_all_by(schema::KeyColumns::Realm, realm.id())
+        .expect("Can get keys");
     for key in keys {
         println!("[{:20}]", key.key_id);
     }
 }
 
-pub fn generate(db: &crate::DB, realm_name: &str) {
+pub fn generate(db: &microrm::DB, realm_name: &str) {
+    let qi = db.query_interface();
     let cs = CertStore::new(db);
     if let Err(e) = cs.generate_in(realm_name) {
         println!("Failed to generate key: {}", e);

+ 31 - 19
src/cli.rs

@@ -1,4 +1,4 @@
-use clap::{Parser,Subcommand};
+use clap::{Parser, Subcommand};
 
 #[derive(Debug, Parser)]
 #[clap(author, version, about, long_about = None)]
@@ -13,54 +13,68 @@ struct RootArgs {
     command: Command,
 }
 
-#[derive(Debug,Subcommand)]
+#[derive(Debug, Subcommand)]
 enum Command {
     Init,
     Cert(CertArgs),
-    Server(ServerArgs)
+    Server(ServerArgs),
 }
 
 impl RootArgs {
     async fn run(&self) {
-
         if let Command::Init = self.command {
             return self.init().await;
         }
 
-        let storage = crate::DB::new(crate::schema::schema(), &self.db, false);
+        let storage = microrm::DB::new(
+            crate::schema::schema(),
+            &self.db,
+            microrm::CreateMode::MustExist,
+        );
 
         if let Err(e) = storage {
             println!("Error occured while loading database: {}", e);
-            return
+            return;
         }
         let storage = storage.unwrap();
 
         match &self.command {
             Command::Init => unreachable!(),
             Command::Cert(v) => v.run(&self, &storage).await,
-            Command::Server(v) => v.run(&self, &storage).await,
+            Command::Server(v) => v.run(&self, storage).await,
         }
     }
 
     async fn init(&self) {
         // first check to see if the database is already vaguely set up
-        let maybedb = crate::DB::new(crate::schema::schema(), &self.db, false);
+        let maybedb = microrm::DB::new(
+            crate::schema::schema(),
+            &self.db,
+            microrm::CreateMode::MustExist,
+        );
 
         if maybedb.is_ok() {
             println!("Database already initialized, not overwriting!");
-            return
+            return;
         }
 
         println!("Initializing!");
 
-        let db = crate::DB::new(crate::schema::schema(), &self.db, true).expect("Unable to initialize database!");
+        let db = microrm::DB::new(
+            crate::schema::schema(),
+            &self.db,
+            microrm::CreateMode::AllowNewDatabase,
+        )
+        .expect("Unable to initialize database!");
 
         // create primary realm
-        microrm::query::add(&db, &crate::schema::Realm { shortname: "primary".to_string() });
+        db.query_interface().add(&crate::schema::Realm {
+            shortname: "primary".to_string(),
+        });
     }
 }
 
-#[derive(Debug,Subcommand)]
+#[derive(Debug, Subcommand)]
 enum CertCommand {
     Inspect,
     Generate,
@@ -69,11 +83,11 @@ enum CertCommand {
 #[derive(Debug, Parser)]
 struct CertArgs {
     #[clap(subcommand)]
-    command: CertCommand
+    command: CertCommand,
 }
 
 impl CertArgs {
-    async fn run(&self, root: &RootArgs, si: &crate::DB) {
+    async fn run(&self, root: &RootArgs, si: &microrm::DB) {
         match &self.command {
             CertCommand::Inspect => {
                 crate::cert::inspect(si, &root.realm);
@@ -86,13 +100,11 @@ impl CertArgs {
 }
 
 #[derive(Debug, Parser)]
-struct ServerArgs {
-    
-}
+struct ServerArgs {}
 
 impl ServerArgs {
-    async fn run(&self, root: &RootArgs, _si: &crate::DB) {
-        
+    async fn run(&self, root: &RootArgs, db: microrm::DB) {
+        crate::server::run_server(db).await;
     }
 }
 

+ 4 - 4
src/main.rs

@@ -1,8 +1,8 @@
-pub use microrm::DB;
-
-mod schema;
-mod cli;
 mod cert;
+mod cli;
+mod schema;
+mod server;
+mod login;
 
 fn main() {
     cli::invoked();

+ 79 - 24
src/schema.rs

@@ -1,66 +1,121 @@
-use serde::{Serialize,Deserialize};
-pub use microrm::{Entity, model::SchemaModel};
+pub use microrm::{model::SchemaModel, Entity, Modelable};
+use serde::{Deserialize, Serialize};
 
-#[derive(Entity,Serialize,Deserialize)]
+#[derive(Entity, Serialize, Deserialize)]
+pub struct Session {
+    pub key: String,
+    // TODO: add expiry here
+}
+
+microrm::make_index!(!SessionKeyIndex, SessionColumns::Key);
+
+#[derive(Entity, Serialize, Deserialize)]
+pub struct SessionAuthentication {
+    #[microrm_foreign]
+    pub session: SessionID,
+    #[microrm_foreign]
+    pub user: UserID,
+
+    challenges_left: Vec<AuthChallengeType>
+}
+
+// **** oauth types ****
+#[derive(Entity, Serialize, Deserialize)]
 pub struct Realm {
-    pub shortname: String
+    pub shortname: String,
 }
 
-#[derive(Entity,Serialize,Deserialize)]
+#[derive(Entity, Serialize, Deserialize)]
 pub struct Key {
+    #[microrm_foreign]
     pub realm: RealmID,
     pub key_id: String,
     #[serde(with = "serde_bytes")]
-    pub keydata: Vec<u8>
+    pub keydata: Vec<u8>,
 }
 
-#[derive(Entity,Serialize,Deserialize)]
+#[derive(Entity, Serialize, Deserialize)]
 pub struct User {
+    #[microrm_foreign]
     pub realm: RealmID,
     pub username: String,
 }
 
-#[derive(Entity,Serialize,Deserialize)]
-pub struct Password {
+#[derive(Modelable, Serialize, Deserialize)]
+pub enum AuthChallengeType {
+    Password,
+    TOTP,
+    Grid,
+    WebAuthn
+}
+
+#[derive(Entity, Serialize, Deserialize)]
+pub struct AuthChallenge {
+    #[microrm_foreign]
     pub user: UserID,
-    pub salt: String,
-    pub hash: String
+    pub challenge_type: AuthChallengeType,
+    pub public: String,
+    pub secret: String
 }
 
-#[derive(Entity,Serialize,Deserialize)]
+#[derive(Entity, Serialize, Deserialize)]
 pub struct Group {
+    #[microrm_foreign]
     pub realm: RealmID,
     pub shortname: String,
 }
 
-#[derive(Entity,Serialize,Deserialize)]
+#[derive(Entity, Serialize, Deserialize)]
 pub struct Client {
+    #[microrm_foreign]
     pub realm: RealmID,
     pub shortname: String,
     pub secret: String,
 }
 
-#[derive(Entity,Serialize,Deserialize)]
+microrm::make_index!(
+    !ClientNameIndex,
+    ClientColumns::Realm,
+    ClientColumns::Shortname
+);
+
+#[derive(Entity, Serialize, Deserialize)]
+pub struct ClientRedirect {
+    #[microrm_foreign]
+    pub client: ClientID,
+    pub redirect: String,
+}
+
+#[derive(Entity, Serialize, Deserialize)]
 pub struct Scope {
+    #[microrm_foreign]
     pub realm: RealmID,
     pub shortname: String,
 }
 
-#[derive(Entity,Serialize,Deserialize)]
+#[derive(Entity, Serialize, Deserialize)]
 pub struct Role {
+    #[microrm_foreign]
     pub realm: RealmID,
+    #[microrm_foreign]
     pub group: GroupID,
     pub shortname: String,
 }
 
 pub fn schema() -> SchemaModel {
-    SchemaModel::new()
-        .add::<Realm>()
-        .add::<Key>()
-        .add::<User>()
-        .add::<Password>()
-        .add::<Group>()
-        .add::<Client>()
-        .add::<Scope>()
-        .add::<Role>()
+    microrm::model::SchemaModel::new()
+        .entity::<Session>()
+        .index::<SessionKeyIndex>()
+        .entity::<SessionAuthentication>()
+        // oauth types
+        .entity::<Realm>()
+        .entity::<Key>()
+        .entity::<User>()
+        .entity::<AuthChallenge>()
+        .entity::<Group>()
+        .entity::<Client>()
+        .index::<ClientNameIndex>()
+        .entity::<ClientRedirect>()
+        .entity::<Scope>()
+        .entity::<Role>()
 }