bleep bloop what was I doing again (#870)

* human-facing message generator thingie
* doctests for new code
This commit is contained in:
James Hodgkinson 2022-06-28 09:22:31 +10:00 committed by GitHub
parent b380c4b4ba
commit 664e2e4df0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 354 additions and 239 deletions

1
Cargo.lock generated
View file

@ -1010,6 +1010,7 @@ dependencies = [
"clap 3.2.6",
"clap_complete",
"kanidm",
"kanidm_proto",
"profiles",
"score",
"serde",

View file

@ -8,5 +8,6 @@
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
pub mod messages;
pub mod oauth2;
pub mod v1;

View file

@ -0,0 +1,129 @@
// User-facing output things
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ConsoleOutputMode {
Text,
JSON,
}
impl Default for ConsoleOutputMode {
fn default() -> Self {
ConsoleOutputMode::Text
}
}
impl FromStr for ConsoleOutputMode {
type Err = &'static str;
/// This can be safely unwrap'd because it'll always return a default
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"json" => Ok(ConsoleOutputMode::JSON),
"text" => Ok(ConsoleOutputMode::Text),
_ => {
eprintln!(
"Supplied output mode ({:?}) was invalid, defaulting to text",
s
);
Ok(ConsoleOutputMode::Text)
}
}
}
}
/// This will take any string, if it's 'text' or 'json' then you'll get
/// what you asked for, else you'll get a text version.
///
/// ```
/// use kanidm_proto::messages::ConsoleOutputMode;
/// let bork = "text";
/// let com: ConsoleOutputMode = bork.into();
/// matches!(ConsoleOutputMode::Text, com);
/// ```
impl From<&str> for ConsoleOutputMode {
fn from(input: &str) -> Self {
match ConsoleOutputMode::from_str(input) {
Ok(val) => val,
Err(_) => Self::Text,
}
}
}
/// This will take any string, if it's 'text' or 'json' then you'll get
/// what you asked for, else you'll get a text version.
///
/// ```
/// use kanidm_proto::messages::ConsoleOutputMode;
/// let bork = String::from("cr4bz");
/// let com: ConsoleOutputMode = bork.into();
/// matches!(ConsoleOutputMode::Text, com);
/// ```
impl From<String> for ConsoleOutputMode {
fn from(input: String) -> Self {
match ConsoleOutputMode::from_str(input.as_str()) {
Ok(val) => val,
Err(_) => Self::Text,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum MessageStatus {
Failure,
Success,
}
impl fmt::Display for MessageStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
match *self {
MessageStatus::Failure => f.write_str("failure"),
MessageStatus::Success => f.write_str("success"),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AccountChangeMessage {
#[serde(skip_serializing)]
pub output_mode: ConsoleOutputMode,
pub action: String,
pub result: String,
pub status: MessageStatus,
pub src_user: String,
pub dest_user: String,
}
impl Default for AccountChangeMessage {
fn default() -> Self {
AccountChangeMessage {
output_mode: ConsoleOutputMode::Text,
action: String::from(""),
result: String::from(""),
status: MessageStatus::Success,
src_user: String::from(""),
dest_user: String::from(""),
}
}
}
/// This outputs in either JSON or Text depending on the output_mode setting
impl fmt::Display for AccountChangeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.output_mode {
ConsoleOutputMode::JSON => write!(
f,
"{}",
serde_json::to_string(self).unwrap_or(format!("{:?}", self)) // if it fails to JSON serialize, just debug-dump it
),
ConsoleOutputMode::Text => write!(
f,
"{} - {} for user {}: {}",
self.status, self.action, self.dest_user, self.result,
),
}
}
}

View file

@ -3,22 +3,17 @@ use crate::{
AccountCredential, AccountOpt, AccountPerson, AccountPosix, AccountRadius, AccountSsh,
AccountValidity,
};
use qrcode::{render::unicode, QrCode};
// use std::io;
use kanidm_client::KanidmClient;
use time::OffsetDateTime;
use dialoguer::{theme::ColorfulTheme, Select};
use dialoguer::{Confirm, Input, Password};
// use webauthn_authenticator_rs::{u2fhid::U2FHid, WebauthnAuthenticator};
// use kanidm_client::ClientError;
use kanidm_client::ClientError::Http as ClientErrorHttp;
use kanidm_proto::v1::OperationError::PasswordQuality;
use kanidm_client::KanidmClient;
use kanidm_proto::messages::{AccountChangeMessage, MessageStatus};
use kanidm_proto::v1::OperationError::{InvalidAttribute, PasswordQuality};
use kanidm_proto::v1::{CUIntentToken, CURegState, CUSessionToken, CUStatus};
use std::fmt;
use qrcode::{render::unicode, QrCode};
use std::fmt::{self, Debug};
use std::str::FromStr;
use time::OffsetDateTime;
use url::Url;
impl AccountOpt {
@ -149,10 +144,23 @@ impl AccountOpt {
}
}
}, // end AccountOpt::Posix
AccountOpt::Person { commands } => match commands {
AccountPerson::Extend(aopt) => {
let client = aopt.copt.to_client().await;
if let Err(e) = client
let mut result_output = kanidm_proto::messages::AccountChangeMessage {
output_mode: aopt.copt.output_mode.to_owned().into(),
action: String::from("account_person_extend"),
result: String::from("This is a filler message"),
src_user: aopt
.copt
.username
.to_owned()
.unwrap_or(format!("{:?}", client.whoami().await)),
dest_user: aopt.aopts.account_id.to_string(),
status: kanidm_proto::messages::MessageStatus::Failure,
};
match client
.idm_account_person_extend(
aopt.aopts.account_id.as_str(),
aopt.mail.as_deref(),
@ -160,12 +168,71 @@ impl AccountOpt {
)
.await
{
error!("Error -> {:?}", e);
// TODO: JSON output for account person extend.
Ok(_) => {
result_output.result = format!(
"Successfully extended the user {}.",
aopt.aopts.account_id
);
match &aopt.legalname {
Some(legalname) => {
result_output.result +=
format!(" Set legalname to {}.", legalname).as_str()
}
_ => debug!("Didn't change legalname field."),
};
match &aopt.mail {
Some(mail) => {
result_output.result +=
format!(" Set mail to {:?}.", mail.join(", ")).as_str()
}
_ => debug!("Didn't change mail field."),
};
println!("{}", result_output);
}
// TODO: consider a macro to unpack the KanidmClient result object
Err(e) => {
match e {
ClientErrorHttp(_, result, _) => {
if let Some(ia_error) = result {
match ia_error {
InvalidAttribute(msg) => {
result_output.result =
format!("Failed to set value: {}", msg)
}
_ => {
result_output.result =
format!("Operation Error - {:?}", ia_error)
}
};
} else {
result_output.result =
format!("ClientError - {:?}", result);
}
}
_ => result_output.result = format!("Error -> {:?}", e),
};
eprintln!("{:?}", result_output);
}
}
}
// TODO: there should probably be an 'unset' variant of this
AccountPerson::Set(aopt) => {
let client = aopt.copt.to_client().await;
if let Err(e) = client
let mut result_output = AccountChangeMessage {
output_mode: aopt.copt.output_mode.to_owned().into(),
action: String::from("account_person set"),
result: String::from(""),
src_user: aopt
.copt
.username
.to_owned()
.unwrap_or(format!("{:?}", client.whoami().await)),
dest_user: aopt.aopts.account_id.to_string(),
status: MessageStatus::Failure,
};
match client
.idm_account_person_set(
aopt.aopts.account_id.as_str(),
aopt.mail.as_deref(),
@ -173,7 +240,16 @@ impl AccountOpt {
)
.await
{
error!("Error -> {:?}", e);
Ok(_) => {
result_output.status = kanidm_proto::messages::MessageStatus::Success;
result_output.result = "set 'person' status on user".to_string();
println!("{}", result_output)
}
// TODO: ponder macro'ing handling ClientError
Err(e) => {
result_output.result = format!("Error -> {:?}", e);
eprintln!("{}", result_output)
}
}
}
}, // end AccountOpt::Person
@ -460,13 +536,13 @@ impl AccountCredential {
.build();
println!("{}", image);
println!("");
println!();
println!("link: {}", url.as_str());
println!(
"command: kanidm account credential reset {}",
cuintent_token.token
);
println!("");
println!();
}
Err(e) => {
error!("Error starting credential reset -> {:?}", e);
@ -826,8 +902,7 @@ async fn credential_update_exec(
if password_a != password_b {
eprintln!("Passwords do not match");
} else {
if let Err(e) = client
} else if let Err(e) = client
.idm_account_credential_update_set_password(&session_token, &password_a)
.await
{
@ -840,8 +915,7 @@ async fn credential_update_exec(
_ => eprintln!("An error occured -> {:?}", e),
}
} else {
println!("success");
}
println!("Successfully reset password.");
}
}
CUAction::Totp => totp_enroll_prompt(&session_token, &client).await,

View file

@ -155,7 +155,7 @@ pub fn prompt_for_username_get_values() -> Result<(String, String), String> {
options.push(String::from(option.0));
}
let user_select = Select::with_theme(&ColorfulTheme::default())
.with_prompt("Authentication tokens exist. Please select one")
.with_prompt("Multiple authentication tokens exist. Please select one")
.default(0)
.items(&options)
.interact();

View file

@ -12,9 +12,7 @@
use clap::Parser;
use kanidm_cli::KanidmClientParser;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
#[tokio::main(flavor = "current_thread")]
async fn main() {

View file

@ -15,14 +15,20 @@ pub struct DebugOpt {
#[derive(Debug, Args)]
pub struct CommonOpt {
// TODO: this should probably be a flag, or renamed to log level if it's a level
#[clap(short, long, env = "KANIDM_DEBUG")]
pub debug: bool,
#[clap(short = 'H', long = "url", env = "KANIDM_URL")]
pub addr: Option<String>,
/// User which will initiate requests
#[clap(short = 'D', long = "name", env = "KANIDM_NAME")]
pub username: Option<String>,
/// Path to a CA certificate file
#[clap(parse(from_os_str), short = 'C', long = "ca", env = "KANIDM_CA_PATH")]
pub ca_path: Option<PathBuf>,
/// Log format (still in very early development)
#[clap(short, long = "output", env = "KANIDM_OUTPUT", default_value="text")]
pub output_mode: String,
}
#[derive(Debug, Args)]
@ -183,9 +189,9 @@ pub enum AccountRadius {
pub struct AccountPosixOpt {
#[clap(flatten)]
aopts: AccountCommonOpt,
#[clap(long = "gidnumber")]
#[clap(long)]
gidnumber: Option<u32>,
#[clap(long = "shell")]
#[clap(long)]
shell: Option<String>,
#[clap(flatten)]
copt: CommonOpt,
@ -205,9 +211,9 @@ pub enum AccountPosix {
pub struct AccountPersonOpt {
#[clap(flatten)]
aopts: AccountCommonOpt,
#[clap(long = "mail")]
#[clap(long, short, help="Set the mail address, can be set multiple times for multiple addresses.")]
mail: Option<Vec<String>>,
#[clap(long = "legalname")]
#[clap(long, short, help="Set the legal name for the person.")]
legalname: Option<String>,
#[clap(flatten)]
copt: CommonOpt,

View file

@ -18,6 +18,7 @@ path = "src/main.rs"
[dependencies]
kanidm = { path = "../idm" }
kanidm_proto = { path = "../../kanidm_proto" }
score = { path = "../score" }
clap = { version = "^3.2", features = ["derive", "env"] }
users = "^0.11.0"

View file

@ -28,7 +28,7 @@ use std::path::PathBuf;
use std::str::FromStr;
use kanidm::audit::LogLevel;
use kanidm::config::{Configuration, ConsoleOutputMode, OnlineBackup, ServerRole};
use kanidm::config::{Configuration, OnlineBackup, ServerRole};
use kanidm::tracing_tree;
use kanidm::utils::file_permissions_readonly;
use score::{
@ -221,9 +221,7 @@ async fn main() {
config.update_domain(&sconfig.domain.as_str());
config.update_db_arc_size(sconfig.db_arc_size);
config.update_role(sconfig.role);
config.update_output_mode(
ConsoleOutputMode::from_str(opt.commands.commonopt().output_mode.as_str()).unwrap(),
);
config.update_output_mode(opt.commands.commonopt().output_mode.to_owned().into());
// Apply any cli overrides, normally debug level.
if let Some(dll) = opt.commands.commonopt().debug.as_ref() {

View file

@ -6,7 +6,6 @@ struct CommonOpt {
#[clap(parse(from_os_str), short, long = "config", env = "KANIDM_CONFIG")]
/// Path to the server's configuration file. If it does not exist, it will be created.
config_path: PathBuf,
//TODO: remove this once we work out the format
/// Log format (still in very early development)
#[clap(short, long = "output", env = "KANIDM_OUTPUT", default_value="text")]
output_mode: String,

View file

@ -15,74 +15,54 @@ name = "kanidm"
path = "src/lib.rs"
[dependencies]
kanidm_proto = { path = "../../kanidm_proto" }
tracing = { version = "^0.1.35", features = ["attributes"] }
tracing-subscriber = { version = "^0.3.11", features = ["env-filter"] }
tracing-serde = "^0.1.3"
dyn-clone = "^1.0.6"
url = { version = "^2.2.2", features = ["serde"] }
tide = "^0.16.0"
async-trait = "^0.1.53"
fernet = { version = "^0.1.4", features = ["fernet_danger_timestamps"] }
compact_jwt = "^0.2.1"
async-std = { version = "^1.12.0", features = ["tokio1"] }
rand = "^0.8.5"
toml = "^0.5.9"
async-trait = "^0.1.53"
base64 = "^0.13.0"
chrono = "^0.4.19"
saffron = "^0.1.0"
regex = "^1.5.6"
lazy_static = "^1.4.0"
compact_jwt = "^0.2.1"
compiled-uuid = "0.1.2"
concread = "^0.3.4"
dyn-clone = "^1.0.6"
fernet = { version = "^0.1.4", features = ["fernet_danger_timestamps"] }
filetime = "^0.2.16"
futures = "^0.3.21"
futures-util = "^0.3.21"
tokio = { version = "^1.19.1", features = ["net", "sync", "time"] }
tokio-util = { version = "^0.7.3", features = ["codec"] }
hashbrown = { version = "0.12.0", features = ["serde", "inline-more", "ahash"] }
idlset = { version = "^0.2.3" }
kanidm_proto = { path = "../../kanidm_proto" }
lazy_static = "^1.4.0"
ldap3_proto = "^0.2.3"
libc = "^0.2.126"
libsqlite3-sys = "0.24.2"
num_enum = "^0.5.7"
openssl = "^0.10.38"
uuid = { version = "^1.1.2", features = ["serde", "v4" ] }
compiled-uuid = "0.1.2"
r2d2 = "^0.8.9"
r2d2_sqlite = "^0.20.0"
rand = "^0.8.5"
regex = "^1.5.6"
rusqlite = "^0.27.0"
saffron = "^0.1.0"
serde = { version = "^1.0.137", features = ["derive"] }
serde_cbor = "^0.11.2"
serde_json = "^1.0.81"
libsqlite3-sys = "0.24.2"
rusqlite = "^0.27.0"
r2d2 = "^0.8.10"
r2d2_sqlite = "^0.20.0"
time = { version = "=0.2.27", features = ["serde", "std"] }
hashbrown = { version = "0.12.0", features = ["serde", "inline-more", "ahash"] }
concread = "^0.3.4"
smolset = "^1.3.1"
sshkeys = "^0.3.1"
zxcvbn = "^2.2.1"
base64 = "^0.13.0"
idlset = { version = "^0.2.3" }
ldap3_proto = "^0.2.3"
webauthn-rs = "^0.3.2"
libc = "^0.2.126"
users = "^0.11.0"
smartstring = { version = "^1.0.1", features = ["serde"] }
validator = { version = "^0.15.0", features = ["phone"] }
smolset = "^1.3.1"
sshkeys = "^0.3.1"
tide = "^0.16.0"
time = { version = "=0.2.27", features = ["serde", "std"] }
tokio = { version = "^1.19.1", features = ["net", "sync", "time"] }
tokio-util = { version = "^0.7.3", features = ["codec"] }
toml = "^0.5.9"
touch = "^0.0.1"
filetime = "^0.2.16"
num_enum = "^0.5.7"
tracing = { version = "^0.1.35", features = ["attributes"] }
tracing-serde = "^0.1.3"
tracing-subscriber = { version = "^0.3.11", features = ["env-filter"] }
url = { version = "^2.2.2", features = ["serde"] }
users = "^0.11.0"
uuid = { version = "^1.1.2", features = ["serde", "v4" ] }
validator = { version = "^0.15.0", features = ["phone"] }
webauthn-rs = "^0.3.2"
zxcvbn = "^2.2.1"
[features]
# default = [ "libsqlite3-sys/bundled", "openssl/vendored" ]

View file

@ -4,6 +4,7 @@
//! These components should be "per server". Any "per domain" config should be in the system
//! or domain entries that are able to be replicated.
use kanidm_proto::messages::ConsoleOutputMode;
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -74,31 +75,6 @@ impl FromStr for ServerRole {
}
}
// TODO: this should probably be in the kanidm crate
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
#[serde(rename_all = "lowercase")]
pub enum ConsoleOutputMode {
Text,
JSON,
}
impl Default for ConsoleOutputMode {
fn default() -> Self {
ConsoleOutputMode::Text
}
}
impl FromStr for ConsoleOutputMode {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"json" => Ok(ConsoleOutputMode::JSON),
"text" => Ok(ConsoleOutputMode::Text),
_ => Err("Must be one of json, text"),
}
}
}
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Configuration {
pub address: String,

View file

@ -370,7 +370,7 @@ impl IdmServer {
}
impl IdmServerDelayed {
pub(crate) fn is_empty_or_panic(&mut self) {
pub(crate) fn check_is_empty_or_panic(&mut self) {
let waker = futures_task::noop_waker();
let mut cx = Context::from_waker(&waker);
match self.async_rx.poll_recv(&mut cx) {
@ -3107,7 +3107,7 @@ mod tests {
run_idm_test!(
|qs: &QueryServer, idms: &IdmServer, idms_delayed: &mut IdmServerDelayed| {
// Assert the delayed action queue is empty
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
// Setup the admin w_ an imported password.
{
let qs_write = qs.write(duration_from_epoch_now());
@ -3126,7 +3126,7 @@ mod tests {
qs_write.commit().expect("failed to commit");
}
// Still empty
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
// Do an auth, this will trigger the action to send.
check_admin_password(idms, "password");
// process it.
@ -3136,7 +3136,7 @@ mod tests {
// Check the admin pw still matches
check_admin_password(idms, "password");
// No delayed action was queued.
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
}
)
}
@ -3146,7 +3146,7 @@ mod tests {
run_idm_test!(
|_qs: &QueryServer, idms: &IdmServer, idms_delayed: &mut IdmServerDelayed| {
// Assert the delayed action queue is empty
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
// Setup the admin with an imported unix pw.
let idms_prox_write = idms.proxy_write(duration_from_epoch_now());
@ -3170,7 +3170,7 @@ mod tests {
};
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
assert!(idms_prox_write.commit().is_ok());
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
// Get the auth ready.
let uuae = UnixUserAuthEvent::new_internal(&UUID_ADMIN, "password");
let mut idms_auth = idms.auth();
@ -3197,7 +3197,7 @@ mod tests {
};
idms_auth.commit().expect("Must not fail");
// No delayed action was queued.
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
}
)
}
@ -3749,7 +3749,7 @@ mod tests {
// Assert we can increment the counter if needed.
// Assert the delayed action queue is empty
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
// Generate a fake counter increment
let da = DelayedAction::WebauthnCounterIncrement(WebauthnCounterIncrement {
@ -3841,7 +3841,7 @@ mod tests {
assert!(idms_prox_write.commit().is_ok());
// Assert the delayed action queue is empty
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
// Generate a fake action to remove one backup code
let da = DelayedAction::BackupCodeRemoval(BackupCodeRemoval {

View file

@ -191,7 +191,7 @@ macro_rules! run_idm_test_inner {
// Any needed teardown?
// Make sure there are no errors.
assert!(test_server.verify().len() == 0);
idms_delayed.is_empty_or_panic();
idms_delayed.check_is_empty_or_panic();
}};
}

View file

@ -1579,7 +1579,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
// Validate input.
// Is the modlist non zero?
if me.modlist.len() == 0 {
if me.modlist.is_empty() {
request_error!("modify: empty modify request");
return Err(OperationError::EmptyRequest);
}

View file

@ -336,7 +336,8 @@ impl TreeEvent {
fn record_u64(&mut self, field: &Field, value: u64) {
if field.name() == "event_tag_id" {
let tag = EventTag::try_from(value).unwrap_or_else(|_| {
panic!("Invalid `event_tag_id`: {}, this is a bug", value)
error!("Invalid `event_tag_id`: {}, this is a bug", value);
std::process::exit(1)
});
self.tag = Some(tag);
} else {

View file

@ -13,29 +13,25 @@ repository = "https://github.com/kanidm/kanidm/"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
kanidm = { path = "../idm" }
kanidm_proto = { path = "../../kanidm_proto" }
libc = "^0.2.126"
uuid = { version = "^1.1.2", features = ["serde", "v4" ] }
tide = "^0.16.0"
tide-openssl = "^0.1.1"
async-std = { version = "^1.12.0", features = ["tokio1"] }
async-trait = "^0.1.53"
compact_jwt = "^0.2.1"
futures-util = "^0.3.21"
tokio = { version = "^1.19.1", features = ["net", "sync", "io-util", "macros"] }
tokio-util = { version = "^0.7.3", features = ["codec"] }
tokio-openssl = "^0.6.3"
openssl = "^0.10.38"
kanidm = { path = "../idm" }
kanidm_client = { path = "../../kanidm_client" }
kanidm_proto = { path = "../../kanidm_proto" }
ldap3_proto = "^0.2.3"
tracing = { version = "^0.1.35", features = ["attributes"] }
libc = "^0.2.126"
openssl = "^0.10.38"
serde = { version = "^1.0.137", features = ["derive"] }
serde_json = "^1.0.81"
async-trait = "^0.1.53"
async-std = { version = "^1.12.0", features = ["tokio1"] }
compact_jwt = "^0.2.1"
tide = "^0.16.0"
tide-openssl = "^0.1.1"
tokio = { version = "^1.19.1", features = ["net", "sync", "io-util", "macros"] }
tokio-openssl = "^0.6.3"
tokio-util = { version = "^0.7.3", features = ["codec"] }
tracing = { version = "^0.1.35", features = ["attributes"] }
uuid = { version = "^1.1.2", features = ["serde", "v4" ] }
[build-dependencies]
profiles = { path = "../../profiles" }
@ -52,6 +48,5 @@ webauthn-authenticator-rs = "^0.3.2"
oauth2_ext = { package = "oauth2", version = "^4.1.0", default-features = false }
base64 = "^0.13.0"
kanidm_client = { path = "../../kanidm_client" }
url = { version = "^2.2.2", features = ["serde"] }
reqwest = { version = "0.11.11", features=["cookies", "json", "native-tls"] }

View file

@ -37,7 +37,7 @@ use libc::umask;
use kanidm::actors::v1_read::QueryServerReadV1;
use kanidm::actors::v1_write::QueryServerWriteV1;
use kanidm::be::{Backend, BackendConfig, BackendTransaction, FsType};
use kanidm::config::{Configuration, ConsoleOutputMode};
use kanidm::config::Configuration;
use kanidm::crypto::setup_tls;
use kanidm::idm::server::{IdmServer, IdmServerDelayed};
use kanidm::interval::IntervalActor;
@ -45,11 +45,9 @@ use kanidm::ldap::LdapServer;
use kanidm::schema::Schema;
use kanidm::status::StatusActor;
use kanidm::utils::{duration_from_epoch_now, touch_file_or_quit};
use kanidm_proto::messages::{AccountChangeMessage, MessageStatus};
use kanidm_proto::v1::OperationError;
use serde::{Deserialize, Serialize};
use serde_json;
use std::fmt;
use std::sync::Arc;
// === internal setup helpers
@ -483,42 +481,6 @@ pub fn verify_server_core(config: &Configuration) {
// Now add IDM server verifications?
}
// TODO: should this go somewhere else
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
enum MessageStatus {
Failure,
Success,
}
impl fmt::Display for MessageStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
match *self {
MessageStatus::Failure => f.write_str("failure"),
MessageStatus::Success => f.write_str("status"),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
struct AccountChangeMessage {
action: String,
result: String,
status: MessageStatus,
src_user: String,
dest_user: String,
}
impl fmt::Display for AccountChangeMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
serde_json::to_string(self).unwrap_or(format!("{:?}", self))
)
}
}
pub fn recover_account_core(config: &Configuration, name: &str) {
let schema = match Schema::new() {
Ok(s) => s,
@ -562,11 +524,10 @@ pub fn recover_account_core(config: &Configuration, name: &str) {
std::process::exit(1);
}
};
match config.output_mode {
ConsoleOutputMode::JSON => {
println!(
"{}",
AccountChangeMessage {
output_mode: config.output_mode,
status: MessageStatus::Success,
src_user: String::from("command-line invocation"),
dest_user: name.to_string(),
@ -574,14 +535,6 @@ pub fn recover_account_core(config: &Configuration, name: &str) {
action: String::from("recover_account"),
}
);
}
ConsoleOutputMode::Text => {
println!(
"Successfully recovered account '{}' - password reset to -> {}",
name, new_pw
);
}
}
}
pub async fn create_server_core(config: Configuration, config_test: bool) -> Result<(), ()> {

View file

@ -113,7 +113,7 @@ impl Component for PwModalApp {
type Message = Msg;
type Properties = ModalProps;
fn create(ctx: &Context<Self>) -> Self {
fn create(_ctx: &Context<Self>) -> Self {
console::log!("pw modal create");
PwModalApp {

View file

@ -339,10 +339,11 @@ impl CredentialResetApp {
uuid: _,
claims: _,
type_:
// TODO: review this and find out why we aren't using these variables
CredentialDetailType::PasswordMfa(
totp_set,
security_key_labels,
backup_codes_remaining,
_totp_set,
_security_key_labels,
_backup_codes_remaining,
),
}) => {
html! {

View file

@ -28,6 +28,7 @@ enum State {
Consent {
token: String,
client_name: String,
#[allow(dead_code)]
scopes: Vec<String>,
pii_scopes: Vec<String>,
consent_token: String,

View file

@ -2,7 +2,7 @@ use gloo::console;
use wasm_bindgen::prelude::*;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
pub use web_sys::InputEvent;
use web_sys::{Document, Event, HtmlButtonElement, HtmlElement, HtmlInputElement, Window};
use web_sys::{Document, Event, /*HtmlButtonElement,*/ HtmlElement, HtmlInputElement, Window};
pub fn window() -> Window {
web_sys::window().expect_throw("Unable to retrieve window")
@ -37,23 +37,23 @@ pub fn get_value_from_input_event(e: InputEvent) -> String {
target.value()
}
pub fn get_element_by_id(id: &str) -> Option<HtmlElement> {
document()
.get_element_by_id(id)
.and_then(|element| element.dyn_into::<web_sys::HtmlElement>().ok())
}
// pub fn get_element_by_id(id: &str) -> Option<HtmlElement> {
// document()
// .get_element_by_id(id)
// .and_then(|element| element.dyn_into::<web_sys::HtmlElement>().ok())
// }
pub fn get_buttonelement_by_id(id: &str) -> Option<HtmlButtonElement> {
document()
.get_element_by_id(id)
.and_then(|element| element.dyn_into::<web_sys::HtmlButtonElement>().ok())
}
// pub fn get_buttonelement_by_id(id: &str) -> Option<HtmlButtonElement> {
// document()
// .get_element_by_id(id)
// .and_then(|element| element.dyn_into::<web_sys::HtmlButtonElement>().ok())
// }
pub fn get_inputelement_by_id(id: &str) -> Option<HtmlInputElement> {
document()
.get_element_by_id(id)
.and_then(|element| element.dyn_into::<web_sys::HtmlInputElement>().ok())
}
// pub fn get_inputelement_by_id(id: &str) -> Option<HtmlInputElement> {
// document()
// .get_element_by_id(id)
// .and_then(|element| element.dyn_into::<web_sys::HtmlInputElement>().ok())
// }
pub fn get_value_from_element_id(id: &str) -> Option<String> {
document()

View file

@ -147,7 +147,8 @@ impl Component for SecurityApp {
<button type="button" class="btn btn-primary"
disabled={ !submit_enabled }
onclick={
ctx.link().callback(|e| {
// TODO: figure out if we need the e here? :)
ctx.link().callback(|_e| {
Msg::RequestCredentialUpdate
})
}