mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
20240221 2489 cleanup api v1 (#2573)
This commit is contained in:
parent
4096b8f02d
commit
fbc021f487
40
Cargo.lock
generated
40
Cargo.lock
generated
|
@ -221,8 +221,6 @@ dependencies = [
|
|||
"memchr",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"zstd",
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -667,7 +665,6 @@ version = "1.0.83"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -2885,15 +2882,6 @@ version = "1.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.3.1"
|
||||
|
@ -6892,34 +6880,6 @@ dependencies = [
|
|||
"flate2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.9+zstd.1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zxcvbn"
|
||||
version = "2.2.2"
|
||||
|
|
|
@ -29,6 +29,7 @@ use kanidm_proto::constants::{
|
|||
APPLICATION_JSON, ATTR_ENTRY_MANAGED_BY, ATTR_NAME, CLIENT_TOKEN_CACHE, KOPID, KSESSIONID,
|
||||
KVERSION,
|
||||
};
|
||||
use kanidm_proto::internal::*;
|
||||
use kanidm_proto::v1::*;
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
use reqwest::Response;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::internal::{IdentifyUserRequest, IdentifyUserResponse};
|
||||
use kanidm_proto::v1::{
|
||||
AccountUnixExtend, CredentialStatus, Entry, SingleStringRequest, UatStatus,
|
||||
};
|
||||
use kanidm_proto::internal::{CredentialStatus, IdentifyUserRequest, IdentifyUserResponse};
|
||||
use kanidm_proto::v1::{AccountUnixExtend, Entry, SingleStringRequest, UatStatus};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{ClientError, KanidmClient};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use kanidm_proto::constants::{ATTR_DISPLAYNAME, ATTR_ENTRY_MANAGED_BY, ATTR_MAIL, ATTR_NAME};
|
||||
use kanidm_proto::v1::{AccountUnixExtend, ApiToken, ApiTokenGenerate, CredentialStatus, Entry};
|
||||
use kanidm_proto::internal::{ApiToken, CredentialStatus};
|
||||
use kanidm_proto::v1::{AccountUnixExtend, ApiTokenGenerate, Entry};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// include!("src/lib/audit_loglevel.rs");
|
||||
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=DEP_OPENSSL_VERSION_NUMBER");
|
||||
if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
|
||||
let version = u64::from_str_radix(&v, 16).unwrap();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use openssl::error::ErrorStack as OpenSSLErrorStack;
|
||||
use openssl::hash::{self, MessageDigest};
|
||||
use openssl::nid::Nid;
|
||||
|
|
|
@ -33,6 +33,14 @@ fn determine_git_rev() -> Option<String> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
/*
|
||||
* https://doc.rust-lang.org/cargo/reference/build-scripts.html#change-detection
|
||||
* If the build script inherently does not need to re-run under any circumstance, then emitting
|
||||
* cargo:rerun-if-changed=build.rs is a simple way to prevent it from being re-run (otherwise,
|
||||
* the default if no rerun-if instructions are emitted is to scan the entire package directory
|
||||
* for changes).
|
||||
*/
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=KANIDM_BUILD_PROFILE");
|
||||
|
||||
let profile = env::var("KANIDM_BUILD_PROFILE").unwrap_or_else(|_| "developer".to_string());
|
||||
|
|
|
@ -2,6 +2,9 @@ use base64::{engine::general_purpose, Engine as _};
|
|||
use serde::Deserialize;
|
||||
use std::env;
|
||||
|
||||
// To debug why a rebuild is requested.
|
||||
// CARGO_LOG=cargo::core::compiler::fingerprint=info cargo ...
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(non_camel_case_types)]
|
||||
enum CpuOptLevel {
|
||||
|
@ -76,6 +79,9 @@ pub fn apply_profile() {
|
|||
// We have to setup for our pkg version to be passed into things correctly
|
||||
// now. This relies on the profile build.rs to get the commit rev if present, but
|
||||
// we combine it with the local package version
|
||||
println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");
|
||||
println!("cargo:rerun-if-env-changed=KANIDM_PKG_COMMIT_REV");
|
||||
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
if let Some(commit_rev) = option_env!("KANIDM_PKG_COMMIT_REV") {
|
||||
println!(
|
||||
|
|
|
@ -84,9 +84,9 @@ Stable APIs are:
|
|||
|
||||
- LDAP protocol operations
|
||||
- JSON HTTP end points which use elements from
|
||||
[`proto/src/v1.rs`](https://github.com/kanidm/kanidm/blob/master/proto/src/v1.rs)
|
||||
[`proto/src/v1`](https://github.com/kanidm/kanidm/blob/master/proto/src/v1)
|
||||
- SCIM operations from
|
||||
[`proto/src/scim_v1.rs`](https://github.com/kanidm/kanidm/blob/master/proto/src/scim_v1.rs)
|
||||
[`proto/src/scim_v1`](https://github.com/kanidm/kanidm/blob/master/proto/src/scim_v1)
|
||||
|
||||
All other APIs and interactions are not considered stable. Changes will be minimised if possible.
|
||||
This includes but is not limited to:
|
||||
|
|
|
@ -5,10 +5,15 @@ pub mod uri;
|
|||
/// The default location for the `kanidm` CLI tool's token cache.
|
||||
pub const CLIENT_TOKEN_CACHE: &str = "~/.cache/kanidm_tokens";
|
||||
|
||||
/// Content type string for jpeg
|
||||
pub const CONTENT_TYPE_JPG: &str = "image/jpeg";
|
||||
/// Content type string for png
|
||||
pub const CONTENT_TYPE_PNG: &str = "image/png";
|
||||
/// Content type string for gif
|
||||
pub const CONTENT_TYPE_GIF: &str = "image/gif";
|
||||
/// Content type string for svg
|
||||
pub const CONTENT_TYPE_SVG: &str = "image/svg+xml";
|
||||
/// Content type string for webp
|
||||
pub const CONTENT_TYPE_WEBP: &str = "image/webp";
|
||||
|
||||
// For when the user uploads things to the various image endpoints, these are the valid content-types.
|
||||
|
|
437
proto/src/internal/credupdate.rs
Normal file
437
proto/src/internal/credupdate.rs
Normal file
|
@ -0,0 +1,437 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use url::Url;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use webauthn_rs_proto::CreationChallengeResponse;
|
||||
use webauthn_rs_proto::RegisterPublicKeyCredential;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum TotpAlgo {
|
||||
Sha1,
|
||||
Sha256,
|
||||
Sha512,
|
||||
}
|
||||
|
||||
impl fmt::Display for TotpAlgo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
TotpAlgo::Sha1 => write!(f, "SHA1"),
|
||||
TotpAlgo::Sha256 => write!(f, "SHA256"),
|
||||
TotpAlgo::Sha512 => write!(f, "SHA512"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct TotpSecret {
|
||||
pub accountname: String,
|
||||
/// User-facing name of the system, issuer of the TOTP
|
||||
pub issuer: String,
|
||||
pub secret: Vec<u8>,
|
||||
pub algo: TotpAlgo,
|
||||
pub step: u64,
|
||||
pub digits: u8,
|
||||
}
|
||||
|
||||
impl TotpSecret {
|
||||
/// <https://github.com/google/google-authenticator/wiki/Key-Uri-Format>
|
||||
pub fn to_uri(&self) -> String {
|
||||
let accountname = urlencoding::Encoded(&self.accountname);
|
||||
let issuer = urlencoding::Encoded(&self.issuer);
|
||||
let label = format!("{}:{}", issuer, accountname);
|
||||
let algo = self.algo.to_string();
|
||||
let secret = self.get_secret();
|
||||
let period = self.step;
|
||||
let digits = self.digits;
|
||||
|
||||
format!(
|
||||
"otpauth://totp/{}?secret={}&issuer={}&algorithm={}&digits={}&period={}",
|
||||
label, secret, issuer, algo, digits, period
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_secret(&self) -> String {
|
||||
base32::encode(base32::Alphabet::RFC4648 { padding: false }, &self.secret)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct CUIntentToken {
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
|
||||
pub struct CUSessionToken {
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum CURequest {
|
||||
PrimaryRemove,
|
||||
Password(String),
|
||||
CancelMFAReg,
|
||||
TotpGenerate,
|
||||
TotpVerify(u32, String),
|
||||
TotpAcceptSha1,
|
||||
TotpRemove(String),
|
||||
BackupCodeGenerate,
|
||||
BackupCodeRemove,
|
||||
PasskeyInit,
|
||||
PasskeyFinish(String, RegisterPublicKeyCredential),
|
||||
PasskeyRemove(Uuid),
|
||||
AttestedPasskeyInit,
|
||||
AttestedPasskeyFinish(String, RegisterPublicKeyCredential),
|
||||
AttestedPasskeyRemove(Uuid),
|
||||
}
|
||||
|
||||
impl fmt::Debug for CURequest {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let t = match self {
|
||||
CURequest::PrimaryRemove => "CURequest::PrimaryRemove",
|
||||
CURequest::Password(_) => "CURequest::Password",
|
||||
CURequest::CancelMFAReg => "CURequest::CancelMFAReg",
|
||||
CURequest::TotpGenerate => "CURequest::TotpGenerate",
|
||||
CURequest::TotpVerify(_, _) => "CURequest::TotpVerify",
|
||||
CURequest::TotpAcceptSha1 => "CURequest::TotpAcceptSha1",
|
||||
CURequest::TotpRemove(_) => "CURequest::TotpRemove",
|
||||
CURequest::BackupCodeGenerate => "CURequest::BackupCodeGenerate",
|
||||
CURequest::BackupCodeRemove => "CURequest::BackupCodeRemove",
|
||||
CURequest::PasskeyInit => "CURequest::PasskeyInit",
|
||||
CURequest::PasskeyFinish(_, _) => "CURequest::PasskeyFinish",
|
||||
CURequest::PasskeyRemove(_) => "CURequest::PasskeyRemove",
|
||||
CURequest::AttestedPasskeyInit => "CURequest::AttestedPasskeyInit",
|
||||
CURequest::AttestedPasskeyFinish(_, _) => "CURequest::AttestedPasskeyFinish",
|
||||
CURequest::AttestedPasskeyRemove(_) => "CURequest::AttestedPasskeyRemove",
|
||||
};
|
||||
writeln!(f, "{}", t)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub enum CURegState {
|
||||
// Nothing in progress.
|
||||
None,
|
||||
TotpCheck(TotpSecret),
|
||||
TotpTryAgain,
|
||||
TotpInvalidSha1,
|
||||
BackupCodes(Vec<String>),
|
||||
Passkey(CreationChallengeResponse),
|
||||
AttestedPasskey(CreationChallengeResponse),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub enum CUExtPortal {
|
||||
None,
|
||||
Hidden,
|
||||
Some(Url),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ToSchema, PartialEq)]
|
||||
pub enum CUCredState {
|
||||
Modifiable,
|
||||
DeleteOnly,
|
||||
AccessDeny,
|
||||
PolicyDeny,
|
||||
// Disabled,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub enum CURegWarning {
|
||||
MfaRequired,
|
||||
PasskeyRequired,
|
||||
AttestedPasskeyRequired,
|
||||
AttestedResidentKeyRequired,
|
||||
Unsatisfiable,
|
||||
WebauthnAttestationUnsatisfiable,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct CUStatus {
|
||||
// Display values
|
||||
pub spn: String,
|
||||
pub displayname: String,
|
||||
pub ext_cred_portal: CUExtPortal,
|
||||
// Internal State Tracking
|
||||
pub mfaregstate: CURegState,
|
||||
// Display hints + The credential details.
|
||||
pub can_commit: bool,
|
||||
pub warnings: Vec<CURegWarning>,
|
||||
pub primary: Option<CredentialDetail>,
|
||||
pub primary_state: CUCredState,
|
||||
pub passkeys: Vec<PasskeyDetail>,
|
||||
pub passkeys_state: CUCredState,
|
||||
pub attested_passkeys: Vec<PasskeyDetail>,
|
||||
pub attested_passkeys_state: CUCredState,
|
||||
pub attested_passkeys_allowed_devices: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct CredentialStatus {
|
||||
pub creds: Vec<CredentialDetail>,
|
||||
}
|
||||
|
||||
impl fmt::Display for CredentialStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for cred in &self.creds {
|
||||
writeln!(f, "---")?;
|
||||
cred.fmt(f)?;
|
||||
}
|
||||
writeln!(f, "---")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, ToSchema)]
|
||||
pub enum CredentialDetailType {
|
||||
Password,
|
||||
GeneratedPassword,
|
||||
Passkey(Vec<String>),
|
||||
/// totp, webauthn
|
||||
PasswordMfa(Vec<String>, Vec<String>, usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct CredentialDetail {
|
||||
pub uuid: Uuid,
|
||||
pub type_: CredentialDetailType,
|
||||
}
|
||||
|
||||
impl fmt::Display for CredentialDetail {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "uuid: {}", self.uuid)?;
|
||||
/*
|
||||
writeln!(f, "claims:")?;
|
||||
for claim in &self.claims {
|
||||
writeln!(f, " * {}", claim)?;
|
||||
}
|
||||
*/
|
||||
match &self.type_ {
|
||||
CredentialDetailType::Password => writeln!(f, "password: set"),
|
||||
CredentialDetailType::GeneratedPassword => writeln!(f, "generated password: set"),
|
||||
CredentialDetailType::Passkey(labels) => {
|
||||
if labels.is_empty() {
|
||||
writeln!(f, "passkeys: none registered")
|
||||
} else {
|
||||
writeln!(f, "passkeys:")?;
|
||||
for label in labels {
|
||||
writeln!(f, " * {}", label)?;
|
||||
}
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
CredentialDetailType::PasswordMfa(totp_labels, wan_labels, backup_code) => {
|
||||
writeln!(f, "password: set")?;
|
||||
|
||||
if !totp_labels.is_empty() {
|
||||
writeln!(f, "totp:")?;
|
||||
for label in totp_labels {
|
||||
writeln!(f, " * {}", label)?;
|
||||
}
|
||||
} else {
|
||||
writeln!(f, "totp: disabled")?;
|
||||
}
|
||||
|
||||
if *backup_code > 0 {
|
||||
writeln!(f, "backup_code: enabled")?;
|
||||
} else {
|
||||
writeln!(f, "backup_code: disabled")?;
|
||||
}
|
||||
|
||||
if !wan_labels.is_empty() {
|
||||
// We no longer show the deprecated security key case by default.
|
||||
writeln!(f, " ⚠️ warning - security keys are deprecated.")?;
|
||||
writeln!(f, " ⚠️ you should re-enroll these to passkeys.")?;
|
||||
writeln!(f, "security keys:")?;
|
||||
for label in wan_labels {
|
||||
writeln!(f, " * {}", label)?;
|
||||
}
|
||||
write!(f, "")
|
||||
} else {
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct PasskeyDetail {
|
||||
pub uuid: Uuid,
|
||||
pub tag: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct BackupCodesView {
|
||||
pub backup_codes: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, ToSchema, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum PasswordFeedback {
|
||||
// https://docs.rs/zxcvbn/latest/zxcvbn/feedback/enum.Suggestion.html
|
||||
UseAFewWordsAvoidCommonPhrases,
|
||||
NoNeedForSymbolsDigitsOrUppercaseLetters,
|
||||
AddAnotherWordOrTwo,
|
||||
CapitalizationDoesntHelpVeryMuch,
|
||||
AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase,
|
||||
ReversedWordsArentMuchHarderToGuess,
|
||||
PredictableSubstitutionsDontHelpVeryMuch,
|
||||
UseALongerKeyboardPatternWithMoreTurns,
|
||||
AvoidRepeatedWordsAndCharacters,
|
||||
AvoidSequences,
|
||||
AvoidRecentYears,
|
||||
AvoidYearsThatAreAssociatedWithYou,
|
||||
AvoidDatesAndYearsThatAreAssociatedWithYou,
|
||||
// https://docs.rs/zxcvbn/latest/zxcvbn/feedback/enum.Warning.html
|
||||
StraightRowsOfKeysAreEasyToGuess,
|
||||
ShortKeyboardPatternsAreEasyToGuess,
|
||||
RepeatsLikeAaaAreEasyToGuess,
|
||||
RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess,
|
||||
ThisIsATop10Password,
|
||||
ThisIsATop100Password,
|
||||
ThisIsACommonPassword,
|
||||
ThisIsSimilarToACommonlyUsedPassword,
|
||||
SequencesLikeAbcAreEasyToGuess,
|
||||
RecentYearsAreEasyToGuess,
|
||||
AWordByItselfIsEasyToGuess,
|
||||
DatesAreOftenEasyToGuess,
|
||||
NamesAndSurnamesByThemselvesAreEasyToGuess,
|
||||
CommonNamesAndSurnamesAreEasyToGuess,
|
||||
// Custom
|
||||
TooShort(u32),
|
||||
BadListed,
|
||||
DontReusePasswords,
|
||||
}
|
||||
|
||||
/// Human-readable PasswordFeedback result.
|
||||
impl fmt::Display for PasswordFeedback {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
PasswordFeedback::AddAnotherWordOrTwo => write!(f, "Add another word or two."),
|
||||
PasswordFeedback::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase => write!(
|
||||
f,
|
||||
"All uppercase is almost as easy to guess as all lowercase."
|
||||
),
|
||||
PasswordFeedback::AvoidDatesAndYearsThatAreAssociatedWithYou => write!(
|
||||
f,
|
||||
"Avoid dates and years that are associated with you or your account."
|
||||
),
|
||||
PasswordFeedback::AvoidRecentYears => write!(f, "Avoid recent years."),
|
||||
PasswordFeedback::AvoidRepeatedWordsAndCharacters => {
|
||||
write!(f, "Avoid repeated words and characters.")
|
||||
}
|
||||
PasswordFeedback::AvoidSequences => write!(f, "Avoid sequences of characters."),
|
||||
PasswordFeedback::AvoidYearsThatAreAssociatedWithYou => {
|
||||
write!(f, "Avoid years that are associated with you.")
|
||||
}
|
||||
PasswordFeedback::AWordByItselfIsEasyToGuess => {
|
||||
write!(f, "A word by itself is easy to guess.")
|
||||
}
|
||||
PasswordFeedback::BadListed => write!(
|
||||
f,
|
||||
"This password has been compromised or otherwise blocked and can not be used."
|
||||
),
|
||||
PasswordFeedback::CapitalizationDoesntHelpVeryMuch => {
|
||||
write!(f, "Capitalization doesn't help very much.")
|
||||
}
|
||||
PasswordFeedback::CommonNamesAndSurnamesAreEasyToGuess => {
|
||||
write!(f, "Common names and surnames are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::DatesAreOftenEasyToGuess => {
|
||||
write!(f, "Dates are often easy to guess.")
|
||||
}
|
||||
PasswordFeedback::DontReusePasswords => {
|
||||
write!(
|
||||
f,
|
||||
"Don't reuse passwords that already exist on your account"
|
||||
)
|
||||
}
|
||||
PasswordFeedback::NamesAndSurnamesByThemselvesAreEasyToGuess => {
|
||||
write!(f, "Names and surnames by themselves are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::NoNeedForSymbolsDigitsOrUppercaseLetters => {
|
||||
write!(f, "No need for symbols, digits or upper-case letters.")
|
||||
}
|
||||
PasswordFeedback::PredictableSubstitutionsDontHelpVeryMuch => {
|
||||
write!(f, "Predictable substitutions don't help very much.")
|
||||
}
|
||||
PasswordFeedback::RecentYearsAreEasyToGuess => {
|
||||
write!(f, "Recent years are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::RepeatsLikeAaaAreEasyToGuess => {
|
||||
write!(f, "Repeats like 'aaa' are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess => write!(
|
||||
f,
|
||||
"Repeats like abcabcabc are only slightly harder to guess."
|
||||
),
|
||||
PasswordFeedback::ReversedWordsArentMuchHarderToGuess => {
|
||||
write!(f, "Reversed words aren't much harder to guess.")
|
||||
}
|
||||
PasswordFeedback::SequencesLikeAbcAreEasyToGuess => {
|
||||
write!(f, "Sequences like 'abc' are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::ShortKeyboardPatternsAreEasyToGuess => {
|
||||
write!(f, "Short keyboard patterns are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::StraightRowsOfKeysAreEasyToGuess => {
|
||||
write!(f, "Straight rows of keys are easy to guess.")
|
||||
}
|
||||
PasswordFeedback::ThisIsACommonPassword => write!(f, "This is a common password."),
|
||||
PasswordFeedback::ThisIsATop100Password => write!(f, "This is a top 100 password."),
|
||||
PasswordFeedback::ThisIsATop10Password => write!(f, "This is a top 10 password."),
|
||||
PasswordFeedback::ThisIsSimilarToACommonlyUsedPassword => {
|
||||
write!(f, "This is similar to a commonly used password.")
|
||||
}
|
||||
PasswordFeedback::TooShort(minlength) => write!(
|
||||
f,
|
||||
"Password too was short, needs to be at least {} characters long.",
|
||||
minlength
|
||||
),
|
||||
PasswordFeedback::UseAFewWordsAvoidCommonPhrases => {
|
||||
write!(f, "Use a few words and avoid common phrases.")
|
||||
}
|
||||
PasswordFeedback::UseALongerKeyboardPatternWithMoreTurns => {
|
||||
write!(
|
||||
f,
|
||||
"The password included keyboard patterns across too much of a single row."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{TotpAlgo, TotpSecret};
|
||||
|
||||
#[test]
|
||||
fn totp_to_string() {
|
||||
let totp = TotpSecret {
|
||||
accountname: "william".to_string(),
|
||||
issuer: "blackhats".to_string(),
|
||||
secret: vec![0xaa, 0xbb, 0xcc, 0xdd],
|
||||
step: 30,
|
||||
algo: TotpAlgo::Sha256,
|
||||
digits: 6,
|
||||
};
|
||||
let s = totp.to_uri();
|
||||
assert!(s == "otpauth://totp/blackhats:william?secret=VK54ZXI&issuer=blackhats&algorithm=SHA256&digits=6&period=30");
|
||||
|
||||
// check that invalid issuer/accounts are cleaned up.
|
||||
let totp = TotpSecret {
|
||||
accountname: "william:%3A".to_string(),
|
||||
issuer: "blackhats australia".to_string(),
|
||||
secret: vec![0xaa, 0xbb, 0xcc, 0xdd],
|
||||
step: 30,
|
||||
algo: TotpAlgo::Sha256,
|
||||
digits: 6,
|
||||
};
|
||||
let s = totp.to_uri();
|
||||
println!("{}", s);
|
||||
assert!(s == "otpauth://totp/blackhats%20australia:william%3A%253A?secret=VK54ZXI&issuer=blackhats%20australia&algorithm=SHA256&digits=6&period=30");
|
||||
}
|
||||
}
|
147
proto/src/internal/error.rs
Normal file
147
proto/src/internal/error.rs
Normal file
|
@ -0,0 +1,147 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::credupdate::PasswordFeedback;
|
||||
|
||||
/* ===== errors ===== */
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SchemaError {
|
||||
NotImplemented,
|
||||
NoClassFound,
|
||||
InvalidClass(Vec<String>),
|
||||
MissingMustAttribute(Vec<String>),
|
||||
InvalidAttribute(String),
|
||||
InvalidAttributeSyntax(String),
|
||||
AttributeNotValidForClass(String),
|
||||
SupplementsNotSatisfied(Vec<String>),
|
||||
ExcludesNotSatisfied(Vec<String>),
|
||||
EmptyFilter,
|
||||
Corrupted,
|
||||
PhantomAttribute(String),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum PluginError {
|
||||
AttrUnique(String),
|
||||
Base(String),
|
||||
ReferentialIntegrity(String),
|
||||
CredImport(String),
|
||||
Oauth2Secrets,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ConsistencyError {
|
||||
Unknown,
|
||||
// Class, Attribute
|
||||
SchemaClassMissingAttribute(String, String),
|
||||
SchemaClassPhantomAttribute(String, String),
|
||||
SchemaUuidNotUnique(Uuid),
|
||||
QueryServerSearchFailure,
|
||||
EntryUuidCorrupt(u64),
|
||||
UuidIndexCorrupt(String),
|
||||
UuidNotUnique(String),
|
||||
RefintNotUpheld(u64),
|
||||
MemberOfInvalid(u64),
|
||||
InvalidAttributeType(String),
|
||||
DuplicateUniqueAttribute,
|
||||
InvalidSpn(u64),
|
||||
SqliteIntegrityFailure,
|
||||
BackendAllIdsSync,
|
||||
BackendIndexSync,
|
||||
ChangelogDesynchronised(u64),
|
||||
ChangeStateDesynchronised(u64),
|
||||
RuvInconsistent(String),
|
||||
DeniedName(Uuid),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum OperationError {
|
||||
SessionExpired,
|
||||
EmptyRequest,
|
||||
Backend,
|
||||
NoMatchingEntries,
|
||||
NoMatchingAttributes,
|
||||
CorruptedEntry(u64),
|
||||
CorruptedIndex(String),
|
||||
// TODO: this should just be a vec of the ConsistencyErrors, surely?
|
||||
ConsistencyError(Vec<Result<(), ConsistencyError>>),
|
||||
SchemaViolation(SchemaError),
|
||||
Plugin(PluginError),
|
||||
FilterGeneration,
|
||||
FilterUuidResolution,
|
||||
InvalidAttributeName(String),
|
||||
InvalidAttribute(String),
|
||||
InvalidDbState,
|
||||
InvalidCacheState,
|
||||
InvalidValueState,
|
||||
InvalidEntryId,
|
||||
InvalidRequestState,
|
||||
InvalidSyncState,
|
||||
InvalidState,
|
||||
InvalidEntryState,
|
||||
InvalidUuid,
|
||||
InvalidReplChangeId,
|
||||
InvalidAcpState(String),
|
||||
InvalidSchemaState(String),
|
||||
InvalidAccountState(String),
|
||||
MissingEntries,
|
||||
ModifyAssertionFailed,
|
||||
BackendEngine,
|
||||
SqliteError, //(RusqliteError)
|
||||
FsError,
|
||||
SerdeJsonError,
|
||||
SerdeCborError,
|
||||
AccessDenied,
|
||||
NotAuthenticated,
|
||||
NotAuthorised,
|
||||
InvalidAuthState(String),
|
||||
InvalidSessionState,
|
||||
SystemProtectedObject,
|
||||
SystemProtectedAttribute,
|
||||
PasswordQuality(Vec<PasswordFeedback>),
|
||||
CryptographyError,
|
||||
ResourceLimit,
|
||||
QueueDisconnected,
|
||||
Webauthn,
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
Wait(time::OffsetDateTime),
|
||||
ReplReplayFailure,
|
||||
ReplEntryNotChanged,
|
||||
ReplInvalidRUVState,
|
||||
ReplDomainLevelUnsatisfiable,
|
||||
ReplDomainUuidMismatch,
|
||||
ReplServerUuidSplitDataState,
|
||||
TransactionAlreadyCommitted,
|
||||
/// when you ask for a gid that's lower than a safe minimum
|
||||
GidOverlapsSystemMin(u32),
|
||||
/// When a name is denied by the system config
|
||||
ValueDenyName,
|
||||
// What about something like this for unique errors?
|
||||
// Credential Update Errors
|
||||
CU0001WebauthnAttestationNotTrusted,
|
||||
CU0002WebauthnRegistrationError,
|
||||
// ValueSet errors
|
||||
VS0001IncomingReplSshPublicKey,
|
||||
// Value Errors
|
||||
VL0001ValueSshPublicKeyString,
|
||||
// SCIM
|
||||
SC0001IncomingSshPublicKey,
|
||||
// Migration
|
||||
MG0001InvalidReMigrationLevel,
|
||||
MG0002RaiseDomainLevelExceedsMaximum,
|
||||
MG0003ServerPhaseInvalidForMigration,
|
||||
}
|
||||
|
||||
impl PartialEq for OperationError {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// We do this to avoid InvalidPassword being checked as it's not
|
||||
// derive PartialEq. Generally we only use the PartialEq for TESTING
|
||||
// anyway.
|
||||
std::mem::discriminant(self) == std::mem::discriminant(other)
|
||||
}
|
||||
}
|
|
@ -1,12 +1,29 @@
|
|||
//! Kanidm internal elements
|
||||
//!
|
||||
//! Items defined in this module *may* change between releases without notice.
|
||||
|
||||
use crate::constants::{
|
||||
CONTENT_TYPE_GIF, CONTENT_TYPE_JPG, CONTENT_TYPE_PNG, CONTENT_TYPE_SVG, CONTENT_TYPE_WEBP,
|
||||
};
|
||||
use crate::v1::ApiTokenPurpose;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
mod credupdate;
|
||||
mod error;
|
||||
mod raw;
|
||||
mod token;
|
||||
|
||||
pub use self::credupdate::*;
|
||||
pub use self::error::*;
|
||||
pub use self::raw::*;
|
||||
pub use self::token::*;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
/// This is a description of a linked or connected application for a user. This is
|
||||
/// used in the UI to render applications on the dashboard for a user to access.
|
||||
|
@ -20,15 +37,40 @@ pub enum AppLink {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct ScimSyncToken {
|
||||
// uuid of the token?
|
||||
pub token_id: Uuid,
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
pub issued_at: time::OffsetDateTime,
|
||||
#[serde(default)]
|
||||
pub purpose: ApiTokenPurpose,
|
||||
#[derive(TryFromPrimitive)]
|
||||
#[repr(u16)]
|
||||
pub enum UiHint {
|
||||
ExperimentalFeatures = 0,
|
||||
PosixAccount = 1,
|
||||
CredentialUpdate = 2,
|
||||
SynchronisedAccount = 3,
|
||||
}
|
||||
|
||||
impl fmt::Display for UiHint {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
UiHint::PosixAccount => write!(f, "PosixAccount"),
|
||||
UiHint::CredentialUpdate => write!(f, "CredentialUpdate"),
|
||||
UiHint::ExperimentalFeatures => write!(f, "ExperimentalFeatures"),
|
||||
UiHint::SynchronisedAccount => write!(f, "SynchronisedAccount"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for UiHint {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"CredentialUpdate" => Ok(UiHint::CredentialUpdate),
|
||||
"PosixAccount" => Ok(UiHint::PosixAccount),
|
||||
"ExperimentalFeatures" => Ok(UiHint::ExperimentalFeatures),
|
||||
"SynchronisedAccount" => Ok(UiHint::SynchronisedAccount),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// State machine states and transitions for the identity verification system feature!
|
113
proto/src/internal/raw.rs
Normal file
113
proto/src/internal/raw.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::v1::Entry;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Filter {
|
||||
// This is attr - value
|
||||
#[serde(alias = "Eq")]
|
||||
Eq(String, String),
|
||||
#[serde(alias = "Cnt")]
|
||||
Cnt(String, String),
|
||||
#[serde(alias = "Pres")]
|
||||
Pres(String),
|
||||
#[serde(alias = "Or")]
|
||||
Or(Vec<Filter>),
|
||||
#[serde(alias = "And")]
|
||||
And(Vec<Filter>),
|
||||
#[serde(alias = "AndNot")]
|
||||
AndNot(Box<Filter>),
|
||||
#[serde(rename = "self", alias = "Self")]
|
||||
SelfUuid,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Modify {
|
||||
Present(String, String),
|
||||
Removed(String, String),
|
||||
Purged(String),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
|
||||
pub struct ModifyList {
|
||||
pub mods: Vec<Modify>,
|
||||
}
|
||||
|
||||
impl ModifyList {
|
||||
pub fn new_list(mods: Vec<Modify>) -> Self {
|
||||
ModifyList { mods }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SearchRequest {
|
||||
pub filter: Filter,
|
||||
}
|
||||
|
||||
impl SearchRequest {
|
||||
pub fn new(filter: Filter) -> Self {
|
||||
SearchRequest { filter }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SearchResponse {
|
||||
pub entries: Vec<Entry>,
|
||||
}
|
||||
|
||||
impl SearchResponse {
|
||||
pub fn new(entries: Vec<Entry>) -> Self {
|
||||
SearchResponse { entries }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct CreateRequest {
|
||||
pub entries: Vec<Entry>,
|
||||
}
|
||||
|
||||
impl CreateRequest {
|
||||
pub fn new(entries: Vec<Entry>) -> Self {
|
||||
CreateRequest { entries }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct DeleteRequest {
|
||||
pub filter: Filter,
|
||||
}
|
||||
|
||||
impl DeleteRequest {
|
||||
pub fn new(filter: Filter) -> Self {
|
||||
DeleteRequest { filter }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ModifyRequest {
|
||||
// Probably needs a modlist?
|
||||
pub filter: Filter,
|
||||
pub modlist: ModifyList,
|
||||
}
|
||||
|
||||
impl ModifyRequest {
|
||||
pub fn new(filter: Filter, modlist: ModifyList) -> Self {
|
||||
ModifyRequest { filter, modlist }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Filter as ProtoFilter;
|
||||
use crate::constants::ATTR_CLASS;
|
||||
|
||||
#[test]
|
||||
fn test_protofilter_simple() {
|
||||
let pf: ProtoFilter = ProtoFilter::Pres(ATTR_CLASS.to_string());
|
||||
|
||||
println!("{:?}", serde_json::to_string(&pf).expect("JSON failure"));
|
||||
}
|
||||
}
|
200
proto/src/internal/token.rs
Normal file
200
proto/src/internal/token.rs
Normal file
|
@ -0,0 +1,200 @@
|
|||
use super::UiHint;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
use time::OffsetDateTime;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use serde_with::skip_serializing_none;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum UatPurpose {
|
||||
ReadOnly,
|
||||
ReadWrite {
|
||||
/// If none, there is no expiry, and this is always rw. If there is
|
||||
/// an expiry, check that the current time < expiry.
|
||||
#[serde(with = "time::serde::timestamp::option")]
|
||||
expiry: Option<time::OffsetDateTime>,
|
||||
},
|
||||
}
|
||||
|
||||
/// The currently authenticated user, and any required metadata for them
|
||||
/// to properly authorise them. This is similar in nature to oauth and the krb
|
||||
/// PAC/PAD structures. This information is transparent to clients and CAN
|
||||
/// be parsed by them!
|
||||
///
|
||||
/// This structure and how it works will *very much* change over time from this
|
||||
/// point onward! This means on updates, that sessions will invalidate in many
|
||||
/// cases.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[skip_serializing_none]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct UserAuthToken {
|
||||
pub session_id: Uuid,
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
pub issued_at: time::OffsetDateTime,
|
||||
/// If none, there is no expiry, and this is always valid. If there is
|
||||
/// an expiry, check that the current time < expiry.
|
||||
#[serde(with = "time::serde::timestamp::option")]
|
||||
pub expiry: Option<time::OffsetDateTime>,
|
||||
pub purpose: UatPurpose,
|
||||
pub uuid: Uuid,
|
||||
pub displayname: String,
|
||||
pub spn: String,
|
||||
pub mail_primary: Option<String>,
|
||||
pub ui_hints: BTreeSet<UiHint>,
|
||||
|
||||
pub limit_search_max_results: Option<u64>,
|
||||
pub limit_search_max_filter_test: Option<u64>,
|
||||
}
|
||||
|
||||
impl fmt::Display for UserAuthToken {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "spn: {}", self.spn)?;
|
||||
writeln!(f, "uuid: {}", self.uuid)?;
|
||||
writeln!(f, "display: {}", self.displayname)?;
|
||||
if let Some(exp) = self.expiry {
|
||||
writeln!(f, "expiry: {}", exp)?;
|
||||
} else {
|
||||
writeln!(f, "expiry: -")?;
|
||||
}
|
||||
match &self.purpose {
|
||||
UatPurpose::ReadOnly => writeln!(f, "purpose: read only")?,
|
||||
UatPurpose::ReadWrite {
|
||||
expiry: Some(expiry),
|
||||
} => writeln!(f, "purpose: read write (expiry: {})", expiry)?,
|
||||
UatPurpose::ReadWrite { expiry: None } => {
|
||||
writeln!(f, "purpose: read write (expiry: none)")?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for UserAuthToken {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.session_id == other.session_id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for UserAuthToken {}
|
||||
|
||||
impl UserAuthToken {
|
||||
pub fn name(&self) -> &str {
|
||||
self.spn.split_once('@').map(|x| x.0).unwrap_or(&self.spn)
|
||||
}
|
||||
|
||||
/// Show if the uat at a current point in time has active read-write
|
||||
/// capabilities.
|
||||
pub fn purpose_readwrite_active(&self, ct: time::OffsetDateTime) -> bool {
|
||||
match self.purpose {
|
||||
UatPurpose::ReadWrite { expiry: Some(exp) } => ct < exp,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ApiTokenPurpose {
|
||||
#[default]
|
||||
ReadOnly,
|
||||
ReadWrite,
|
||||
Synchronise,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct ApiToken {
|
||||
// The account this is associated with.
|
||||
pub account_id: Uuid,
|
||||
pub token_id: Uuid,
|
||||
pub label: String,
|
||||
#[serde(with = "time::serde::timestamp::option")]
|
||||
pub expiry: Option<time::OffsetDateTime>,
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
pub issued_at: time::OffsetDateTime,
|
||||
// Defaults to ReadOnly if not present
|
||||
#[serde(default)]
|
||||
pub purpose: ApiTokenPurpose,
|
||||
}
|
||||
|
||||
impl fmt::Display for ApiToken {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "account_id: {}", self.account_id)?;
|
||||
writeln!(f, "token_id: {}", self.token_id)?;
|
||||
writeln!(f, "label: {}", self.label)?;
|
||||
writeln!(f, "issued at: {}", self.issued_at)?;
|
||||
if let Some(expiry) = self.expiry {
|
||||
// if this fails we're in trouble!
|
||||
#[allow(clippy::expect_used)]
|
||||
let expiry_str = expiry
|
||||
.to_offset(
|
||||
time::UtcOffset::local_offset_at(OffsetDateTime::UNIX_EPOCH)
|
||||
.unwrap_or(time::UtcOffset::UTC),
|
||||
)
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.expect("Failed to format timestamp to RFC3339");
|
||||
writeln!(f, "token expiry: {}", expiry_str)
|
||||
} else {
|
||||
writeln!(f, "token expiry: never")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ApiToken {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.token_id == other.token_id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ApiToken {}
|
||||
|
||||
// This is similar to uat, but omits claims (they have no role in radius), and adds
|
||||
// the radius secret field.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct RadiusAuthToken {
|
||||
pub name: String,
|
||||
pub displayname: String,
|
||||
pub uuid: String,
|
||||
pub secret: String,
|
||||
pub groups: Vec<Group>,
|
||||
}
|
||||
|
||||
impl fmt::Display for RadiusAuthToken {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "name: {}", self.name)?;
|
||||
writeln!(f, "displayname: {}", self.displayname)?;
|
||||
writeln!(f, "uuid: {}", self.uuid)?;
|
||||
writeln!(f, "secret: {}", self.secret)?;
|
||||
self.groups
|
||||
.iter()
|
||||
.try_for_each(|g| writeln!(f, "group: {}", g))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct ScimSyncToken {
|
||||
// uuid of the token?
|
||||
pub token_id: Uuid,
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
pub issued_at: time::OffsetDateTime,
|
||||
#[serde(default)]
|
||||
pub purpose: ApiTokenPurpose,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct Group {
|
||||
pub spn: String,
|
||||
pub uuid: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for Group {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "[ spn: {}, ", self.spn)?;
|
||||
write!(f, "uuid: {} ]", self.uuid)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,14 @@
|
|||
//! Kanidm JSON protocol definitions
|
||||
//!
|
||||
//! This library defines the elements that are used by Kanidm's http APIs.
|
||||
//! Each module has different support levels which define the projects policy
|
||||
//! on change for the module.
|
||||
|
||||
#![deny(warnings)]
|
||||
#![warn(unused_extern_crates)]
|
||||
// #![warn(missing_docs)]
|
||||
#![deny(clippy::todo)]
|
||||
#![deny(clippy::unimplemented)]
|
||||
#![deny(clippy::unwrap_used)]
|
||||
#![deny(clippy::expect_used)]
|
||||
#![deny(clippy::panic)]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Oauth2 RFC protocol definitions.
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
|
@ -20,6 +22,8 @@ pub struct PkceRequest {
|
|||
pub code_challenge_method: CodeChallengeMethod,
|
||||
}
|
||||
|
||||
/// An OAuth2 client redirects to the authorisation server with Authorisation Request
|
||||
/// parameters.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct AuthorisationRequest {
|
||||
|
@ -40,6 +44,8 @@ pub struct AuthorisationRequest {
|
|||
pub unknown_keys: BTreeMap<String, serde_json::value::Value>,
|
||||
}
|
||||
|
||||
/// An OIDC client redirects to the authorisation server with Authorisation Request
|
||||
/// parameters.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct AuthorisationRequestOidc {
|
||||
|
@ -53,8 +59,9 @@ pub struct AuthorisationRequestOidc {
|
|||
pub acr: Option<String>,
|
||||
}
|
||||
|
||||
/// When we request to authorise, it can either prompt us for consent,
|
||||
/// or it can immediately be granted due the past grant.
|
||||
/// In response to an Authorisation request, the user may be prompted to consent to the
|
||||
/// scopes requested by the OAuth2 client. If they have previously consented, they will
|
||||
/// immediately proceed.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum AuthorisationResponse {
|
||||
ConsentRequested {
|
||||
|
@ -74,7 +81,6 @@ pub enum AuthorisationResponse {
|
|||
|
||||
#[serde_as]
|
||||
#[skip_serializing_none]
|
||||
// this is the equivalent of serde(skip_serializing_if = "Option::is_none") applied to ALL the options
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(tag = "grant_type", rename_all = "snake_case")]
|
||||
pub enum GrantTypeReq {
|
||||
|
@ -96,6 +102,7 @@ pub enum GrantTypeReq {
|
|||
},
|
||||
}
|
||||
|
||||
/// An Access Token request. This requires a set of grant-type parameters to satisfy the request.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AccessTokenRequest {
|
||||
|
@ -117,43 +124,45 @@ impl From<GrantTypeReq> for AccessTokenRequest {
|
|||
}
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct TokenRevokeRequest {
|
||||
pub token: String,
|
||||
/// Generally not needed. See:
|
||||
/// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2>
|
||||
pub token_type_hint: Option<String>,
|
||||
}
|
||||
|
||||
// The corresponding Response to a revoke request is empty body with 200.
|
||||
|
||||
/// The
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AccessTokenResponse {
|
||||
// Could be Base64UrlSafeData
|
||||
pub access_token: String,
|
||||
// Enum?
|
||||
pub token_type: String,
|
||||
// seconds.
|
||||
/// Expiration relative to `now` in seconds.
|
||||
pub expires_in: u32,
|
||||
pub refresh_token: Option<String>,
|
||||
/// Space separated list of scopes that were approved, if this differs from the
|
||||
/// original request.
|
||||
pub scope: Option<String>,
|
||||
/// Oidc puts the token here.
|
||||
/// If the `openid` scope was requested, an `id_token` may be present in the response.
|
||||
pub id_token: Option<String>,
|
||||
}
|
||||
|
||||
/// Request revocation of an Access or Refresh token. On success the response is OK 200
|
||||
/// with no body.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AccessTokenIntrospectRequest {
|
||||
pub struct TokenRevokeRequest {
|
||||
pub token: String,
|
||||
/// Generally not needed. See:
|
||||
/// Not required for Kanidm.
|
||||
/// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2>
|
||||
pub token_type_hint: Option<String>,
|
||||
}
|
||||
|
||||
/// Request to introspect the identity of the account associated to a token.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AccessTokenIntrospectRequest {
|
||||
pub token: String,
|
||||
/// Not required for Kanidm.
|
||||
/// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2>
|
||||
pub token_type_hint: Option<String>,
|
||||
}
|
||||
|
||||
/// Response to an introspection request. If the token is inactive or revoked, only
|
||||
/// `active` will be set to the value of `false`.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AccessTokenIntrospectResponse {
|
||||
|
@ -235,8 +244,9 @@ pub enum PkceAlg {
|
|||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
// WE REFUSE TO SUPPORT NONE. DONT EVEN ASK. IT WON'T HAPPEN.
|
||||
/// Algorithms supported for token signatures. Prefers `ES256`
|
||||
pub enum IdTokenSignAlg {
|
||||
// WE REFUSE TO SUPPORT NONE. DONT EVEN ASK. IT WON'T HAPPEN.
|
||||
ES256,
|
||||
RS256,
|
||||
}
|
||||
|
@ -292,9 +302,10 @@ fn require_request_uri_parameter_supported_default() -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
/// The response to an OpenID connect discovery request
|
||||
/// <https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata>
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
||||
pub struct OidcDiscoveryResponse {
|
||||
pub issuer: Url,
|
||||
pub authorization_endpoint: Url,
|
||||
|
@ -354,9 +365,9 @@ pub struct OidcDiscoveryResponse {
|
|||
pub code_challenge_methods_supported: Vec<PkceAlg>,
|
||||
}
|
||||
|
||||
/// The response to an OAuth2 rfc8414 metadata request
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
||||
pub struct Oauth2Rfc8414MetadataResponse {
|
||||
pub issuer: Url,
|
||||
pub authorization_endpoint: Url,
|
||||
|
|
3
proto/src/scim_v1/mod.rs
Normal file
3
proto/src/scim_v1/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod synch;
|
||||
|
||||
pub use self::synch::*;
|
|
@ -60,11 +60,14 @@ pub const SCIM_DIGITS: &str = "digits";
|
|||
pub const SCIM_SECRET: &str = "secret";
|
||||
pub const SCIM_STEP: &str = "step";
|
||||
|
||||
pub const SCIM_SCHEMA_SYNC: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:";
|
||||
pub const SCIM_SCHEMA_SYNC_PERSON: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:person";
|
||||
pub const SCIM_SCHEMA_SYNC_ACCOUNT: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:account";
|
||||
pub const SCIM_SCHEMA_SYNC_1: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:";
|
||||
pub const SCIM_SCHEMA_SYNC_ACCOUNT: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:account";
|
||||
pub const SCIM_SCHEMA_SYNC_GROUP: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:group";
|
||||
pub const SCIM_SCHEMA_SYNC_PERSON: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:person";
|
||||
pub const SCIM_SCHEMA_SYNC_POSIXACCOUNT: &str =
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:posixaccount";
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixaccount";
|
||||
pub const SCIM_SCHEMA_SYNC_POSIXGROUP: &str =
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixgroup";
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct ScimTotp {
|
||||
|
@ -206,9 +209,6 @@ impl Into<ScimEntry> for ScimSyncPerson {
|
|||
}
|
||||
}
|
||||
|
||||
pub const SCIM_SCHEMA_SYNC_GROUP: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:group";
|
||||
pub const SCIM_SCHEMA_SYNC_POSIXGROUP: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:posixgroup";
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct ScimExternalMember {
|
||||
pub external_id: String,
|
1321
proto/src/v1.rs
1321
proto/src/v1.rs
File diff suppressed because it is too large
Load diff
189
proto/src/v1/auth.rs
Normal file
189
proto/src/v1/auth.rs
Normal file
|
@ -0,0 +1,189 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use webauthn_rs_proto::PublicKeyCredential;
|
||||
use webauthn_rs_proto::RequestChallengeResponse;
|
||||
|
||||
/// Authentication to Kanidm is a stepped process.
|
||||
///
|
||||
/// The session is fist initialised with the requested username.
|
||||
///
|
||||
/// In response the list of supported authentication mechanisms is provided.
|
||||
///
|
||||
/// The user chooses the authentication mechanism to proceed with.
|
||||
///
|
||||
/// The server responds with a challenge that the user provides a credential
|
||||
/// to satisfy. This challenge and response process continues until a credential
|
||||
/// fails to validate, an error occurs, or successful authentication is complete.
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthStep {
|
||||
/// Initialise a new authentication session
|
||||
Init(String),
|
||||
/// Initialise a new authentication session with extra flags
|
||||
/// for requesting different types of session tokens or
|
||||
/// immediate access to privileges.
|
||||
Init2 {
|
||||
username: String,
|
||||
issue: AuthIssueSession,
|
||||
#[serde(default)]
|
||||
/// If true, the session will have r/w access.
|
||||
privileged: bool,
|
||||
},
|
||||
/// Request the named authentication mechanism to proceed
|
||||
Begin(AuthMech),
|
||||
/// Provide a credential in response to a challenge
|
||||
Cred(AuthCredential),
|
||||
}
|
||||
|
||||
/// The response to an AuthStep request.
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthState {
|
||||
/// You need to select how you want to proceed.
|
||||
Choose(Vec<AuthMech>),
|
||||
/// Continue to auth, allowed mechanisms/challenges listed.
|
||||
Continue(Vec<AuthAllowed>),
|
||||
/// Something was bad, your session is terminated and no cookie.
|
||||
Denied(String),
|
||||
/// Everything is good, your bearer token has been issued and is within.
|
||||
Success(String),
|
||||
}
|
||||
|
||||
/// The credential challenge provided by a user.
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthCredential {
|
||||
Anonymous,
|
||||
Password(String),
|
||||
Totp(u32),
|
||||
SecurityKey(Box<PublicKeyCredential>),
|
||||
BackupCode(String),
|
||||
// Should this just be discoverable?
|
||||
Passkey(Box<PublicKeyCredential>),
|
||||
}
|
||||
|
||||
impl fmt::Debug for AuthCredential {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
AuthCredential::Anonymous => write!(fmt, "Anonymous"),
|
||||
AuthCredential::Password(_) => write!(fmt, "Password(_)"),
|
||||
AuthCredential::Totp(_) => write!(fmt, "TOTP(_)"),
|
||||
AuthCredential::SecurityKey(_) => write!(fmt, "SecurityKey(_)"),
|
||||
AuthCredential::BackupCode(_) => write!(fmt, "BackupCode(_)"),
|
||||
AuthCredential::Passkey(_) => write!(fmt, "Passkey(_)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The mechanisms that may proceed in this authentication
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthMech {
|
||||
Anonymous,
|
||||
Password,
|
||||
PasswordMfa,
|
||||
Passkey,
|
||||
}
|
||||
|
||||
impl PartialEq for AuthMech {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
std::mem::discriminant(self) == std::mem::discriminant(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AuthMech {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
AuthMech::Anonymous => write!(f, "Anonymous (no credentials)"),
|
||||
AuthMech::Password => write!(f, "Password"),
|
||||
AuthMech::PasswordMfa => write!(f, "TOTP/Backup Code and Password"),
|
||||
AuthMech::Passkey => write!(f, "Passkey"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of session that should be issued to the client.
|
||||
#[derive(Debug, Serialize, Deserialize, Copy, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthIssueSession {
|
||||
// Previously supported other types beside token.
|
||||
Token,
|
||||
}
|
||||
|
||||
/// A request for the next step of an authentication.
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct AuthRequest {
|
||||
pub step: AuthStep,
|
||||
}
|
||||
|
||||
/// A challenge containing the list of allowed authentication types
|
||||
/// that can satisfy the next step. These may have inner types with
|
||||
/// required context.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AuthAllowed {
|
||||
Anonymous,
|
||||
BackupCode,
|
||||
Password,
|
||||
Totp,
|
||||
SecurityKey(RequestChallengeResponse),
|
||||
Passkey(RequestChallengeResponse),
|
||||
}
|
||||
|
||||
impl PartialEq for AuthAllowed {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
std::mem::discriminant(self) == std::mem::discriminant(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AuthAllowed> for u8 {
|
||||
fn from(a: &AuthAllowed) -> u8 {
|
||||
match a {
|
||||
AuthAllowed::Anonymous => 0,
|
||||
AuthAllowed::Password => 1,
|
||||
AuthAllowed::BackupCode => 2,
|
||||
AuthAllowed::Totp => 3,
|
||||
AuthAllowed::Passkey(_) => 4,
|
||||
AuthAllowed::SecurityKey(_) => 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for AuthAllowed {}
|
||||
|
||||
impl Ord for AuthAllowed {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
let self_ord: u8 = self.into();
|
||||
let other_ord: u8 = other.into();
|
||||
self_ord.cmp(&other_ord)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for AuthAllowed {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AuthAllowed {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
AuthAllowed::Anonymous => write!(f, "Anonymous (no credentials)"),
|
||||
AuthAllowed::Password => write!(f, "Password"),
|
||||
AuthAllowed::BackupCode => write!(f, "Backup Code"),
|
||||
AuthAllowed::Totp => write!(f, "TOTP"),
|
||||
AuthAllowed::SecurityKey(_) => write!(f, "Security Token"),
|
||||
AuthAllowed::Passkey(_) => write!(f, "Passkey"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct AuthResponse {
|
||||
pub sessionid: Uuid,
|
||||
pub state: AuthState,
|
||||
}
|
149
proto/src/v1/mod.rs
Normal file
149
proto/src/v1/mod.rs
Normal file
|
@ -0,0 +1,149 @@
|
|||
//! Kanidm Version 1
|
||||
//!
|
||||
//! Items defined in this module will remain stable, or change in ways that are forward
|
||||
//! compatible with newer releases.
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
mod auth;
|
||||
mod unix;
|
||||
|
||||
pub use self::auth::*;
|
||||
pub use self::unix::*;
|
||||
|
||||
/// The type of Account in use.
|
||||
#[derive(Clone, Copy, Debug, ToSchema)]
|
||||
pub enum AccountType {
|
||||
Person,
|
||||
ServiceAccount,
|
||||
}
|
||||
|
||||
impl ToString for AccountType {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
AccountType::Person => "person".to_string(),
|
||||
AccountType::ServiceAccount => "service_account".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== higher level types ===== */
|
||||
// These are all types that are conceptually layers on top of entry and
|
||||
// friends. They allow us to process more complex requests and provide
|
||||
// domain specific fields for the purposes of IDM, over the normal
|
||||
// entry/ava/filter types. These related deeply to schema.
|
||||
|
||||
/// The current purpose of a User Auth Token. It may be read-only, read-write
|
||||
/// or privilige capable (able to step up to read-write after re-authentication).
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum UatPurposeStatus {
|
||||
ReadOnly,
|
||||
ReadWrite,
|
||||
PrivilegeCapable,
|
||||
}
|
||||
|
||||
/// The expiry of the User Auth Token.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum UatStatusState {
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
ExpiresAt(time::OffsetDateTime),
|
||||
NeverExpires,
|
||||
Revoked,
|
||||
}
|
||||
|
||||
impl fmt::Display for UatStatusState {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
UatStatusState::ExpiresAt(odt) => write!(f, "expires at {}", odt),
|
||||
UatStatusState::NeverExpires => write!(f, "never expires"),
|
||||
UatStatusState::Revoked => write!(f, "revoked"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of a User Auth Token
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct UatStatus {
|
||||
pub account_id: Uuid,
|
||||
pub session_id: Uuid,
|
||||
pub state: UatStatusState,
|
||||
#[serde(with = "time::serde::timestamp")]
|
||||
pub issued_at: time::OffsetDateTime,
|
||||
pub purpose: UatPurposeStatus,
|
||||
}
|
||||
|
||||
impl fmt::Display for UatStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "account_id: {}", self.account_id)?;
|
||||
writeln!(f, "session_id: {}", self.session_id)?;
|
||||
writeln!(f, "state: {}", self.state)?;
|
||||
writeln!(f, "issued_at: {}", self.issued_at)?;
|
||||
match &self.purpose {
|
||||
UatPurposeStatus::ReadOnly => writeln!(f, "purpose: read only")?,
|
||||
UatPurposeStatus::ReadWrite => writeln!(f, "purpose: read write")?,
|
||||
UatPurposeStatus::PrivilegeCapable => writeln!(f, "purpose: privilege capable")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A request to generate a new API token for a service account
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct ApiTokenGenerate {
|
||||
pub label: String,
|
||||
#[serde(with = "time::serde::timestamp::option")]
|
||||
pub expiry: Option<time::OffsetDateTime>,
|
||||
pub read_write: bool,
|
||||
}
|
||||
|
||||
/* ===== low level proto types ===== */
|
||||
|
||||
/// A limited view of an entry in Kanidm.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default, ToSchema)]
|
||||
pub struct Entry {
|
||||
pub attrs: BTreeMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Entry {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "---")?;
|
||||
self.attrs
|
||||
.iter()
|
||||
.try_for_each(|(k, vs)| vs.iter().try_for_each(|v| writeln!(f, "{}: {}", k, v)))
|
||||
}
|
||||
}
|
||||
|
||||
/// A response to a whoami request
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, ToSchema)]
|
||||
pub struct WhoamiResponse {
|
||||
// Should we just embed the entry? Or destructure it?
|
||||
pub youare: Entry,
|
||||
}
|
||||
|
||||
impl WhoamiResponse {
|
||||
pub fn new(youare: Entry) -> Self {
|
||||
WhoamiResponse { youare }
|
||||
}
|
||||
}
|
||||
|
||||
// Simple string value provision.
|
||||
#[derive(Debug, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SingleStringRequest {
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl SingleStringRequest {
|
||||
pub fn new(s: String) -> Self {
|
||||
SingleStringRequest { value: s }
|
||||
}
|
||||
}
|
80
proto/src/v1/unix.rs
Normal file
80
proto/src/v1/unix.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use serde_with::skip_serializing_none;
|
||||
|
||||
use crate::constants::{ATTR_GROUP, ATTR_LDAP_SSHPUBLICKEY};
|
||||
|
||||
/// A token representing the details of a unix group
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct UnixGroupToken {
|
||||
pub name: String,
|
||||
pub spn: String,
|
||||
pub uuid: Uuid,
|
||||
pub gidnumber: u32,
|
||||
}
|
||||
|
||||
impl fmt::Display for UnixGroupToken {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "[ spn: {}, ", self.spn)?;
|
||||
write!(f, "gidnumber: {} ", self.gidnumber)?;
|
||||
write!(f, "name: {}, ", self.name)?;
|
||||
write!(f, "uuid: {} ]", self.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
/// Request addition of unix attributes to a group.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct GroupUnixExtend {
|
||||
pub gidnumber: Option<u32>,
|
||||
}
|
||||
|
||||
/// A token representing the details of a unix user
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct UnixUserToken {
|
||||
pub name: String,
|
||||
pub spn: String,
|
||||
pub displayname: String,
|
||||
pub gidnumber: u32,
|
||||
pub uuid: Uuid,
|
||||
pub shell: Option<String>,
|
||||
pub groups: Vec<UnixGroupToken>,
|
||||
pub sshkeys: Vec<String>,
|
||||
// The default value of bool is false.
|
||||
#[serde(default)]
|
||||
pub valid: bool,
|
||||
}
|
||||
|
||||
impl fmt::Display for UnixUserToken {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "---")?;
|
||||
writeln!(f, "spn: {}", self.spn)?;
|
||||
writeln!(f, "name: {}", self.name)?;
|
||||
writeln!(f, "displayname: {}", self.displayname)?;
|
||||
writeln!(f, "uuid: {}", self.uuid)?;
|
||||
match &self.shell {
|
||||
Some(s) => writeln!(f, "shell: {}", s)?,
|
||||
None => writeln!(f, "shell: <none>")?,
|
||||
}
|
||||
self.sshkeys
|
||||
.iter()
|
||||
.try_for_each(|s| writeln!(f, "{}: {}", ATTR_LDAP_SSHPUBLICKEY, s))?;
|
||||
self.groups
|
||||
.iter()
|
||||
.try_for_each(|g| writeln!(f, "{}: {}", ATTR_GROUP, g))
|
||||
}
|
||||
}
|
||||
|
||||
/// Request addition of unix attributes to an account
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct AccountUnixExtend {
|
||||
pub gidnumber: Option<u32>,
|
||||
// TODO: rename shell to loginshell everywhere we can find
|
||||
/// The internal attribute is "loginshell" but we use shell in the API currently
|
||||
#[serde(alias = "loginshell")]
|
||||
pub shell: Option<String>,
|
||||
}
|
|
@ -54,7 +54,6 @@ toml = { workspace = true }
|
|||
tower = { version = "0.4.13", features = ["tokio-stream", "tracing"] }
|
||||
tower-http = { version = "0.4.4", features = [
|
||||
"compression-gzip",
|
||||
"compression-zstd",
|
||||
"fs",
|
||||
"tokio",
|
||||
"trace",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
fn main() {
|
||||
profiles::apply_profile();
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
|
|
|
@ -4,11 +4,14 @@ use std::net::IpAddr;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::internal::{AppLink, IdentifyUserRequest, IdentifyUserResponse, ImageValue};
|
||||
use kanidm_proto::internal::{
|
||||
ApiToken, AppLink, BackupCodesView, CURequest, CUSessionToken, CUStatus, CredentialStatus,
|
||||
IdentifyUserRequest, IdentifyUserResponse, ImageValue, OperationError, RadiusAuthToken,
|
||||
SearchRequest, SearchResponse, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, AuthIssueSession, AuthRequest, BackupCodesView, CURequest, CUSessionToken, CUStatus,
|
||||
CredentialStatus, Entry as ProtoEntry, OperationError, RadiusAuthToken, SearchRequest,
|
||||
SearchResponse, UatStatus, UnixGroupToken, UnixUserToken, UserAuthToken, WhoamiResponse,
|
||||
AuthIssueSession, AuthRequest, Entry as ProtoEntry, UatStatus, UnixGroupToken, UnixUserToken,
|
||||
WhoamiResponse,
|
||||
};
|
||||
use kanidmd_lib::idm::identityverification::{
|
||||
IdentifyUserDisplayCodeEvent, IdentifyUserStartEvent, IdentifyUserSubmitCodeEvent,
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use std::{iter, sync::Arc};
|
||||
|
||||
use kanidm_proto::internal::DomainInfo as ProtoDomainInfo;
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use kanidm_proto::internal::Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin;
|
||||
use kanidm_proto::v1::{
|
||||
AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest,
|
||||
Entry as ProtoEntry, GroupUnixExtend, Modify as ProtoModify, ModifyList as ProtoModifyList,
|
||||
ModifyRequest, OperationError,
|
||||
use kanidm_proto::internal::{
|
||||
CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest,
|
||||
DomainInfo as ProtoDomainInfo, ImageValue, Modify as ProtoModify,
|
||||
ModifyList as ProtoModifyList, ModifyRequest, Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin,
|
||||
OperationError,
|
||||
};
|
||||
use kanidm_proto::v1::{AccountUnixExtend, Entry as ProtoEntry, GroupUnixExtend};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{info, instrument, span, trace, Instrument, Level};
|
||||
use uuid::Uuid;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use axum::{middleware::from_fn, response::Redirect, routing::get, Router};
|
||||
use kanidm_proto::{scim_v1, v1};
|
||||
use kanidm_proto::{internal, scim_v1, v1};
|
||||
use utoipa::{
|
||||
openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme},
|
||||
Modify, OpenApi,
|
||||
|
@ -189,57 +189,56 @@ impl Modify for SecurityAddon {
|
|||
// TODO: can't add Entry/ProtoEntry to schema as this was only recently supported utoipa v3.5.0 doesn't support it - ref <https://github.com/juhaku/utoipa/pull/756/files>
|
||||
// v1::Entry,
|
||||
v1::AccountUnixExtend,
|
||||
v1::ApiToken,
|
||||
internal::ApiToken,
|
||||
v1::ApiTokenGenerate,
|
||||
v1::AuthRequest,
|
||||
v1::AuthResponse,
|
||||
v1::AuthState,
|
||||
v1::BackupCodesView,
|
||||
v1::Claim,
|
||||
v1::CreateRequest,
|
||||
v1::CredentialDetail,
|
||||
v1::CredentialStatus,
|
||||
v1::CUIntentToken,
|
||||
v1::CUSessionToken,
|
||||
v1::CUStatus,
|
||||
v1::DeleteRequest,
|
||||
v1::Group,
|
||||
internal::BackupCodesView,
|
||||
internal::CreateRequest,
|
||||
internal::CredentialDetail,
|
||||
internal::CredentialStatus,
|
||||
internal::CUIntentToken,
|
||||
internal::CUSessionToken,
|
||||
internal::CUStatus,
|
||||
internal::DeleteRequest,
|
||||
internal::Group,
|
||||
v1::GroupUnixExtend,
|
||||
v1::ModifyList,
|
||||
v1::ModifyRequest,
|
||||
v1::PasskeyDetail,
|
||||
v1::RadiusAuthToken,
|
||||
v1::SearchRequest,
|
||||
v1::SearchResponse,
|
||||
internal::ModifyList,
|
||||
internal::ModifyRequest,
|
||||
internal::PasskeyDetail,
|
||||
internal::RadiusAuthToken,
|
||||
internal::SearchRequest,
|
||||
internal::SearchResponse,
|
||||
v1::SingleStringRequest,
|
||||
v1::TotpSecret,
|
||||
v1::TotpAlgo,
|
||||
internal::TotpSecret,
|
||||
internal::TotpAlgo,
|
||||
v1::UatStatus,
|
||||
v1::UnixGroupToken,
|
||||
v1::UnixUserToken,
|
||||
v1::UserAuthToken,
|
||||
internal::UserAuthToken,
|
||||
v1::WhoamiResponse,
|
||||
v1::ApiTokenPurpose,
|
||||
internal::ApiTokenPurpose,
|
||||
v1::AuthStep,
|
||||
v1::AuthIssueSession,
|
||||
v1::AuthMech,
|
||||
v1::AuthCredential,
|
||||
v1::AuthAllowed,
|
||||
v1::CUExtPortal,
|
||||
v1::CURegState,
|
||||
v1::CredentialDetailType,
|
||||
internal::CUExtPortal,
|
||||
internal::CURegState,
|
||||
internal::CredentialDetailType,
|
||||
v1::Entry,
|
||||
v1::Filter,
|
||||
v1::Modify,
|
||||
internal::Filter,
|
||||
internal::Modify,
|
||||
v1::UatStatusState,
|
||||
v1::UatPurposeStatus,
|
||||
v1::UatPurpose,
|
||||
v1::OperationError,
|
||||
v1::SchemaError,
|
||||
v1::PluginError,
|
||||
v1::PasswordFeedback,
|
||||
internal::UatPurpose,
|
||||
internal::OperationError,
|
||||
internal::SchemaError,
|
||||
internal::PluginError,
|
||||
internal::PasswordFeedback,
|
||||
|
||||
kanidm_proto::internal::IdentifyUserRequest,
|
||||
internal::IdentifyUserRequest,
|
||||
// terrible workaround for other things
|
||||
response_schema::CreationChallengeResponse,
|
||||
// terrible workaround for other things
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use axum::http::header::ACCESS_CONTROL_ALLOW_ORIGIN;
|
||||
use axum::http::{HeaderValue, StatusCode};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// The web app's top level error type, this takes an `OperationError` and converts it into a HTTP response.
|
||||
|
|
|
@ -12,13 +12,15 @@ use serde::{Deserialize, Serialize};
|
|||
use std::net::IpAddr;
|
||||
use uuid::Uuid;
|
||||
|
||||
use kanidm_proto::internal::{AppLink, IdentifyUserRequest, IdentifyUserResponse};
|
||||
use kanidm_proto::internal::{
|
||||
ApiToken, AppLink, CUIntentToken, CURequest, CUSessionToken, CUStatus, CreateRequest,
|
||||
CredentialStatus, DeleteRequest, IdentifyUserRequest, IdentifyUserResponse, ModifyRequest,
|
||||
RadiusAuthToken, SearchRequest, SearchResponse, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::v1::{
|
||||
AccountUnixExtend, ApiToken, ApiTokenGenerate, AuthIssueSession, AuthRequest, AuthResponse,
|
||||
AuthState as ProtoAuthState, CUIntentToken, CURequest, CUSessionToken, CUStatus, CreateRequest,
|
||||
CredentialStatus, DeleteRequest, Entry as ProtoEntry, GroupUnixExtend, ModifyRequest,
|
||||
RadiusAuthToken, SearchRequest, SearchResponse, SingleStringRequest, UatStatus, UnixGroupToken,
|
||||
UnixUserToken, UserAuthToken, WhoamiResponse,
|
||||
AccountUnixExtend, ApiTokenGenerate, AuthIssueSession, AuthRequest, AuthResponse,
|
||||
AuthState as ProtoAuthState, Entry as ProtoEntry, GroupUnixExtend, SingleStringRequest,
|
||||
UatStatus, UnixGroupToken, UnixUserToken, WhoamiResponse,
|
||||
};
|
||||
use kanidmd_lib::idm::event::AuthResult;
|
||||
use kanidmd_lib::idm::AuthState;
|
||||
|
|
|
@ -40,7 +40,7 @@ use std::sync::Arc;
|
|||
|
||||
use crate::utils::touch_file_or_quit;
|
||||
use compact_jwt::JwsHs256Signer;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use kanidmd_lib::be::{Backend, BackendConfig, BackendTransaction};
|
||||
use kanidmd_lib::idm::ldap::LdapServer;
|
||||
use kanidmd_lib::prelude::*;
|
||||
|
|
|
@ -11,6 +11,9 @@ include!("src/opt.rs");
|
|||
fn main() {
|
||||
profiles::apply_profile();
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=OUT_DIR");
|
||||
println!("cargo:rerun-if-changed=src/opt.rs");
|
||||
let outdir = match env::var_os("OUT_DIR") {
|
||||
None => return,
|
||||
Some(outdir) => outdir,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// include!("src/lib/audit_loglevel.rs");
|
||||
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=DEP_OPENSSL_VERSION_NUMBER");
|
||||
if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
|
||||
let version = u64::from_str_radix(&v, 16).unwrap();
|
||||
|
||||
|
@ -16,6 +16,7 @@ fn main() {
|
|||
profiles::apply_profile();
|
||||
|
||||
// check we don't have duplicate UUIDs
|
||||
println!("cargo:rerun-if-changed=src/constants/uuids.rs");
|
||||
let uuid_filename = format!(
|
||||
"{}/{}",
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
|
|
|
@ -10,7 +10,7 @@ use concread::cowcell::*;
|
|||
use hashbrown::HashMap;
|
||||
use idlset::v2::IDLBitRange;
|
||||
use idlset::AndNot;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use kanidm_proto::internal::{ConsistencyError, OperationError};
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use super::keystorage::{KeyHandle, KeyHandleId};
|
|||
// use crate::valueset;
|
||||
use hashbrown::HashMap;
|
||||
use idlset::v2::IDLBitRange;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use kanidm_proto::internal::{ConsistencyError, OperationError};
|
||||
use rusqlite::vtab::array::Array;
|
||||
use rusqlite::{Connection, OpenFlags, OptionalExtension};
|
||||
use uuid::Uuid;
|
||||
|
|
|
@ -14,7 +14,7 @@ use concread::cowcell::*;
|
|||
use hashbrown::{HashMap as Map, HashSet};
|
||||
use idlset::v2::IDLBitRange;
|
||||
use idlset::AndNot;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
use kanidm_proto::internal::{ConsistencyError, OperationError};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use tracing::{trace, trace_span};
|
||||
use uuid::Uuid;
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::constants::uuids::*;
|
|||
use crate::entry::EntryInitNew;
|
||||
use crate::prelude::*;
|
||||
use crate::value::Value;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
|
||||
lazy_static! {
|
||||
/// either recycled or tombstone
|
||||
|
|
|
@ -10,7 +10,8 @@ use crate::idm::account::Account;
|
|||
use crate::value::PartialValue;
|
||||
use crate::value::Value;
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::v1::{AccountType, OperationError};
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use kanidm_proto::v1::AccountType;
|
||||
|
||||
#[cfg(test)]
|
||||
use uuid::uuid;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::entry::EntryInitNew;
|
||||
use crate::prelude::*;
|
||||
|
||||
use kanidm_proto::v1::{Filter, OperationError, UiHint};
|
||||
use kanidm_proto::internal::{Filter, OperationError, UiHint};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
/// Built-in group definitions
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use hashbrown::{HashMap as Map, HashSet};
|
||||
use kanidm_proto::v1::{BackupCodesView, CredentialDetail, CredentialDetailType, OperationError};
|
||||
use kanidm_proto::internal::{
|
||||
BackupCodesView, CredentialDetail, CredentialDetailType, OperationError,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{AuthenticationResult, Passkey, SecurityKey};
|
||||
use webauthn_rs_core::proto::{Credential as WebauthnCredential, CredentialV3};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::convert::{TryFrom, TryInto};
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use kanidm_proto::v1::{TotpAlgo as ProtoTotpAlgo, TotpSecret as ProtoTotp};
|
||||
use kanidm_proto::internal::{TotpAlgo as ProtoTotpAlgo, TotpSecret as ProtoTotp};
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::sign::Signer;
|
||||
|
|
|
@ -32,10 +32,10 @@ use std::sync::Arc;
|
|||
use compact_jwt::JwsEs256Signer;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use kanidm_proto::v1::{
|
||||
ConsistencyError, Entry as ProtoEntry, Filter as ProtoFilter, OperationError, SchemaError,
|
||||
UiHint,
|
||||
use kanidm_proto::internal::{
|
||||
ConsistencyError, Filter as ProtoFilter, OperationError, SchemaError, UiHint,
|
||||
};
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry};
|
||||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::{Private, Public};
|
||||
|
|
|
@ -19,10 +19,11 @@ use std::collections::BTreeSet;
|
|||
#[cfg(test)]
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::{
|
||||
CreateRequest, DeleteRequest, Entry as ProtoEntry, ModifyList as ProtoModifyList,
|
||||
ModifyRequest, OperationError, SearchRequest, SearchResponse, WhoamiResponse,
|
||||
use kanidm_proto::internal::{
|
||||
CreateRequest, DeleteRequest, ModifyList as ProtoModifyList, ModifyRequest, OperationError,
|
||||
SearchRequest, SearchResponse,
|
||||
};
|
||||
use kanidm_proto::v1::{Entry as ProtoEntry, WhoamiResponse};
|
||||
use ldap3_proto::simple::LdapFilter;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use hashbrown::HashMap;
|
|||
#[cfg(test)]
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::constants::ATTR_UUID;
|
||||
use kanidm_proto::v1::{Filter as ProtoFilter, OperationError, SchemaError};
|
||||
use kanidm_proto::internal::{Filter as ProtoFilter, OperationError, SchemaError};
|
||||
use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter};
|
||||
// use smartstring::alias::String as AttrString;
|
||||
use serde::Deserialize;
|
||||
|
@ -1574,7 +1574,7 @@ mod tests {
|
|||
use std::collections::BTreeSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
use ldap3_proto::simple::LdapFilter;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{
|
||||
BackupCodesView, CredentialStatus, OperationError, UatPurpose, UatStatus, UatStatusState,
|
||||
UiHint, UserAuthToken,
|
||||
use kanidm_proto::internal::{
|
||||
BackupCodesView, CredentialStatus, UatPurpose, UiHint, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::v1::{UatStatus, UatStatusState};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{
|
||||
|
@ -925,7 +925,7 @@ mod tests {
|
|||
use crate::idm::account::Account;
|
||||
use crate::idm::accountpolicy::ResolvedAccountPolicy;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::UiHint;
|
||||
use kanidm_proto::internal::UiHint;
|
||||
|
||||
#[test]
|
||||
fn test_idm_account_from_anonymous() {
|
||||
|
|
|
@ -9,9 +9,8 @@ use std::time::Duration;
|
|||
|
||||
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
AuthAllowed, AuthCredential, AuthIssueSession, AuthMech, OperationError, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::internal::UserAuthToken;
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthIssueSession, AuthMech};
|
||||
use nonempty::{nonempty, NonEmpty};
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use uuid::Uuid;
|
||||
|
@ -1482,9 +1481,8 @@ mod tests {
|
|||
|
||||
use compact_jwt::{JwsCompact, JwsEs256Signer, JwsEs256Verifier, JwsVerifier};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
AuthAllowed, AuthCredential, AuthIssueSession, AuthMech, UatPurpose, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::internal::{UatPurpose, UserAuthToken};
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthIssueSession, AuthMech};
|
||||
use tokio::sync::mpsc::unbounded_channel as unbounded;
|
||||
use webauthn_authenticator_rs::softpasskey::SoftPasskey;
|
||||
use webauthn_authenticator_rs::WebauthnAuthenticator;
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::time::Duration;
|
|||
use sshkey_attest::proto::PublicKey as SshPublicKey;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
use kanidm_proto::internal::{
|
||||
CUCredState, CUExtPortal, CURegState, CURegWarning, CUStatus, CredentialDetail, PasskeyDetail,
|
||||
PasswordFeedback, TotpSecret,
|
||||
};
|
||||
|
@ -2312,10 +2312,8 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
|
|||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{
|
||||
AuthAllowed, AuthIssueSession, AuthMech, CUExtPortal, CredentialDetailType,
|
||||
PasswordFeedback,
|
||||
};
|
||||
use kanidm_proto::internal::{CUExtPortal, CredentialDetailType, PasswordFeedback};
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech};
|
||||
use uuid::uuid;
|
||||
use webauthn_authenticator_rs::softpasskey::SoftPasskey;
|
||||
use webauthn_authenticator_rs::softtoken::{self, SoftToken};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::idm::AuthState;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidm_proto::v1::{AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthStep};
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use kanidm_proto::v1::UiHint;
|
||||
use kanidm_proto::v1::{Group as ProtoGroup, OperationError};
|
||||
use kanidm_proto::internal::{Group as ProtoGroup, UiHint};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::accountpolicy::{AccountPolicy, ResolvedAccountPolicy};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use kanidm_proto::{internal::IdentifyUserResponse, v1::OperationError};
|
||||
use kanidm_proto::internal::IdentifyUserResponse;
|
||||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::{PKey, Private, Public};
|
||||
use openssl::pkey_ctx::PkeyCtx;
|
||||
|
@ -8,7 +9,6 @@ use sketching::admin_error;
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::credential::totp::{Totp, TotpAlgo, TotpDigits};
|
||||
use crate::prelude::{tagged_event, Attribute, EventTag};
|
||||
use crate::server::QueryServerTransaction;
|
||||
use crate::{event::SearchEvent, server::identity::Identity};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::collections::BTreeSet;
|
|||
use std::iter;
|
||||
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::v1::{ApiToken, OperationError, UserAuthToken};
|
||||
use kanidm_proto::internal::{ApiToken, UserAuthToken};
|
||||
use ldap3_proto::simple::*;
|
||||
use regex::Regex;
|
||||
use std::net::IpAddr;
|
||||
|
@ -621,7 +621,7 @@ mod tests {
|
|||
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
use kanidm_proto::internal::ApiToken;
|
||||
use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope, LdapSubstringFilter};
|
||||
use ldap3_proto::simple::*;
|
||||
|
||||
|
|
|
@ -2551,8 +2551,8 @@ mod tests {
|
|||
OidcSubject, OidcUnverified,
|
||||
};
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::internal::UserAuthToken;
|
||||
use kanidm_proto::oauth2::*;
|
||||
use kanidm_proto::v1::UserAuthToken;
|
||||
use openssl::sha;
|
||||
|
||||
use crate::idm::accountpolicy::ResolvedAccountPolicy;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{OperationError, RadiusAuthToken};
|
||||
use kanidm_proto::internal::RadiusAuthToken;
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
|
@ -3,9 +3,8 @@ use std::time::Duration;
|
|||
use base64urlsafedata::Base64UrlSafeData;
|
||||
|
||||
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
|
||||
use kanidm_proto::internal::ScimSyncToken;
|
||||
use kanidm_proto::internal::{ApiTokenPurpose, ScimSyncToken};
|
||||
use kanidm_proto::scim_v1::*;
|
||||
use kanidm_proto::v1::ApiTokenPurpose;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use crate::credential::totp::{Totp, TotpAlgo, TotpDigits};
|
||||
|
@ -1150,7 +1149,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
// What classes did they request for this entry to sync?
|
||||
let requested_classes = scim_ent.schemas.iter()
|
||||
.map(|schema| {
|
||||
schema.as_str().strip_prefix(SCIM_SCHEMA_SYNC)
|
||||
schema.as_str().strip_prefix(SCIM_SCHEMA_SYNC_1)
|
||||
.ok_or_else(|| {
|
||||
error!(?schema, "Invalid requested schema - Not a kanidm sync schema.");
|
||||
OperationError::InvalidEntryState
|
||||
|
@ -1537,8 +1536,8 @@ mod tests {
|
|||
use crate::prelude::*;
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use kanidm_proto::internal::ApiTokenPurpose;
|
||||
use kanidm_proto::scim_v1::*;
|
||||
use kanidm_proto::v1::ApiTokenPurpose;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -2094,7 +2093,7 @@ mod tests {
|
|||
assert!(apply_phase_3_test(
|
||||
idms,
|
||||
vec![ScimEntry {
|
||||
schemas: vec![format!("{SCIM_SCHEMA_SYNC}system")],
|
||||
schemas: vec![format!("{SCIM_SCHEMA_SYNC_1}system")],
|
||||
id: user_sync_uuid,
|
||||
external_id: Some("cn=testgroup,ou=people,dc=test".to_string()),
|
||||
meta: None,
|
||||
|
@ -3168,9 +3167,9 @@ mod tests {
|
|||
"entries": [
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:person",
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:account",
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:posixaccount"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:person",
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:account",
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixaccount"
|
||||
],
|
||||
"id": "babb8302-43a1-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "uid=testuser,cn=users,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3194,7 +3193,7 @@ mod tests {
|
|||
},
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:group"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:group"
|
||||
],
|
||||
"id": "d547c581-5f26-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "cn=testgroup,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3208,7 +3207,7 @@ mod tests {
|
|||
},
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:group"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:group"
|
||||
],
|
||||
"id": "d547c583-5f26-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "cn=testexternal,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3216,8 +3215,8 @@ mod tests {
|
|||
},
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:group",
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:posixgroup"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:group",
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixgroup"
|
||||
],
|
||||
"id": "f90b0b81-5f26-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "cn=testposix,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3249,7 +3248,7 @@ mod tests {
|
|||
"entries": [
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:group"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:group"
|
||||
],
|
||||
"id": "d547c583-5f26-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "cn=testexternal2,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3262,8 +3261,8 @@ mod tests {
|
|||
},
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:group",
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:posixgroup"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:group",
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixgroup"
|
||||
],
|
||||
"id": "f90b0b81-5f26-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "cn=testposix,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3290,9 +3289,9 @@ mod tests {
|
|||
"entries": [
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:person",
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:account",
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:posixaccount"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:person",
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:account",
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixaccount"
|
||||
],
|
||||
"id": "babb8302-43a1-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "uid=testuser,cn=users,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
@ -3307,7 +3306,7 @@ mod tests {
|
|||
},
|
||||
{
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:kanidm:1.0:group"
|
||||
"urn:ietf:params:scim:schemas:kanidm:sync:1:group"
|
||||
],
|
||||
"id": "d547c581-5f26-11ed-a50d-919b4b1a5ec0",
|
||||
"externalId": "cn=testgroup,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
|
||||
|
|
|
@ -11,11 +11,11 @@ use concread::cowcell::{CowCellReadTxn, CowCellWriteTxn};
|
|||
use concread::hashmap::HashMap;
|
||||
use concread::CowCell;
|
||||
use fernet::Fernet;
|
||||
use kanidm_proto::internal::ScimSyncToken;
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, UatPurpose,
|
||||
UnixGroupToken, UnixUserToken, UserAuthToken,
|
||||
use kanidm_proto::internal::{
|
||||
ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, ScimSyncToken,
|
||||
UatPurpose, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
use rand::prelude::*;
|
||||
use tokio::sync::mpsc::{
|
||||
unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender,
|
||||
|
@ -2165,7 +2165,7 @@ mod tests {
|
|||
use std::convert::TryFrom;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech, OperationError};
|
||||
use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -3592,7 +3592,7 @@ mod tests {
|
|||
idms: &IdmServer,
|
||||
idms_delayed: &mut IdmServerDelayed,
|
||||
) {
|
||||
use kanidm_proto::v1::UserAuthToken;
|
||||
use kanidm_proto::internal::UserAuthToken;
|
||||
use std::str::FromStr;
|
||||
|
||||
let ct = Duration::from_secs(TEST_CURRENT_TIME);
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeMap;
|
|||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
|
||||
use kanidm_proto::v1::ApiToken as ProtoApiToken;
|
||||
use kanidm_proto::internal::ApiToken as ProtoApiToken;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::credential::Credential;
|
||||
|
@ -14,21 +14,6 @@ use crate::prelude::*;
|
|||
use crate::utils::password_from_random;
|
||||
use crate::value::ApiToken;
|
||||
|
||||
// Need to add KID to es256 der for lookups ✅
|
||||
|
||||
// Need to generate the es256 on the account on modifies ✅
|
||||
|
||||
// Add migration to generate the es256 on startup at least once. ✅
|
||||
|
||||
// Create new valueset type to store sessions w_ labels ✅
|
||||
|
||||
// Able to lookup from KID to get service account
|
||||
|
||||
// Able to take token -> ident
|
||||
// -- check still valid
|
||||
|
||||
// revoke
|
||||
|
||||
macro_rules! try_from_entry {
|
||||
($value:expr) => {{
|
||||
// Check the classes
|
||||
|
@ -432,7 +417,7 @@ mod tests {
|
|||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
use kanidm_proto::internal::ApiToken;
|
||||
|
||||
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent};
|
||||
use crate::event::CreateEvent;
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::iter;
|
|||
// use crossbeam::channel::Sender;
|
||||
use std::time::Duration;
|
||||
|
||||
use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken};
|
||||
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use uuid::Uuid;
|
||||
|
|
|
@ -63,7 +63,7 @@ pub mod testkit;
|
|||
/// help make imports cleaner.
|
||||
pub mod prelude {
|
||||
pub use kanidm_proto::constants::*;
|
||||
pub use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError};
|
||||
pub use kanidm_proto::internal::{ConsistencyError, OperationError, PluginError, SchemaError};
|
||||
pub use sketching::{
|
||||
admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace,
|
||||
filter_warn, perf_trace, request_error, request_info, request_trace, request_warn,
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
use std::slice;
|
||||
|
||||
use kanidm_proto::v1::{
|
||||
Entry as ProtoEntry, Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError,
|
||||
SchemaError,
|
||||
use kanidm_proto::internal::{
|
||||
Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError, SchemaError,
|
||||
};
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
// Should this be std?
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::alias::String as AttrString;
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::collections::VecDeque;
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
|
@ -491,8 +490,6 @@ impl Plugin for AttrUnique {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
// Test entry in db, and same name, reject.
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::iter::once;
|
|||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{ConsistencyError, PluginError};
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::modify::Modify;
|
||||
|
@ -241,7 +240,6 @@ impl Plugin for Base {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
use std::sync::Arc;
|
||||
|
||||
const UUID_TEST_ACCOUNT: Uuid = uuid::uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
|
||||
|
|
|
@ -3,8 +3,6 @@ use std::convert::TryFrom;
|
|||
use std::iter::once;
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
use crate::credential::{Credential, Password};
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
|
@ -171,7 +169,6 @@ mod tests {
|
|||
use crate::credential::{Credential, CredentialType};
|
||||
use crate::prelude::*;
|
||||
use kanidm_lib_crypto::CryptoPolicy;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
|
||||
const IMPORT_HASH: &str =
|
||||
"pbkdf2_sha256$36000$xIEozuZVAoYm$uW1b35DUKyhvQAf1mBqMvoBDcqSD06juzyO/nmyV0+w=";
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::iter::once;
|
|||
use std::sync::Arc;
|
||||
|
||||
use compact_jwt::JwsEs256Signer;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use rand::prelude::*;
|
||||
use regex::Regex;
|
||||
use tracing::trace;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
|
||||
use crate::filter::FilterInvalid;
|
||||
use crate::prelude::*;
|
||||
|
@ -378,7 +378,7 @@ impl DynGroup {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use openssl::ec::{EcGroup, EcKey};
|
|||
use openssl::nid::Nid;
|
||||
|
||||
use crate::prelude::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::Plugin;
|
||||
|
||||
|
@ -62,21 +63,21 @@ impl Plugin for EcdhKeyGen {
|
|||
|
||||
#[instrument(level = "debug", name = "ecdhkeygen::pre_modify", skip_all)]
|
||||
fn pre_modify(
|
||||
_qs: &mut crate::server::QueryServerWriteTransaction,
|
||||
_pre_cand: &[std::sync::Arc<crate::prelude::EntrySealedCommitted>],
|
||||
cand: &mut Vec<crate::prelude::EntryInvalidCommitted>,
|
||||
_me: &crate::event::ModifyEvent,
|
||||
) -> Result<(), kanidm_proto::v1::OperationError> {
|
||||
_qs: &mut QueryServerWriteTransaction,
|
||||
_pre_cand: &[Arc<EntrySealedCommitted>],
|
||||
cand: &mut Vec<EntryInvalidCommitted>,
|
||||
_me: &ModifyEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
Self::generate_key(cand)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", name = "ecdhkeygen::pre_batch_modify", skip_all)]
|
||||
fn pre_batch_modify(
|
||||
_qs: &mut crate::server::QueryServerWriteTransaction,
|
||||
_pre_cand: &[std::sync::Arc<crate::prelude::EntrySealedCommitted>],
|
||||
cand: &mut Vec<crate::prelude::EntryInvalidCommitted>,
|
||||
_me: &crate::server::batch_modify::BatchModifyEvent,
|
||||
) -> Result<(), kanidm_proto::v1::OperationError> {
|
||||
_qs: &mut QueryServerWriteTransaction,
|
||||
_pre_cand: &[Arc<EntrySealedCommitted>],
|
||||
cand: &mut Vec<EntryInvalidCommitted>,
|
||||
_me: &BatchModifyEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
Self::generate_key(cand)
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +87,7 @@ mod tests {
|
|||
use openssl::ec::EcKey;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::plugins::eckeygen::DEFAULT_KEY_GROUP;
|
||||
use super::DEFAULT_KEY_GROUP;
|
||||
use crate::prelude::*;
|
||||
use crate::value::Value;
|
||||
use crate::valueset;
|
||||
|
|
|
@ -14,7 +14,6 @@ use std::collections::BTreeSet;
|
|||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntrySealed, EntryTuple};
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::prelude::*;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use kanidm_proto::v1::OperationError;
|
||||
|
||||
use crate::entry::{EntryInvalidCommitted, EntrySealedCommitted};
|
||||
use crate::event::ModifyEvent;
|
||||
use crate::plugins::Plugin;
|
||||
|
|
|
@ -13,7 +13,6 @@ use std::collections::BTreeSet;
|
|||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::ConsistencyError;
|
||||
|
||||
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
|
||||
use crate::filter::{f_eq, FC};
|
||||
|
@ -439,18 +438,15 @@ impl ReferentialIntegrity {
|
|||
error!(?missing);
|
||||
}
|
||||
|
||||
Err(OperationError::Plugin(
|
||||
kanidm_proto::v1::PluginError::ReferentialIntegrity(
|
||||
Err(OperationError::Plugin(PluginError::ReferentialIntegrity(
|
||||
"Uuid referenced not found in database".to_string(),
|
||||
),
|
||||
))
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::v1::PluginError;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
|
||||
use crate::event::CreateEvent;
|
||||
use crate::prelude::*;
|
||||
|
|
|
@ -4,9 +4,6 @@ use std::collections::BTreeSet;
|
|||
use std::iter::once;
|
||||
use std::sync::Arc;
|
||||
|
||||
// use crate::value::{PartialValue, Value};
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError};
|
||||
|
||||
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::plugins::Plugin;
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::time::Duration;
|
|||
|
||||
use crate::be::dbvalue::DbCidV1;
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)]
|
||||
|
|
|
@ -8,7 +8,6 @@ use std::time::Duration;
|
|||
use concread::bptree::{BptreeMap, BptreeMapReadSnapshot, BptreeMapReadTxn, BptreeMapWriteTxn};
|
||||
|
||||
use idlset::v2::IDLBitRange;
|
||||
use kanidm_proto::v1::ConsistencyError;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
|
|
|
@ -20,7 +20,6 @@ use std::collections::BTreeSet;
|
|||
|
||||
use concread::cowcell::*;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError};
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -2268,13 +2267,11 @@ impl Schema {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kanidm_proto::v1::{ConsistencyError, SchemaError};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::{
|
||||
IndexType, Schema, SchemaAttribute, SchemaClass, SchemaTransaction, SyntaxType,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
// use crate::proto_v1::Filter as ProtoFilter;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ use std::sync::Arc;
|
|||
|
||||
use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn};
|
||||
use concread::cowcell::*;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::BTreeSet;
|
|||
|
||||
use crate::filter::{Filter, FilterValid, FilterValidResolved};
|
||||
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
|
||||
// =========================================================================
|
||||
// PARSE ENTRY TO ACP, AND ACP MANAGEMENT
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::net::IpAddr;
|
|||
use std::sync::Arc;
|
||||
use uuid::uuid;
|
||||
|
||||
use kanidm_proto::v1::{ApiTokenPurpose, UatPurpose};
|
||||
use kanidm_proto::internal::{ApiTokenPurpose, UatPurpose};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::value::CredentialType;
|
||||
use kanidm_proto::v1::SchemaError;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
|
|
@ -11,8 +11,7 @@ use std::collections::BTreeSet;
|
|||
use tokio::sync::{Semaphore, SemaphorePermit};
|
||||
use tracing::trace;
|
||||
|
||||
use kanidm_proto::internal::DomainInfo as ProtoDomainInfo;
|
||||
use kanidm_proto::v1::{ConsistencyError, UiHint};
|
||||
use kanidm_proto::internal::{DomainInfo as ProtoDomainInfo, UiHint};
|
||||
|
||||
use crate::be::{Backend, BackendReadTransaction, BackendTransaction, BackendWriteTransaction};
|
||||
// We use so many, we just import them all ...
|
||||
|
|
|
@ -39,10 +39,8 @@ use crate::repl::cid::Cid;
|
|||
use crate::server::identity::IdentityId;
|
||||
use crate::valueset::image::ImageValueThings;
|
||||
use crate::valueset::uuid_to_proto_string;
|
||||
use kanidm_proto::v1::ApiTokenPurpose;
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::{ApiTokenPurpose, Filter as ProtoFilter, UiHint};
|
||||
use kanidm_proto::v1::UatPurposeStatus;
|
||||
use kanidm_proto::v1::UiHint;
|
||||
use std::hash::Hash;
|
||||
|
||||
lazy_static! {
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::be::dbvalue::DbValueSetV2;
|
|||
use crate::prelude::*;
|
||||
use crate::repl::proto::ReplAttrV1;
|
||||
use crate::value::{PartialValue, SyntaxType, Value};
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::{Private, Public};
|
||||
|
||||
|
@ -73,10 +72,7 @@ impl ValueSetEcKeyPrivate {
|
|||
}
|
||||
|
||||
impl ValueSetT for ValueSetEcKeyPrivate {
|
||||
fn insert_checked(
|
||||
&mut self,
|
||||
value: crate::value::Value,
|
||||
) -> Result<bool, kanidm_proto::v1::OperationError> {
|
||||
fn insert_checked(&mut self, value: crate::value::Value) -> Result<bool, OperationError> {
|
||||
match value {
|
||||
Value::EcKeyPrivate(k) => Ok(self.push(&k)),
|
||||
_ => {
|
||||
|
@ -190,7 +186,7 @@ impl ValueSetT for ValueSetEcKeyPrivate {
|
|||
})
|
||||
}
|
||||
|
||||
fn merge(&mut self, other: &super::ValueSet) -> Result<(), kanidm_proto::v1::OperationError> {
|
||||
fn merge(&mut self, other: &super::ValueSet) -> Result<(), OperationError> {
|
||||
if let Some(other_key) = other.as_ec_key_private() {
|
||||
let priv_key = other_key.clone();
|
||||
let pub_key = Self::private_key_to_public_key(&priv_key)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
|
|
@ -14,8 +14,7 @@ use webauthn_rs::prelude::AttestationCaList;
|
|||
use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
|
||||
use kanidm_proto::v1::Filter as ProtoFilter;
|
||||
use kanidm_proto::v1::UiHint;
|
||||
use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
|
||||
|
||||
use crate::be::dbvalue::DbValueSetV2;
|
||||
use crate::credential::{totp::Totp, Credential};
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::repl::proto::ReplAttrV1;
|
|||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use kanidm_proto::v1::UiHint;
|
||||
use kanidm_proto::internal::UiHint;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetUiHint {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
fn main() {
|
||||
profiles::apply_profile();
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::sync::atomic::{AtomicU16, Ordering};
|
|||
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
|
||||
use kanidm_proto::v1::{Filter, Modify, ModifyList};
|
||||
use kanidm_proto::internal::{Filter, Modify, ModifyList};
|
||||
use kanidmd_core::config::{Configuration, IntegrationTestConfig};
|
||||
use kanidmd_core::{create_server_core, CoreHandle};
|
||||
use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use core::result::Result::Err;
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::internal::OperationError;
|
||||
use kanidm_proto::internal::{IdentifyUserRequest, IdentifyUserResponse};
|
||||
|
||||
use kanidmd_lib::prelude::Attribute;
|
||||
|
@ -57,7 +58,7 @@ async fn test_non_existing_user_id(rsclient: KanidmClient) {
|
|||
.idm_person_identify_user(non_existing_user, IdentifyUserRequest::Start)
|
||||
.await;
|
||||
assert!(
|
||||
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(kanidm_proto::v1::OperationError::NoMatchingEntries), .. )))
|
||||
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(OperationError::NoMatchingEntries), .. )))
|
||||
);
|
||||
|
||||
let res = rsclient
|
||||
|
@ -65,7 +66,7 @@ async fn test_non_existing_user_id(rsclient: KanidmClient) {
|
|||
.await;
|
||||
|
||||
assert!(
|
||||
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(kanidm_proto::v1::OperationError::NoMatchingEntries), .. )))
|
||||
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(OperationError::NoMatchingEntries), .. )))
|
||||
);
|
||||
|
||||
let res = rsclient
|
||||
|
@ -76,7 +77,7 @@ async fn test_non_existing_user_id(rsclient: KanidmClient) {
|
|||
.await;
|
||||
|
||||
assert!(
|
||||
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(kanidm_proto::v1::OperationError::NoMatchingEntries), .. )))
|
||||
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(OperationError::NoMatchingEntries), .. )))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,12 @@ use std::path::Path;
|
|||
use std::time::SystemTime;
|
||||
|
||||
use kanidm_proto::constants::KSESSIONID;
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use kanidm_proto::internal::{
|
||||
ApiToken, CURegState, Filter, ImageValue, Modify, ModifyList, UatPurpose, UserAuthToken,
|
||||
};
|
||||
use kanidm_proto::v1::{
|
||||
ApiToken, AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthResponse, AuthState,
|
||||
AuthStep, CURegState, Entry, Filter, Modify, ModifyList, UatPurpose, UserAuthToken,
|
||||
AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthResponse, AuthState, AuthStep,
|
||||
Entry,
|
||||
};
|
||||
use kanidmd_lib::credential::totp::Totp;
|
||||
use kanidmd_lib::prelude::{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use gloo::storage::{LocalStorage, SessionStorage as TemporaryStorage, Storage};
|
||||
use kanidm_proto::internal::{CUSessionToken, CUStatus};
|
||||
use kanidm_proto::oauth2::AuthorisationRequest;
|
||||
use kanidm_proto::v1::{CUSessionToken, CUStatus};
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
||||
use crate::constants::URL_USER_HOME;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use kanidm_proto::v1::{SingleStringRequest, UserAuthToken};
|
||||
use kanidm_proto::internal::UserAuthToken;
|
||||
use kanidm_proto::v1::SingleStringRequest;
|
||||
use kanidmd_web_ui_shared::constants::ID_UNIX_PASSWORDCHANGE;
|
||||
use kanidmd_web_ui_shared::do_request;
|
||||
use kanidmd_web_ui_shared::error::FetchError;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::v1::{CUIntentToken, UserAuthToken};
|
||||
use kanidm_proto::internal::{CUIntentToken, UserAuthToken};
|
||||
use kanidmd_web_ui_shared::constants::{ID_CRED_RESET_CODE, URL_RESET};
|
||||
use kanidmd_web_ui_shared::error::FetchError;
|
||||
use kanidmd_web_ui_shared::utils::{document, modal_hide_by_id, origin};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::v1::{CUSessionToken, CUStatus, UiHint, UserAuthToken};
|
||||
use kanidm_proto::internal::{CUSessionToken, CUStatus, UiHint, UserAuthToken};
|
||||
use kanidmd_web_ui_shared::models::{
|
||||
push_cred_update_session, push_login_hint, push_return_location,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus};
|
||||
use kanidm_proto::internal::{CURequest, CUSessionToken, CUStatus};
|
||||
use kanidmd_web_ui_shared::error::FetchError;
|
||||
use kanidmd_web_ui_shared::utils::modal_hide_by_id;
|
||||
use serde::Serialize;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use gloo::console;
|
||||
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus};
|
||||
use kanidm_proto::internal::{CURegState, CURequest, CUSessionToken, CUStatus};
|
||||
use kanidm_proto::webauthn::{CreationChallengeResponse, RegisterPublicKeyCredential};
|
||||
use kanidmd_web_ui_shared::constants::CLASS_BUTTON_SUCCESS;
|
||||
use kanidmd_web_ui_shared::error::FetchError;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus};
|
||||
use kanidm_proto::internal::{CURegState, CURequest, CUSessionToken, CUStatus};
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use gloo::console;
|
||||
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus, OperationError, PasswordFeedback};
|
||||
use kanidm_proto::internal::{
|
||||
CURequest, CUSessionToken, CUStatus, OperationError, PasswordFeedback,
|
||||
};
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
||||
use serde::Serialize;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use gloo::console;
|
||||
use kanidm_proto::v1::{
|
||||
use kanidm_proto::internal::{
|
||||
CUCredState, CUExtPortal, CUIntentToken, CURegWarning, CUSessionToken, CUStatus,
|
||||
CredentialDetail, CredentialDetailType, PasskeyDetail,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus, TotpSecret};
|
||||
use kanidm_proto::internal::{CURegState, CURequest, CUSessionToken, CUStatus, TotpSecret};
|
||||
use qrcode::render::svg;
|
||||
use qrcode::QrCode;
|
||||
use wasm_bindgen::UnwrapThrowExt;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::reset::{EventBusMsg, TotpRemoveProps};
|
||||
#[cfg(debug_assertions)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus};
|
||||
use kanidm_proto::internal::{CURequest, CUSessionToken, CUStatus};
|
||||
use kanidmd_web_ui_shared::RequestMethod;
|
||||
use kanidmd_web_ui_shared::{do_request, error::FetchError};
|
||||
use serde::Serialize;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
use gloo::console;
|
||||
use kanidm_proto::constants::uri::V1_AUTH_VALID;
|
||||
use kanidm_proto::v1::{UiHint, UserAuthToken};
|
||||
use kanidm_proto::internal::{UiHint, UserAuthToken};
|
||||
use kanidmd_web_ui_shared::constants::{
|
||||
CSS_ALERT_DANGER, CSS_NAVBAR_BRAND, CSS_NAVBAR_LINKS_UL, CSS_NAVBAR_NAV, CSS_NAV_LINK,
|
||||
ID_NAVBAR_COLLAPSE, IMG_LOGO_SQUARE, URL_ADMIN, URL_LOGIN,
|
||||
|
|
|
@ -15,6 +15,10 @@ include!("src/opt/kanidm.rs");
|
|||
fn main() -> Result<(), Error> {
|
||||
profiles::apply_profile();
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=OUT_DIR");
|
||||
println!("cargo:rerun-if-changed=src/opt/kanidm.rs");
|
||||
println!("cargo:rerun-if-changed=src/opt/ssh_authorizedkeys.rs");
|
||||
let outdir = match env::var_os("OUT_DIR") {
|
||||
None => return Ok(()),
|
||||
Some(outdir) => outdir,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue