Bläddra i källkod

Moved more CLI code to use new microrm clap autogen.

Kestrel 11 månader sedan
förälder
incheckning
ffa0e426c8
11 ändrade filer med 333 tillägg och 217 borttagningar
  1. 81 45
      Cargo.lock
  2. 2 1
      Cargo.toml
  3. 42 152
      src/cli.rs
  4. 62 0
      src/cli/client.rs
  5. 59 0
      src/cli/group.rs
  6. 2 3
      src/cli/role.rs
  7. 58 0
      src/cli/scope.rs
  8. 14 5
      src/cli/user.rs
  9. 9 0
      src/client_management.rs
  10. 3 1
      src/key.rs
  11. 1 10
      src/main.rs

+ 81 - 45
Cargo.lock

@@ -56,6 +56,15 @@ dependencies = [
  "opaque-debug",
 ]
 
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "android-tzdata"
 version = "0.1.1"
@@ -376,17 +385,6 @@ version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
 
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi 0.1.19",
- "libc",
- "winapi",
-]
-
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -769,6 +767,19 @@ version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
 
+[[package]]
+name = "env_logger"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
+dependencies = [
+ "humantime",
+ "is-terminal",
+ "log",
+ "regex",
+ "termcolor",
+]
+
 [[package]]
 name = "equivalent"
 version = "1.0.1"
@@ -999,15 +1010,6 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "hermit-abi"
 version = "0.3.3"
@@ -1093,6 +1095,12 @@ version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
 
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
 [[package]]
 name = "iana-time-zone"
 version = "0.1.58"
@@ -1157,11 +1165,22 @@ version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 dependencies = [
- "hermit-abi 0.3.3",
+ "hermit-abi",
  "libc",
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "is-terminal"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "itertools"
 version = "0.12.1"
@@ -1492,6 +1511,16 @@ version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
+[[package]]
+name = "pretty_env_logger"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
+dependencies = [
+ "env_logger",
+ "log",
+]
+
 [[package]]
 name = "proc-macro-hack"
 version = "0.5.20+deprecated"
@@ -1615,6 +1644,35 @@ dependencies = [
  "bitflags 1.3.2",
 ]
 
+[[package]]
+name = "regex"
+version = "1.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+
 [[package]]
 name = "ring"
 version = "0.16.20"
@@ -1947,19 +2005,6 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "stderrlog"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69a26bbf6de627d389164afa9783739b56746c6c72c4ed16539f4ff54170327b"
-dependencies = [
- "atty",
- "chrono",
- "log",
- "termcolor",
- "thread_local",
-]
-
 [[package]]
 name = "stdweb"
 version = "0.4.20"
@@ -2140,16 +2185,6 @@ dependencies = [
  "syn 2.0.51",
 ]
 
-[[package]]
-name = "thread_local"
-version = "1.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
-dependencies = [
- "cfg-if 1.0.0",
- "once_cell",
-]
-
 [[package]]
 name = "tide"
 version = "0.16.0"
@@ -2328,9 +2363,11 @@ dependencies = [
  "clap",
  "handlebars",
  "hmac 0.12.1",
+ "itertools",
  "lazy_static",
  "log",
  "microrm",
+ "pretty_env_logger",
  "qr2term",
  "ring",
  "rpassword",
@@ -2340,7 +2377,6 @@ dependencies = [
  "sha1 0.10.6",
  "sha2 0.10.8",
  "smol",
- "stderrlog",
  "tide",
  "time 0.3.34",
  "toml",

+ 2 - 1
Cargo.toml

@@ -12,6 +12,7 @@ log = "0.4"
 serde = { version =  "1.0", features = ["derive"] }
 lazy_static = "1.4.0"
 time = { version = "0.3", features = ["std", "formatting"] }
+itertools = "0.12"
 
 # crypto
 ring = { version = "0.16.20", features = ["std"] }
@@ -36,5 +37,5 @@ serde_json = "1.0"
 # CLI dependencies
 clap = { version = "4.5", features = ["derive", "env", "string"] }
 rpassword = "6.0"
-stderrlog = "0.5"
+pretty_env_logger = "0.5"
 qr2term = "0.3.1"

+ 42 - 152
src/cli.rs

@@ -8,8 +8,11 @@ use clap::{Parser, Subcommand};
 use microrm::{prelude::*, schema::Stored};
 use microrm::cli::Autogenerate;
 
+mod client;
+mod group;
 mod role;
 mod user;
+mod scope;
 
 impl microrm::cli::CLIError for UIDCError {
     fn no_such_entity(ename: &'static str, keys: String) -> Self {
@@ -37,23 +40,41 @@ enum Command {
     /// database initialization
     Init,
     /// OAuth2 client management
-    Client(ClientArgs),
+    Client {
+        #[clap(subcommand)]
+        cmd: Autogenerate<client::ClientInterface>,
+    },
     /// general configuration
     Config(ConfigArgs),
     /// permissions grouping management
-    Group(GroupArgs),
+    Group {
+        #[clap(subcommand)]
+        cmd: Autogenerate<group::GroupInterface>,
+    },
     /// key management
     Key(KeyArgs),
     /// scope management
-    Scope(ScopeArgs),
+    Scope {
+        #[clap(subcommand)]
+        cmd: Autogenerate<scope::ScopeInterface>,
+    },
     /// run the actual OIDC server
     Server(ServerArgs),
     /// manual token generation and inspection
-    Token(TokenArgs),
+    Token {
+        #[clap(subcommand)]
+        cmd: TokenCommand,
+    },
     /// role management
-    Role(RoleArgs),
+    Role {
+        #[clap(subcommand)]
+        cmd: Autogenerate<role::RoleInterface>,
+    },
     /// user management
-    User(UserArgs),
+    User {
+        #[clap(subcommand)]
+        cmd: Autogenerate<user::UserInterface>,
+    },
 }
 
 struct RunArgs {
@@ -85,13 +106,13 @@ impl RootArgs {
             Command::Init => unreachable!(),
             Command::Config(v) => v.run(ra).await,
             Command::Key(v) => v.run(ra).await,
-            Command::Client(v) => v.run(ra).await,
-            Command::Scope(v) => v.run(ra).await,
-            Command::Group(v) => v.run(ra).await,
+            Command::Client { cmd } => cmd.perform(&ra.realm, &ra.realm.clients),
+            Command::Scope { cmd } => cmd.perform(&ra.realm, &ra.realm.scopes),
+            Command::Group { cmd } => cmd.perform(&ra.realm, &ra.realm.groups),
             Command::Server(v) => v.run(ra).await,
-            Command::Token(v) => v.run(ra).await,
-            Command::Role(v) => v.run(ra).await,
-            Command::User(v) => v.run(ra).await,
+            Command::Token { cmd } => cmd.run(ra).await,
+            Command::Role { cmd } => cmd.perform(&ra.realm, &ra.realm.roles),
+            Command::User { cmd } => cmd.perform(&ra.realm, &ra.realm.users),
         }
     }
 
@@ -211,7 +232,7 @@ impl ConfigArgs {
         match &self.command {
             ConfigCommand::Dump => {
                 let config = config::Config::build_from(&args.db, None);
-                println!("{:?}", config);
+                println!("{:#?}", config);
             }
             ConfigCommand::Set { key, value } => {
                 args.db.persistent_config.keyed(key).delete()?;
@@ -229,87 +250,6 @@ impl ConfigArgs {
     }
 }
 
-#[derive(Debug, Subcommand)]
-enum GroupCommand {
-    Create {
-        group_name: String,
-    },
-    Members {
-        group_name: String,
-    },
-    Roles {
-        group_name: String,
-    },
-    List,
-    AttachRole {
-        group_name: String,
-        role_name: String,
-    },
-    DetachRole {
-        group_name: String,
-        role_name: String,
-    },
-    AttachUser {
-        group_name: String,
-        username: String,
-    },
-    DetachUser {
-        group_name: String,
-        username: String,
-    },
-}
-
-#[derive(Debug, Parser)]
-struct GroupArgs {
-    #[clap(subcommand)]
-    command: GroupCommand,
-}
-
-impl GroupArgs {
-    async fn run(self, args: RunArgs) -> Result<(), UIDCError> {
-        todo!()
-        /*match &self.command {
-            GroupCommand::Create { group_name } => {
-                group_management::create_group(&args.realm, group_name)?;
-            }
-            GroupCommand::Members { group_name } => {
-                group_management::list_members(&args.realm, group_name)?;
-            }
-            GroupCommand::Roles { group_name } => {
-                group_management::list_roles(&args.realm, group_name)?;
-            }
-            GroupCommand::List => {
-                group_management::list_groups(&args.realm)?;
-            }
-            GroupCommand::AttachRole {
-                group_name,
-                role_name,
-            } => {
-                group_management::attach_role(&args.realm, group_name, role_name)?;
-            }
-            GroupCommand::DetachRole {
-                group_name,
-                role_name,
-            } => {
-                group_management::detach_role(&args.realm, group_name, role_name)?;
-            }
-            GroupCommand::AttachUser {
-                group_name,
-                username,
-            } => {
-                group_management::attach_user(&args.realm, group_name, username)?;
-            }
-            GroupCommand::DetachUser {
-                group_name,
-                username,
-            } => {
-                group_management::detach_user(&args.realm, group_name, username)?;
-            }
-        }*/
-        // Ok(())
-    }
-}
-
 #[derive(Debug, Subcommand)]
 enum ScopeCommand {
     AttachRole {
@@ -393,16 +333,10 @@ enum TokenCommand {
     },
 }
 
-#[derive(Debug, Parser)]
-struct TokenArgs {
-    #[clap(subcommand)]
-    command: TokenCommand,
-}
-
-impl TokenArgs {
+impl TokenCommand {
     async fn run(self, args: RunArgs) -> Result<(), UIDCError> {
         let config = config::Config::build_from(&args.db, None);
-        match &self.command {
+        match self {
             TokenCommand::GenerateAuth {
                 client,
                 username,
@@ -411,9 +345,9 @@ impl TokenArgs {
                 let token = token_management::create_auth_token(
                     &args.realm,
                     &config,
-                    client,
-                    username,
-                    scopes,
+                    &client,
+                    &username,
+                    &scopes,
                 )?;
                 println!("{}", token);
                 Ok(())
@@ -426,9 +360,9 @@ impl TokenArgs {
                 let token = token_management::create_refresh_token(
                     &args.realm,
                     &config,
-                    client,
-                    username,
-                    scopes,
+                    &client,
+                    &username,
+                    &scopes,
                 )?;
                 println!("{}", token);
                 Ok(())
@@ -440,50 +374,6 @@ impl TokenArgs {
     }
 }
 
-#[derive(Debug, Subcommand)]
-enum RoleCommand {
-    List,
-    Create { name: String },
-    Delete { name: String },
-}
-
-#[derive(Debug, Parser)]
-struct RoleArgs {
-    #[clap(subcommand)]
-    command: Autogenerate<role::RoleInterface>,
-}
-
-impl RoleArgs {
-    async fn run(self, args: RunArgs) -> Result<(), UIDCError> {
-        self.command.perform(&args.realm, &args.realm.roles, &args.realm.roles)
-    }
-}
-
-#[derive(Debug, Subcommand)]
-enum UserCommand {
-    Auth {
-        username: String,
-
-        #[clap(short = 'p', long, action = clap::ArgAction::Count)]
-        change_password: usize,
-
-        #[clap(short = 't', long, action = clap::ArgAction::Count)]
-        change_totp: usize,
-    },
-}
-
-#[derive(Debug, Parser)]
-struct UserArgs {
-    #[clap(subcommand)]
-    command: Autogenerate<user::UserInterface>,
-}
-
-impl UserArgs {
-    async fn run(self, args: RunArgs) -> Result<(), UIDCError> {
-        self.command.perform(&args.realm, &args.realm.users, &args.realm.users)
-    }
-}
-
 pub fn invoked() {
     let args = RootArgs::parse();
 

+ 62 - 0
src/cli/client.rs

@@ -0,0 +1,62 @@
+use std::str::FromStr;
+
+use microrm::{prelude::*, schema::entity::EntityID};
+use crate::{schema, UIDCError, key, client_management};
+
+#[derive(Debug)]
+pub struct ClientInterface;
+
+#[derive(Debug, clap::Subcommand)]
+pub enum ClientCommands {
+    Create { name: String, key_type: String },
+    RotateSecret { name: String },
+}
+
+impl microrm::cli::EntityInterface for ClientInterface {
+    type Error = UIDCError;
+    type Entity = schema::Client;
+    type Context = microrm::schema::Stored<schema::Realm>;
+    type CustomCommand = ClientCommands;
+
+    fn run_custom(
+        ctx: &Self::Context,
+        cmd: Self::CustomCommand,
+        _query_ctx: impl Queryable<EntityOutput = Self::Entity> + Insertable<Self::Entity>,
+    ) -> Result<(), Self::Error> {
+        match cmd {
+            ClientCommands::Create { name, key_type } => {
+                let kt = key::KeyType::from_str(key_type.as_str())?;
+                client_management::create(ctx, &name, kt)?;
+            },
+            ClientCommands::RotateSecret { name } =>  {
+                client_management::rotate_secret(ctx, &name)?;
+            },
+        }
+
+        Ok(())
+    }
+
+    fn should_override(_entity: &'static str, field: &'static str, _role: microrm::cli::ValueRole) -> bool {
+        if field == "realm" {
+            true
+        }
+        else {
+            false
+        }
+    }
+
+    fn override_for(
+        ctx: &Self::Context,
+        _entity: &'static str,
+        field: &'static str,
+        _role: microrm::cli::ValueRole,
+    ) -> String {
+        if field == "realm" {
+            format!("{}", ctx.id().into_raw())
+        }
+        else {
+            unreachable!()
+        }
+    }
+}
+

+ 59 - 0
src/cli/group.rs

@@ -0,0 +1,59 @@
+use microrm::{prelude::*, schema::entity::EntityID};
+use crate::{schema, UIDCError};
+
+#[derive(Debug)]
+pub struct GroupInterface;
+
+#[derive(Debug, clap::Subcommand)]
+pub enum GroupCommands {
+    Create { name: String }
+}
+
+impl microrm::cli::EntityInterface for GroupInterface {
+    type Error = UIDCError;
+    type Entity = schema::Group;
+    type Context = microrm::schema::Stored<schema::Realm>;
+    type CustomCommand = GroupCommands;
+
+    fn run_custom(
+        ctx: &Self::Context,
+        cmd: Self::CustomCommand,
+        query_ctx: impl Queryable<EntityOutput = Self::Entity> + Insertable<Self::Entity>,
+    ) -> Result<(), Self::Error> {
+        match cmd {
+            GroupCommands::Create { name } => {
+                query_ctx.insert(schema::Group {
+                    realm: ctx.id(),
+                    shortname: name,
+                    users: Default::default(),
+                    roles: Default::default(),
+                })?;
+            },
+        }
+
+        Ok(())
+    }
+
+    fn should_override(_entity: &'static str, field: &'static str, _role: microrm::cli::ValueRole) -> bool {
+        if field == "realm" {
+            true
+        }
+        else {
+            false
+        }
+    }
+
+    fn override_for(
+        ctx: &Self::Context,
+        _entity: &'static str,
+        field: &'static str,
+        _role: microrm::cli::ValueRole,
+    ) -> String {
+        if field == "realm" {
+            format!("{}", ctx.id().into_raw())
+        }
+        else {
+            unreachable!()
+        }
+    }
+}

+ 2 - 3
src/cli/role.rs

@@ -18,12 +18,11 @@ impl microrm::cli::EntityInterface for RoleInterface {
     fn run_custom(
         ctx: &Self::Context,
         cmd: Self::CustomCommand,
-        _query_ctx: impl Queryable<EntityOutput = Self::Entity>,
-        insert_ctx: &impl Insertable<Self::Entity>,
+        query_ctx: impl Queryable<EntityOutput = Self::Entity> + Insertable<Self::Entity>,
     ) -> Result<(), Self::Error> {
         match cmd {
             RoleCommands::Create { name } => {
-                insert_ctx.insert(schema::Role {
+                query_ctx.insert(schema::Role {
                     realm: ctx.id(),
                     shortname: name,
                     groups: Default::default(),

+ 58 - 0
src/cli/scope.rs

@@ -0,0 +1,58 @@
+use microrm::{prelude::*, schema::entity::EntityID};
+use crate::{schema, UIDCError};
+
+#[derive(Debug)]
+pub struct ScopeInterface;
+
+#[derive(Debug, clap::Subcommand)]
+pub enum ScopeCommands {
+    Create { name: String }
+}
+
+impl microrm::cli::EntityInterface for ScopeInterface {
+    type Error = UIDCError;
+    type Entity = schema::Scope;
+    type Context = microrm::schema::Stored<schema::Realm>;
+    type CustomCommand = ScopeCommands;
+
+    fn run_custom(
+        ctx: &Self::Context,
+        cmd: Self::CustomCommand,
+        query_ctx: impl Queryable<EntityOutput = Self::Entity> + Insertable<Self::Entity>,
+    ) -> Result<(), Self::Error> {
+        match cmd {
+            ScopeCommands::Create { name } => {
+                query_ctx.insert(schema::Scope {
+                    realm: ctx.id(),
+                    shortname: name,
+                    roles: Default::default(),
+                })?;
+            },
+        }
+
+        Ok(())
+    }
+
+    fn should_override(_entity: &'static str, field: &'static str, _role: microrm::cli::ValueRole) -> bool {
+        if field == "realm" {
+            true
+        }
+        else {
+            false
+        }
+    }
+
+    fn override_for(
+        ctx: &Self::Context,
+        _entity: &'static str,
+        field: &'static str,
+        _role: microrm::cli::ValueRole,
+    ) -> String {
+        if field == "realm" {
+            format!("{}", ctx.id().into_raw())
+        }
+        else {
+            unreachable!()
+        }
+    }
+}

+ 14 - 5
src/cli/user.rs

@@ -1,12 +1,19 @@
 use microrm::{prelude::*, schema::entity::EntityID};
-use crate::{schema, UIDCError};
+use crate::{schema, user_management, UIDCError};
 
 #[derive(Debug)]
 pub struct UserInterface;
 
 #[derive(Debug, clap::Subcommand)]
 pub enum UserCommands {
-    Create { username: String }
+    Create { username: String },
+    UpdateAuth {
+        username: String,
+        #[clap(short = 'p', long, action = clap::ArgAction::Count)]
+        password: u8,
+        #[clap(short = 't', long, action = clap::ArgAction::Count)]
+        totp: u8,
+    },
 }
 
 impl microrm::cli::EntityInterface for UserInterface {
@@ -18,18 +25,20 @@ impl microrm::cli::EntityInterface for UserInterface {
     fn run_custom(
         ctx: &Self::Context,
         cmd: Self::CustomCommand,
-        _query_ctx: impl Queryable<EntityOutput = Self::Entity>,
-        insert_ctx: &impl Insertable<Self::Entity>,
+        query_ctx: impl Queryable<EntityOutput = Self::Entity> + Insertable<Self::Entity>,
     ) -> Result<(), Self::Error> {
         match cmd {
             UserCommands::Create { username } => {
-                insert_ctx.insert(schema::User {
+                query_ctx.insert(schema::User {
                     realm: ctx.id(),
                     username,
                     auth: Default::default(),
                     groups: Default::default(),
                 })?;
             },
+            UserCommands::UpdateAuth { username, password, totp } => {
+                user_management::change_auth(ctx.as_ref(), &username, password > 0, totp > 0)?;
+            },
         }
 
         Ok(())

+ 9 - 0
src/client_management.rs

@@ -16,6 +16,15 @@ pub fn create(realm: &microrm::Stored<schema::Realm>, name: &String, key_type: K
     Ok(())
 }
 
+pub fn rotate_secret(realm: &microrm::Stored<schema::Realm>, name: &str) -> Result<(), UIDCError> {
+    let rng = ring::rand::SystemRandom::new();
+    let client_secret: [u8; 32] = ring::rand::generate(&rng).unwrap().expose();
+
+    todo!();
+
+    Ok(())
+}
+
 pub fn inspect(realm: &microrm::Stored<schema::Realm>, name: &str) -> Result<(), UIDCError> {
     if let Some(client) = realm.clients.with(schema::Client::Shortname, name).first().get()? {
         println!("Found client {name}");

+ 3 - 1
src/key.rs

@@ -5,6 +5,8 @@ use microrm::prelude::*;
 use ring::signature::{Ed25519KeyPair, KeyPair};
 use sha2::Digest;
 
+use itertools::Itertools;
+
 #[derive(Debug)]
 pub enum KeyError {
     Plain(&'static str),
@@ -38,7 +40,7 @@ impl std::str::FromStr for KeyType {
                 return Ok(*kty);
             }
         }
-        Err(UIDCError::Abort("invalid keytype"))
+        Err(UIDCError::AbortString(format!("invalid keytype: must be one of {}", KEY_TYPE_NAMES.iter().map(|v| v.0).join(","))))
     }
 }
 

+ 1 - 10
src/main.rs

@@ -4,7 +4,6 @@ mod cli;
 mod client_management;
 mod config;
 mod error;
-// mod group_management;
 mod jwt;
 mod key;
 mod role_management;
@@ -19,15 +18,7 @@ mod user_management;
 pub use error::UIDCError;
 
 fn main() {
-    stderrlog::new()
-        .module(module_path!())
-        .module("tide")
-        .module("microrm")
-        .show_module_names(true)
-        .timestamp(stderrlog::Timestamp::Millisecond)
-        .verbosity(10)
-        .init()
-        .unwrap();
+    pretty_env_logger::init_timed();
 
     cli::invoked();
 }