chore: Migrate all the crates to edition 2024

This commit is contained in:
Valentin Tolmer
2025-03-30 21:10:04 -05:00
committed by nitnelave
parent e18f2af54f
commit ba9bcb3894
76 changed files with 358 additions and 302 deletions

29
Cargo.lock generated
View File

@@ -2565,7 +2565,7 @@ dependencies = [
"serial_test",
"sha2 0.10.8",
"strum 0.25.0",
"thiserror 1.0.66",
"thiserror 2.0.12",
"time",
"tokio",
"tokio-rustls 0.23.4",
@@ -2632,7 +2632,7 @@ dependencies = [
"sea-orm",
"serde",
"sha2 0.9.9",
"thiserror 1.0.66",
"thiserror 2.0.12",
]
[[package]]
@@ -5154,24 +5154,24 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.95"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.100",
@@ -5192,9 +5192,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5202,9 +5202,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
@@ -5215,9 +5215,12 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"

View File

@@ -2,7 +2,7 @@
name = "lldap_app"
version = "0.6.2-alpha"
description = "Frontend for LLDAP"
edition = "2021"
edition.workspace = true
include = ["src/**/*", "queries/**/*", "Cargo.toml", "../schema.graphql"]
authors.workspace = true
homepage.workspace = true
@@ -23,7 +23,7 @@ serde_json = "1"
url-escape = "0.1.1"
validator = "0.14"
validator_derive = "0.14"
wasm-bindgen = "0.2"
wasm-bindgen = "0.2.100"
wasm-bindgen-futures = "*"
yew = "0.19.3"
yew-router = "0.16"

View File

@@ -23,15 +23,14 @@ use crate::{
use gloo_console::error;
use lldap_frontend_options::Options;
use yew::{
function_component,
Context, function_component,
html::Scope,
prelude::{html, Component, Html},
Context,
prelude::{Component, Html, html},
};
use yew_router::{
BrowserRouter, Switch,
prelude::{History, Location},
scope_ext::RouterScopeExt,
BrowserRouter, Switch,
};
#[function_component(AppContainer)]

View File

@@ -1,6 +1,6 @@
use crate::infra::functional::{use_graphql_call, LoadableResult};
use crate::infra::functional::{LoadableResult, use_graphql_call};
use graphql_client::GraphQLQuery;
use yew::{function_component, html, virtual_dom::AttrValue, Properties};
use yew::{Properties, function_component, html, virtual_dom::AttrValue};
#[derive(GraphQLQuery)]
#[graphql(

View File

@@ -4,7 +4,7 @@ use crate::components::{
router::{AppRoute, Link},
};
use wasm_bindgen::prelude::wasm_bindgen;
use yew::{function_component, html, Callback, Properties};
use yew::{Callback, Properties, function_component, html};
#[derive(Properties, PartialEq)]
pub struct Props {

View File

@@ -8,7 +8,7 @@ use crate::{
common_component::{CommonComponent, CommonComponentParts},
},
};
use anyhow::{anyhow, bail, Result};
use anyhow::{Result, anyhow, bail};
use gloo_console::error;
use lldap_auth::*;
use validator_derive::Validate;

View File

@@ -11,13 +11,13 @@ use crate::{
infra::{
common_component::{CommonComponent, CommonComponentParts},
form_utils::{
read_all_form_attributes, AttributeValue, EmailIsRequired, GraphQlAttributeSchema,
IsAdmin,
AttributeValue, EmailIsRequired, GraphQlAttributeSchema, IsAdmin,
read_all_form_attributes,
},
schema::AttributeType,
},
};
use anyhow::{ensure, Result};
use anyhow::{Result, ensure};
use gloo_console::log;
use graphql_client::GraphQLQuery;
use validator_derive::Validate;

View File

@@ -6,10 +6,10 @@ use crate::{
convert_attribute_type,
infra::{
common_component::{CommonComponent, CommonComponentParts},
schema::{validate_attribute_type, AttributeType},
schema::{AttributeType, validate_attribute_type},
},
};
use anyhow::{bail, Result};
use anyhow::{Result, bail};
use gloo_console::log;
use graphql_client::GraphQLQuery;
use lldap_validation::attributes::validate_attribute_name;

View File

@@ -12,13 +12,13 @@ use crate::{
api::HostService,
common_component::{CommonComponent, CommonComponentParts},
form_utils::{
read_all_form_attributes, AttributeValue, EmailIsRequired, GraphQlAttributeSchema,
IsAdmin,
AttributeValue, EmailIsRequired, GraphQlAttributeSchema, IsAdmin,
read_all_form_attributes,
},
schema::AttributeType,
},
};
use anyhow::{ensure, Result};
use anyhow::{Result, ensure};
use gloo_console::log;
use graphql_client::GraphQLQuery;
use lldap_auth::{opaque, registration};

View File

@@ -6,10 +6,10 @@ use crate::{
convert_attribute_type,
infra::{
common_component::{CommonComponent, CommonComponentParts},
schema::{validate_attribute_type, AttributeType},
schema::{AttributeType, validate_attribute_type},
},
};
use anyhow::{bail, Result};
use anyhow::{Result, bail};
use gloo_console::log;
use graphql_client::GraphQLQuery;
use lldap_validation::attributes::validate_attribute_name;

View File

@@ -4,8 +4,8 @@ use crate::{
};
use web_sys::Element;
use yew::{
function_component, html, use_effect_with_deps, use_node_ref, virtual_dom::AttrValue,
Component, Context, Html, Properties,
Component, Context, Html, Properties, function_component, html, use_effect_with_deps,
use_node_ref, virtual_dom::AttrValue,
};
#[derive(Properties, PartialEq)]
@@ -24,12 +24,12 @@ fn attribute_input(props: &AttributeInputProps) -> Html {
AttributeType::DateTime => {
return html! {
<DateTimeInput name={props.name.clone()} value={props.value.clone()} />
}
};
}
AttributeType::Jpeg => {
return html! {
<JpegFileInput name={props.name.clone()} value={props.value.clone()} />
}
};
}
};

View File

@@ -1,4 +1,4 @@
use yew::{function_component, html, virtual_dom::AttrValue, Callback, Properties};
use yew::{Callback, Properties, function_component, html, virtual_dom::AttrValue};
use yew_form::{Form, Model};
#[derive(Properties, PartialEq)]

View File

@@ -3,7 +3,7 @@ use std::str::FromStr;
use chrono::{DateTime, NaiveDateTime, Utc};
use wasm_bindgen::JsCast;
use web_sys::HtmlInputElement;
use yew::{function_component, html, use_state, virtual_dom::AttrValue, Event, Properties};
use yew::{Event, Properties, function_component, html, use_state, virtual_dom::AttrValue};
#[derive(Properties, PartialEq)]
pub struct DateTimeInputProps {

View File

@@ -1,4 +1,4 @@
use yew::{function_component, html, virtual_dom::AttrValue, Callback, InputEvent, Properties};
use yew::{Callback, InputEvent, Properties, function_component, html, virtual_dom::AttrValue};
use yew_form::{Form, Model};
#[derive(Properties, PartialEq)]

View File

@@ -1,9 +1,9 @@
use std::{fmt::Display, str::FromStr};
use anyhow::{bail, Error, Ok, Result};
use anyhow::{Error, Ok, Result, bail};
use gloo_file::{
callbacks::{read_as_bytes, FileReader},
File,
callbacks::{FileReader, read_as_bytes},
};
use web_sys::{FileList, HtmlInputElement, InputEvent};
use yew::Properties;

View File

@@ -1,5 +1,5 @@
use yew::{
function_component, html, virtual_dom::AttrValue, Callback, Children, InputEvent, Properties,
Callback, Children, InputEvent, Properties, function_component, html, virtual_dom::AttrValue,
};
use yew_form::{Form, Model};

View File

@@ -1,4 +1,4 @@
use yew::{function_component, html, virtual_dom::AttrValue, Children, Properties};
use yew::{Children, Properties, function_component, html, virtual_dom::AttrValue};
#[derive(Properties, PartialEq)]
pub struct Props {

View File

@@ -1,5 +1,5 @@
use web_sys::MouseEvent;
use yew::{function_component, html, virtual_dom::AttrValue, Callback, Children, Properties};
use yew::{Callback, Children, Properties, function_component, html, virtual_dom::AttrValue};
#[derive(Properties, PartialEq)]
pub struct Props {

View File

@@ -1,6 +1,6 @@
use crate::infra::attributes::AttributeDescription;
use lldap_validation::attributes::{validate_attribute_name, ALLOWED_CHARACTERS_DESCRIPTION};
use yew::{html, Html};
use lldap_validation::attributes::{ALLOWED_CHARACTERS_DESCRIPTION, validate_attribute_name};
use yew::{Html, html};
fn render_attribute_aliases(attribute_description: &AttributeDescription) -> Html {
if attribute_description.aliases.is_empty() {

View File

@@ -11,7 +11,7 @@ use crate::{
form_utils::GraphQlAttributeSchema,
},
};
use anyhow::{bail, Error, Result};
use anyhow::{Error, Result, bail};
use graphql_client::GraphQLQuery;
use yew::prelude::*;

View File

@@ -9,7 +9,7 @@ use crate::{
},
infra::{
common_component::{CommonComponent, CommonComponentParts},
form_utils::{read_all_form_attributes, AttributeValue, EmailIsRequired, IsAdmin},
form_utils::{AttributeValue, EmailIsRequired, IsAdmin, read_all_form_attributes},
schema::AttributeType,
},
};

View File

@@ -11,7 +11,7 @@ use crate::{
schema::AttributeType,
},
};
use anyhow::{anyhow, Error, Result};
use anyhow::{Error, Result, anyhow};
use gloo_console::log;
use graphql_client::GraphQLQuery;
use yew::prelude::*;
@@ -57,21 +57,21 @@ impl CommonComponent<GroupSchemaTable> for GroupSchemaTable {
Ok(true)
}
Msg::OnError(e) => Err(e),
Msg::OnAttributeDeleted(attribute_name) => {
match self.attributes {
None => {
log!(format!("Attribute {attribute_name} was deleted but component has no attributes"));
Err(anyhow!("invalid state"))
}
Some(_) => {
self.attributes
.as_mut()
.unwrap()
.retain(|a| a.name != attribute_name);
Ok(true)
}
Msg::OnAttributeDeleted(attribute_name) => match self.attributes {
None => {
log!(format!(
"Attribute {attribute_name} was deleted but component has no attributes"
));
Err(anyhow!("invalid state"))
}
}
Some(_) => {
self.attributes
.as_mut()
.unwrap()
.retain(|a| a.name != attribute_name);
Ok(true)
}
},
}
}

View File

@@ -8,7 +8,7 @@ use crate::{
common_component::{CommonComponent, CommonComponentParts},
},
};
use anyhow::{anyhow, bail, Result};
use anyhow::{Result, anyhow, bail};
use gloo_console::error;
use lldap_auth::*;
use validator_derive::Validate;

View File

@@ -5,7 +5,7 @@ use crate::{
common_component::{CommonComponent, CommonComponentParts},
},
};
use anyhow::{bail, Result};
use anyhow::{Result, bail};
use validator_derive::Validate;
use yew::prelude::*;
use yew_form::Form;

View File

@@ -8,7 +8,7 @@ use crate::{
common_component::{CommonComponent, CommonComponentParts},
},
};
use anyhow::{bail, Result};
use anyhow::{Result, bail};
use lldap_auth::{
opaque::client::registration as opaque_registration,
password_reset::ServerPasswordResetResponse, registration,
@@ -148,7 +148,7 @@ impl Component for ResetPasswordStep2Form {
(None, None) => {
return html! {
{"Validating token"}
}
};
}
(None, Some(e)) => {
return html! {
@@ -163,7 +163,7 @@ impl Component for ResetPasswordStep2Form {
{"Back"}
</Link>
</>
}
};
}
_ => (),
};

View File

@@ -11,7 +11,7 @@ use crate::{
form_utils::GraphQlAttributeSchema,
},
};
use anyhow::{bail, Error, Result};
use anyhow::{Error, Result, bail};
use graphql_client::GraphQLQuery;
use yew::prelude::*;

View File

@@ -9,7 +9,7 @@ use crate::{
},
infra::{
common_component::{CommonComponent, CommonComponentParts},
form_utils::{read_all_form_attributes, AttributeValue, EmailIsRequired, IsAdmin},
form_utils::{AttributeValue, EmailIsRequired, IsAdmin, read_all_form_attributes},
schema::AttributeType,
},
};

View File

@@ -11,7 +11,7 @@ use crate::{
schema::AttributeType,
},
};
use anyhow::{anyhow, Error, Result};
use anyhow::{Error, Result, anyhow};
use gloo_console::log;
use graphql_client::GraphQLQuery;
use yew::prelude::*;
@@ -55,21 +55,21 @@ impl CommonComponent<UserSchemaTable> for UserSchemaTable {
Ok(true)
}
Msg::OnError(e) => Err(e),
Msg::OnAttributeDeleted(attribute_name) => {
match self.attributes {
None => {
log!(format!("Attribute {attribute_name} was deleted but component has no attributes"));
Err(anyhow!("invalid state"))
}
Some(_) => {
self.attributes
.as_mut()
.unwrap()
.retain(|a| a.name != attribute_name);
Ok(true)
}
Msg::OnAttributeDeleted(attribute_name) => match self.attributes {
None => {
log!(format!(
"Attribute {attribute_name} was deleted but component has no attributes"
));
Err(anyhow!("invalid state"))
}
}
Some(_) => {
self.attributes
.as_mut()
.unwrap()
.retain(|a| a.name != attribute_name);
Ok(true)
}
},
}
}

View File

@@ -1,11 +1,11 @@
use super::cookies::set_cookie;
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use gloo_net::http::{Method, RequestBuilder};
use graphql_client::GraphQLQuery;
use lldap_auth::{login, registration, JWTClaims};
use lldap_auth::{JWTClaims, login, registration};
use lldap_frontend_options::Options;
use serde::{de::DeserializeOwned, Serialize};
use serde::{Serialize, de::DeserializeOwned};
use web_sys::RequestCredentials;
#[derive(Default)]

View File

@@ -1,4 +1,4 @@
use anyhow::{anyhow, Result};
use anyhow::{Result, anyhow};
use chrono::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::HtmlDocument;

View File

@@ -1,4 +1,4 @@
use anyhow::{anyhow, ensure, Result};
use anyhow::{Result, anyhow, ensure};
use validator::validate_email;
use web_sys::{FormData, HtmlFormElement};
use yew::NodeRef;

View File

@@ -2,7 +2,7 @@ use crate::infra::api::HostService;
use anyhow::Result;
use graphql_client::GraphQLQuery;
use wasm_bindgen_futures::spawn_local;
use yew::{use_effect_with_deps, use_state_eq, UseStateHandle};
use yew::{UseStateHandle, use_effect_with_deps, use_state_eq};
// Enum to represent a result that is fetched asynchronously.
#[derive(Debug)]

View File

@@ -6,7 +6,7 @@
pub mod components;
pub mod infra;
use wasm_bindgen::prelude::{wasm_bindgen, JsValue};
use wasm_bindgen::prelude::{JsValue, wasm_bindgen};
#[wasm_bindgen]
pub fn run_app() -> Result<(), JsValue> {

View File

@@ -2,7 +2,7 @@
name = "lldap_auth"
version = "0.6.0"
description = "Authentication protocol for LLDAP"
edition = "2021"
edition.workspace = true
authors.workspace = true
homepage.workspace = true
license.workspace = true

View File

@@ -1,7 +1,7 @@
[package]
name = "lldap_domain_handlers"
version = "0.1.0"
edition = "2021"
edition.workspace = true
authors.workspace = true
homepage.workspace = true
license.workspace = true

View File

@@ -1,7 +1,7 @@
[package]
name = "lldap_domain_model"
version = "0.1.0"
edition = "2021"
edition.workspace = true
authors.workspace = true
homepage.workspace = true
license.workspace = true

View File

@@ -5,7 +5,7 @@ authors = [
"Valentin Tolmer <valentin@tolmer.fr>",
"Simon Broeng Jensen <sbj@cwconsult.dk>",
]
edition = "2021"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true

View File

@@ -4,12 +4,12 @@ use base64::Engine;
use chrono::{NaiveDateTime, TimeZone};
use lldap_auth::types::CaseInsensitiveString;
use sea_orm::{
DbErr, DeriveValueType, QueryResult, TryFromU64, TryGetError, TryGetable, Value,
entity::IntoActiveValue,
sea_query::{
extension::mysql::MySqlType, value::ValueType, ArrayType, ColumnType, Nullable, SeaRc,
StringLen, ValueTypeErr,
ArrayType, ColumnType, Nullable, SeaRc, StringLen, ValueTypeErr,
extension::mysql::MySqlType, value::ValueType,
},
DbErr, DeriveValueType, QueryResult, TryFromU64, TryGetError, TryGetable, Value,
};
use serde::{Deserialize, Serialize};
use strum::{EnumString, IntoStaticStr};

View File

@@ -3,7 +3,7 @@ name = "lldap_validation"
version = "0.6.0"
authors = ["Simon Broeng Jensen <sbj@cwconsult.dk>"]
description = "Validation logic for LLDAP"
edition = "2021"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true

View File

@@ -2,7 +2,7 @@
name = "lldap_migration_tool"
version = "0.4.2"
description = "CLI migration tool to go from OpenLDAP to LLDAP"
edition = "2021"
edition.workspace = true
authors.workspace = true
homepage.workspace = true
license.workspace = true

View File

@@ -1,6 +1,6 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use ldap3::{ResultEntry, SearchEntry};
use requestty::{prompt_one, Question};
use requestty::{Question, prompt_one};
use smallvec::SmallVec;
use crate::lldap::User;

View File

@@ -1,12 +1,12 @@
use std::collections::{HashMap, HashSet};
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{Context, Result, anyhow, bail};
use graphql_client::GraphQLQuery;
use requestty::{prompt_one, Question};
use requestty::{Question, prompt_one};
use reqwest::blocking::{Client, ClientBuilder};
use smallvec::SmallVec;
use crate::ldap::{check_host_exists, LdapGroup};
use crate::ldap::{LdapGroup, check_host_exists};
pub struct GraphQLClient {
url: String,

View File

@@ -2,8 +2,8 @@
use std::collections::HashSet;
use anyhow::{anyhow, Result};
use requestty::{prompt_one, Question};
use anyhow::{Result, anyhow};
use requestty::{Question, prompt_one};
mod ldap;
mod lldap;

View File

@@ -3,7 +3,7 @@ name = "lldap"
version = "0.6.2-alpha"
description = "Super-simple and lightweight LDAP server"
categories = ["authentication", "command-line-utilities"]
edition = "2021"
edition.workspace = true
keywords = ["cli", "ldap", "graphql", "server", "authentication"]
authors.workspace = true
homepage.workspace = true

View File

@@ -1,4 +1,4 @@
use anyhow::{bail, Context as AnyhowContext, Result};
use anyhow::{Context as AnyhowContext, Result, bail};
use lldap_domain::types::{AttributeType, AttributeValue, JpegPhoto};
pub fn deserialize_attribute_value(

View File

@@ -1,6 +1,6 @@
use chrono::TimeZone;
use ldap3_proto::{
proto::LdapOp, LdapFilter, LdapPartialAttribute, LdapResultCode, LdapSearchResultEntry,
LdapFilter, LdapPartialAttribute, LdapResultCode, LdapSearchResultEntry, proto::LdapOp,
};
use tracing::{debug, instrument, warn};
@@ -9,10 +9,9 @@ use crate::domain::{
ldap::{
error::{LdapError, LdapResult},
utils::{
expand_attribute_wildcards, get_custom_attribute,
get_group_id_from_distinguished_name_or_plain_name,
get_user_id_from_distinguished_name_or_plain_name, map_group_field, ExpandedAttributes,
GroupFieldType, LdapInfo,
ExpandedAttributes, GroupFieldType, LdapInfo, expand_attribute_wildcards,
get_custom_attribute, get_group_id_from_distinguished_name_or_plain_name,
get_user_id_from_distinguished_name_or_plain_name, map_group_field,
},
},
schema::PublicSchema,
@@ -51,10 +50,12 @@ pub fn get_group_attribute(
vec![group.id.0.to_string().into_bytes()]
}
GroupFieldType::DisplayName => vec![group.display_name.to_string().into_bytes()],
GroupFieldType::CreationDate => vec![chrono::Utc
.from_utc_datetime(&group.creation_date)
.to_rfc3339()
.into_bytes()],
GroupFieldType::CreationDate => vec![
chrono::Utc
.from_utc_datetime(&group.creation_date)
.to_rfc3339()
.into_bytes(),
],
GroupFieldType::Member => group
.users
.iter()

View File

@@ -1,6 +1,6 @@
use chrono::TimeZone;
use ldap3_proto::{
proto::LdapOp, LdapFilter, LdapPartialAttribute, LdapResultCode, LdapSearchResultEntry,
LdapFilter, LdapPartialAttribute, LdapResultCode, LdapSearchResultEntry, proto::LdapOp,
};
use tracing::{debug, instrument, warn};
@@ -9,10 +9,9 @@ use crate::domain::{
ldap::{
error::{LdapError, LdapResult},
utils::{
expand_attribute_wildcards, get_custom_attribute,
get_group_id_from_distinguished_name_or_plain_name,
get_user_id_from_distinguished_name_or_plain_name, map_user_field, ExpandedAttributes,
LdapInfo, UserFieldType,
ExpandedAttributes, LdapInfo, UserFieldType, expand_attribute_wildcards,
get_custom_attribute, get_group_id_from_distinguished_name_or_plain_name,
get_user_id_from_distinguished_name_or_plain_name, map_user_field,
},
},
schema::PublicSchema,
@@ -74,10 +73,12 @@ pub fn get_user_attribute(
UserFieldType::PrimaryField(UserColumn::DisplayName) => {
vec![user.display_name.clone()?.into_bytes()]
}
UserFieldType::PrimaryField(UserColumn::CreationDate) => vec![chrono::Utc
.from_utc_datetime(&user.creation_date)
.to_rfc3339()
.into_bytes()],
UserFieldType::PrimaryField(UserColumn::CreationDate) => vec![
chrono::Utc
.from_utc_datetime(&user.creation_date)
.to_rfc3339()
.into_bytes(),
],
UserFieldType::Attribute(attr, _, _) => get_custom_attribute(&user.attributes, &attr)?,
UserFieldType::NoMatch => match attribute.as_str() {
"1.1" => return None,

View File

@@ -12,12 +12,12 @@ use lldap_domain_handlers::handler::{
};
use lldap_domain_model::{
error::{DomainError, Result},
model::{self, deserialize, GroupColumn, MembershipColumn},
model::{self, GroupColumn, MembershipColumn, deserialize},
};
use sea_orm::{
sea_query::{Alias, Cond, Expr, Func, IntoCondition, OnConflict, SimpleExpr},
ActiveModelTrait, ColumnTrait, DatabaseTransaction, EntityTrait, QueryFilter, QueryOrder,
QuerySelect, QueryTrait, Set, TransactionTrait,
sea_query::{Alias, Cond, Expr, Func, IntoCondition, OnConflict, SimpleExpr},
};
use tracing::instrument;

View File

@@ -1,13 +1,13 @@
use crate::domain::sql_tables::{DbConnection, SchemaVersion, LAST_SCHEMA_VERSION};
use crate::domain::sql_tables::{DbConnection, LAST_SCHEMA_VERSION, SchemaVersion};
use itertools::Itertools;
use lldap_domain::types::{AttributeType, GroupId, JpegPhoto, Serialized, UserId, Uuid};
use sea_orm::{
sea_query::{
all, BinOper, ColumnDef, Expr, ForeignKey, ForeignKeyAction, Func, Index, Query,
SimpleExpr, Table, Value,
},
ConnectionTrait, DatabaseTransaction, DbErr, DeriveIden, FromQueryResult, Iden, Order,
Statement, TransactionTrait,
sea_query::{
BinOper, ColumnDef, Expr, ForeignKey, ForeignKeyAction, Func, Index, Query, SimpleExpr,
Table, Value, all,
},
};
use serde::{Deserialize, Serialize};
use tracing::{error, info, instrument, warn};

View File

@@ -1,5 +1,5 @@
use super::{
opaque_handler::{login, registration, OpaqueHandler},
opaque_handler::{OpaqueHandler, login, registration},
sql_backend_handler::SqlBackendHandler,
};
use async_trait::async_trait;

View File

@@ -252,27 +252,31 @@ mod tests {
is_hardcoded: false,
is_readonly: false,
};
assert!(fixture
.handler
.get_schema()
.await
.unwrap()
.user_attributes
.attributes
.contains(&expected_value));
assert!(
fixture
.handler
.get_schema()
.await
.unwrap()
.user_attributes
.attributes
.contains(&expected_value)
);
fixture
.handler
.delete_user_attribute(&"new_attribute".into())
.await
.unwrap();
assert!(!fixture
.handler
.get_schema()
.await
.unwrap()
.user_attributes
.attributes
.contains(&expected_value));
assert!(
!fixture
.handler
.get_schema()
.await
.unwrap()
.user_attributes
.attributes
.contains(&expected_value)
);
}
#[tokio::test]
@@ -336,27 +340,31 @@ mod tests {
is_hardcoded: false,
is_readonly: false,
};
assert!(fixture
.handler
.get_schema()
.await
.unwrap()
.group_attributes
.attributes
.contains(&expected_value));
assert!(
fixture
.handler
.get_schema()
.await
.unwrap()
.group_attributes
.attributes
.contains(&expected_value)
);
fixture
.handler
.delete_group_attribute(&"new_attriBUte".into())
.await
.unwrap();
assert!(!fixture
.handler
.get_schema()
.await
.unwrap()
.group_attributes
.attributes
.contains(&expected_value));
assert!(
!fixture
.handler
.get_schema()
.await
.unwrap()
.group_attributes
.attributes
.contains(&expected_value)
);
}
#[tokio::test]
@@ -396,12 +404,14 @@ mod tests {
.delete_user_object_class(&new_object_class)
.await
.unwrap();
assert!(fixture
.handler
.get_schema()
.await
.unwrap()
.extra_user_object_classes
.is_empty());
assert!(
fixture
.handler
.get_schema()
.await
.unwrap()
.extra_user_object_classes
.is_empty()
);
}
}

View File

@@ -1,8 +1,8 @@
use crate::domain::sql_migrations::{
get_schema_version, migrate_from_version, upgrade_to_v1, Metadata,
Metadata, get_schema_version, migrate_from_version, upgrade_to_v1,
};
use sea_orm::{
sea_query::Query, ConnectionTrait, DeriveValueType, Iden, QueryResult, TryGetable, Value,
ConnectionTrait, DeriveValueType, Iden, QueryResult, TryGetable, Value, sea_query::Query,
};
use serde::{Deserialize, Serialize};

View File

@@ -9,14 +9,14 @@ use lldap_domain_handlers::handler::{
};
use lldap_domain_model::{
error::{DomainError, Result},
model::{self, deserialize, GroupColumn, UserColumn},
model::{self, GroupColumn, UserColumn, deserialize},
};
use sea_orm::{
sea_query::{
query::OnConflict, Alias, Cond, Expr, Func, IntoColumnRef, IntoCondition, SimpleExpr,
},
ActiveModelTrait, ActiveValue, ColumnTrait, DatabaseTransaction, EntityTrait, ModelTrait,
QueryFilter, QueryOrder, QuerySelect, QueryTrait, Set, TransactionTrait,
sea_query::{
Alias, Cond, Expr, Func, IntoColumnRef, IntoCondition, SimpleExpr, query::OnConflict,
},
};
use std::collections::HashSet;
use tracing::instrument;
@@ -800,7 +800,7 @@ mod tests {
#[tokio::test]
async fn test_get_user_groups() {
let fixture = TestFixture::new().await;
let get_group_ids = |user: &'static str| async {
let get_group_ids = async |user: &'static str| {
let mut groups = fixture
.handler
.get_user_groups(&UserId::new(user))

View File

@@ -183,14 +183,14 @@ impl<Handler: BackendHandler> AccessControlledBackendHandler<Handler> {
pub fn get_admin_handler(
&self,
validation_result: &ValidationResults,
) -> Option<&impl AdminBackendHandler> {
) -> Option<&(impl AdminBackendHandler + use<Handler>)> {
validation_result.is_admin().then_some(&self.handler)
}
pub fn get_readonly_handler(
&self,
validation_result: &ValidationResults,
) -> Option<&impl ReadonlyBackendHandler> {
) -> Option<&(impl ReadonlyBackendHandler + use<Handler>)> {
validation_result.can_read_all().then_some(&self.handler)
}
@@ -198,7 +198,7 @@ impl<Handler: BackendHandler> AccessControlledBackendHandler<Handler> {
&self,
validation_result: &ValidationResults,
user_id: &UserId,
) -> Option<&impl UserWriteableBackendHandler> {
) -> Option<&(impl UserWriteableBackendHandler + use<Handler>)> {
validation_result
.can_write(user_id)
.then_some(&self.handler)
@@ -208,7 +208,7 @@ impl<Handler: BackendHandler> AccessControlledBackendHandler<Handler> {
&self,
validation_result: &ValidationResults,
user_id: &UserId,
) -> Option<&impl UserReadableBackendHandler> {
) -> Option<&(impl UserReadableBackendHandler + use<Handler>)> {
validation_result.can_read(user_id).then_some(&self.handler)
}

View File

@@ -1,13 +1,14 @@
use actix_web::{
HttpRequest, HttpResponse,
cookie::{Cookie, SameSite},
dev::{Service, ServiceRequest, ServiceResponse, Transform},
error::{ErrorBadRequest, ErrorUnauthorized},
web, HttpRequest, HttpResponse,
web,
};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use anyhow::Result;
use chrono::prelude::*;
use futures::future::{ok, Ready};
use futures::future::{Ready, ok};
use futures_util::FutureExt;
use hmac::Hmac;
use jwt::{SignWithKey, VerifyWithKey};
@@ -22,7 +23,7 @@ use time::ext::NumericalDuration;
use tracing::{debug, info, instrument, warn};
use lldap_auth::{
access_control::ValidationResults, login, password_reset, registration, JWTClaims,
JWTClaims, access_control::ValidationResults, login, password_reset, registration,
};
use lldap_domain::types::{GroupDetails, GroupName, UserId};
use lldap_domain_handlers::handler::{
@@ -35,7 +36,7 @@ use crate::{
infra::{
access_control::{ReadonlyBackendHandler, UserReadableBackendHandler},
tcp_backend_handler::*,
tcp_server::{error_to_http_response, AppState, TcpError, TcpResult},
tcp_server::{AppState, TcpError, TcpResult, error_to_http_response},
},
};

View File

@@ -1,6 +1,6 @@
use std::str::FromStr;
use clap::{builder::EnumValueParser, Parser};
use clap::{Parser, builder::EnumValueParser};
use lettre::message::Mailbox;
use serde::{Deserialize, Serialize};
use strum::{EnumString, IntoStaticStr};

View File

@@ -10,13 +10,13 @@ use crate::{
database_string::DatabaseUrl,
},
};
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use figment::{
providers::{Env, Format, Serialized, Toml},
Figment,
providers::{Env, Format, Serialized, Toml},
};
use figment_file_provider_adapter::FileAdapter;
use lldap_auth::opaque::{server::ServerSetup, KeyPair};
use lldap_auth::opaque::{KeyPair, server::ServerSetup};
use lldap_domain::types::{AttributeName, UserId};
use secstr::SecUtf8;
use serde::{Deserialize, Serialize};
@@ -219,23 +219,33 @@ pub fn compare_private_key_hashes(
PrivateKeyLocation::KeyFile(old_location, file_path),
PrivateKeyLocation::KeySeed(new_location),
) => {
bail!("The private key is configured to be generated from a seed (from {new_location:?}), but it used to come from the file {file_path:?} (defined in {old_location:?}). Did you just upgrade from <=v0.4 to >=v0.5? The key seed was not supported, revert to just using the file.");
bail!(
"The private key is configured to be generated from a seed (from {new_location:?}), but it used to come from the file {file_path:?} (defined in {old_location:?}). Did you just upgrade from <=v0.4 to >=v0.5? The key seed was not supported, revert to just using the file."
);
}
(PrivateKeyLocation::Default, PrivateKeyLocation::KeySeed(new_location)) => {
bail!("The private key is configured to be generated from a seed (from {new_location:?}), but it used to come from default key file \"server_key\". Did you just upgrade from <=v0.4 to >=v0.5? The key seed was not yet supported, revert to just using the file.");
bail!(
"The private key is configured to be generated from a seed (from {new_location:?}), but it used to come from default key file \"server_key\". Did you just upgrade from <=v0.4 to >=v0.5? The key seed was not yet supported, revert to just using the file."
);
}
(
PrivateKeyLocation::KeyFile(old_location, old_path),
PrivateKeyLocation::KeyFile(new_location, new_path),
) => {
if old_path == new_path {
bail!("The contents of the private key file from {old_path:?} have changed. This usually means that the file was deleted and re-created. If using docker, make sure that the folder is made persistent (by mounting a volume or a directory). If you have several instances of LLDAP, make sure they share the same file (or switch to a key seed).");
bail!(
"The contents of the private key file from {old_path:?} have changed. This usually means that the file was deleted and re-created. If using docker, make sure that the folder is made persistent (by mounting a volume or a directory). If you have several instances of LLDAP, make sure they share the same file (or switch to a key seed)."
);
} else {
bail!("The private key file used to be {old_path:?} (defined in {old_location:?}), but now is {new_path:?} (defined in {new_location:?}. Make sure to copy the old file in the new location.");
bail!(
"The private key file used to be {old_path:?} (defined in {old_location:?}), but now is {new_path:?} (defined in {new_location:?}. Make sure to copy the old file in the new location."
);
}
}
(old_location, new_location) => {
bail!("The private key has changed. It used to come from {old_location:?}, but now it comes from {new_location:?}.");
bail!(
"The private key has changed. It used to come from {old_location:?}, but now it comes from {new_location:?}."
);
}
}
}
@@ -362,7 +372,9 @@ fn get_server_setup<L: Into<PrivateKeyLocationOrFigment>>(
file_path
);
} else if file_path == "server_key" {
eprintln!("WARNING: A key_seed was given, we will ignore the key_file and generate one from the seed! Set key_file to an empty string in the config to silence this message.");
eprintln!(
"WARNING: A key_seed was given, we will ignore the key_file and generate one from the seed! Set key_file to an empty string in the config to silence this message."
);
} else {
println!("Generating the private key from the key_seed");
}
@@ -609,7 +621,7 @@ where
figment_config,
)?);
if config.jwt_secret.is_none() {
use rand::{seq::SliceRandom, Rng};
use rand::{Rng, seq::SliceRandom};
struct Symbols;
impl rand::prelude::Distribution<char> for Symbols {
@@ -617,18 +629,22 @@ where
*b"01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+,-./:;<=>?_~!@#$%^&*()[]{}:;".choose(rng).unwrap() as char
}
}
bail!("The JWT secret must be initialized to a random string, preferably at least 32 characters long. \
bail!(
"The JWT secret must be initialized to a random string, preferably at least 32 characters long. \
Either set the `jwt_secret` config value or the `LLDAP_JWT_SECRET` environment variable. \
You can generate the value by running\n\
LC_ALL=C tr -dc 'A-Za-z0-9!#%&'\\''()*+,-./:;<=>?@[\\]^_{{|}}~' </dev/urandom | head -c 32; echo ''\n\
or you can use this random value: {}",
rand::thread_rng()
.sample_iter(&Symbols)
.take(32)
.collect::<String>());
rand::thread_rng()
.sample_iter(&Symbols)
.take(32)
.collect::<String>()
);
}
if config.smtp_options.tls_required.is_some() {
println!("DEPRECATED: smtp_options.tls_required field is deprecated, it never did anything. You can replace it with smtp_options.smtp_encryption.");
println!(
"DEPRECATED: smtp_options.tls_required field is deprecated, it never did anything. You can replace it with smtp_options.smtp_encryption."
);
}
Ok(config)
}

View File

@@ -11,14 +11,14 @@ use crate::infra::{
use actix_web::FromRequest;
use actix_web::HttpMessage;
use actix_web::{error::JsonPayloadError, web, Error, HttpRequest, HttpResponse};
use actix_web::{Error, HttpRequest, HttpResponse, error::JsonPayloadError, web};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use juniper::{
http::{
graphiql::graphiql_source, playground::playground_source, GraphQLBatchRequest,
GraphQLRequest,
},
EmptySubscription, FieldError, RootNode, ScalarValue,
http::{
GraphQLBatchRequest, GraphQLRequest, graphiql::graphiql_source,
playground::playground_source,
},
};
use lldap_auth::{access_control::ValidationResults, types::UserId};
use lldap_domain_handlers::handler::BackendHandler;
@@ -48,18 +48,18 @@ impl<Handler: BackendHandler> Context<Handler> {
}
}
pub fn get_admin_handler(&self) -> Option<&impl AdminBackendHandler> {
pub fn get_admin_handler(&self) -> Option<&(impl AdminBackendHandler + use<Handler>)> {
self.handler.get_admin_handler(&self.validation_result)
}
pub fn get_readonly_handler(&self) -> Option<&impl ReadonlyBackendHandler> {
pub fn get_readonly_handler(&self) -> Option<&(impl ReadonlyBackendHandler + use<Handler>)> {
self.handler.get_readonly_handler(&self.validation_result)
}
pub fn get_writeable_handler(
&self,
user_id: &UserId,
) -> Option<&impl UserWriteableBackendHandler> {
) -> Option<&(impl UserWriteableBackendHandler + use<Handler>)> {
self.handler
.get_writeable_handler(&self.validation_result, user_id)
}
@@ -67,7 +67,7 @@ impl<Handler: BackendHandler> Context<Handler> {
pub fn get_readable_handler(
&self,
user_id: &UserId,
) -> Option<&impl UserReadableBackendHandler> {
) -> Option<&(impl UserReadableBackendHandler + use<Handler>)> {
self.handler
.get_readable_handler(&self.validation_result, user_id)
}

View File

@@ -7,11 +7,11 @@ use crate::{
AdminBackendHandler, ReadonlyBackendHandler, UserReadableBackendHandler,
UserWriteableBackendHandler,
},
graphql::api::{field_error_callback, Context},
graphql::api::{Context, field_error_callback},
},
};
use anyhow::{anyhow, Context as AnyhowContext};
use juniper::{graphql_object, FieldError, FieldResult, GraphQLInputObject, GraphQLObject};
use anyhow::{Context as AnyhowContext, anyhow};
use juniper::{FieldError, FieldResult, GraphQLInputObject, GraphQLObject, graphql_object};
use lldap_domain::{
requests::{
CreateAttributeRequest, CreateGroupRequest, CreateUserRequest, UpdateGroupRequest,
@@ -24,8 +24,8 @@ use lldap_domain::{
},
};
use lldap_domain_handlers::handler::BackendHandler;
use lldap_validation::attributes::{validate_attribute_name, ALLOWED_CHARACTERS_DESCRIPTION};
use tracing::{debug, debug_span, Instrument, Span};
use lldap_validation::attributes::{ALLOWED_CHARACTERS_DESCRIPTION, validate_attribute_name};
use tracing::{Instrument, Span, debug, debug_span};
#[derive(PartialEq, Eq, Debug)]
/// The top-level GraphQL mutation type.
@@ -785,8 +785,8 @@ mod tests {
use super::*;
use crate::infra::{graphql::query::Query, test_utils::MockTestBackendHandler};
use juniper::{
execute, graphql_value, DefaultScalarValue, EmptySubscription, GraphQLType, InputValue,
RootNode, Variables,
DefaultScalarValue, EmptySubscription, GraphQLType, InputValue, RootNode, Variables,
execute, graphql_value,
};
use lldap_auth::access_control::{Permission, ValidationResults};
use lldap_domain::types::{AttributeName, AttributeType};
@@ -897,9 +897,11 @@ mod tests {
let expected_error_msg =
"Cannot create attribute with invalid name. Valid characters: a-z, A-Z, 0-9, and dash (-). Invalid chars found: _"
.to_string();
assert!(errors
.iter()
.all(|e| e.error().message() == expected_error_msg));
assert!(
errors
.iter()
.all(|e| e.error().message() == expected_error_msg)
);
}
Err(_) => {
panic!();
@@ -1000,9 +1002,11 @@ mod tests {
let expected_error_msg =
"Cannot create attribute with invalid name. Valid characters: a-z, A-Z, 0-9, and dash (-). Invalid chars found: _"
.to_string();
assert!(errors
.iter()
.all(|e| e.error().message() == expected_error_msg));
assert!(
errors
.iter()
.all(|e| e.error().message() == expected_error_msg)
);
}
Err(_) => {
panic!();

View File

@@ -3,24 +3,24 @@ use std::sync::Arc;
use crate::{
domain::{
deserialize::deserialize_attribute_value,
ldap::utils::{map_user_field, UserFieldType},
ldap::utils::{UserFieldType, map_user_field},
schema::PublicSchema,
},
infra::{
access_control::{ReadonlyBackendHandler, UserReadableBackendHandler},
graphql::api::{field_error_callback, Context},
graphql::api::{Context, field_error_callback},
},
};
use anyhow::Context as AnyhowContext;
use chrono::TimeZone;
use juniper::{graphql_object, FieldResult, GraphQLInputObject};
use juniper::{FieldResult, GraphQLInputObject, graphql_object};
use lldap_domain::types::{
AttributeType, Cardinality, GroupDetails, GroupId, LdapObjectClass, UserId,
};
use lldap_domain_handlers::handler::{BackendHandler, ReadSchemaBackendHandler};
use lldap_domain_model::model::UserColumn;
use serde::{Deserialize, Serialize};
use tracing::{debug, debug_span, Instrument, Span};
use tracing::{Instrument, Span, debug, debug_span};
type DomainRequestFilter = lldap_domain_handlers::handler::UserRequestFilter;
type DomainUser = lldap_domain::types::User;
@@ -786,11 +786,11 @@ impl<Handler: BackendHandler> AttributeValue<Handler> {
#[cfg(test)]
mod tests {
use super::*;
use crate::infra::test_utils::{setup_default_schema, MockTestBackendHandler};
use crate::infra::test_utils::{MockTestBackendHandler, setup_default_schema};
use chrono::TimeZone;
use juniper::{
execute, graphql_value, DefaultScalarValue, EmptyMutation, EmptySubscription, GraphQLType,
RootNode, Variables,
DefaultScalarValue, EmptyMutation, EmptySubscription, GraphQLType, RootNode, Variables,
execute, graphql_value,
};
use lldap_auth::access_control::{Permission, ValidationResults};
use lldap_domain::{

View File

@@ -1,12 +1,12 @@
use crate::infra::{configuration::LdapsOptions, ldap_server::read_certificates};
use anyhow::{anyhow, bail, ensure, Context, Result};
use anyhow::{Context, Result, anyhow, bail, ensure};
use futures_util::SinkExt;
use ldap3_proto::{
LdapCodec,
proto::{
LdapDerefAliases, LdapFilter, LdapMsg, LdapOp, LdapSearchRequest, LdapSearchResultEntry,
LdapSearchScope,
},
LdapCodec,
};
use tokio::net::TcpStream;
use tokio_rustls::TlsConnector as RustlsTlsConnector;

View File

@@ -1,6 +1,6 @@
use sea_orm::{
sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Table},
ConnectionTrait, DeriveIden,
sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Table},
};
pub use crate::domain::{sql_migrations::Users, sql_tables::DbConnection};

View File

@@ -6,7 +6,7 @@ use crate::{
group::{convert_groups_to_ldap_op, get_groups_list},
user::{convert_users_to_ldap_op, get_user_list},
utils::{
get_user_id_from_distinguished_name, is_subtree, parse_distinguished_name, LdapInfo,
LdapInfo, get_user_id_from_distinguished_name, is_subtree, parse_distinguished_name,
},
},
opaque_handler::OpaqueHandler,
@@ -175,9 +175,11 @@ fn root_dse_response(base_dn: &str) -> LdapOp {
},
LdapPartialAttribute {
atype: "vendorVersion".to_string(),
vals: vec![concat!("lldap_", env!("CARGO_PKG_VERSION"))
.to_string()
.into_bytes()],
vals: vec![
concat!("lldap_", env!("CARGO_PKG_VERSION"))
.to_string()
.into_bytes(),
],
},
LdapPartialAttribute {
atype: "supportedLDAPVersion".to_string(),
@@ -229,13 +231,13 @@ impl<Backend> LdapHandler<Backend> {
}
impl<Backend: LoginHandler> LdapHandler<Backend> {
pub fn get_login_handler(&self) -> &impl LoginHandler {
pub fn get_login_handler(&self) -> &(impl LoginHandler + use<Backend>) {
self.backend_handler.unsafe_get_handler()
}
}
impl<Backend: OpaqueHandler> LdapHandler<Backend> {
pub fn get_opaque_handler(&self) -> &impl OpaqueHandler {
pub fn get_opaque_handler(&self) -> &(impl OpaqueHandler + use<Backend>) {
self.backend_handler.unsafe_get_handler()
}
}
@@ -589,7 +591,7 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
x
}
let get_user_list = cast(|filter: &LdapFilter| async {
let get_user_list = cast(async |filter: &LdapFilter| {
let need_groups = request
.attrs
.iter()
@@ -927,7 +929,7 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
#[cfg(test)]
mod tests {
use super::*;
use crate::infra::test_utils::{setup_default_schema, MockTestBackendHandler};
use crate::infra::test_utils::{MockTestBackendHandler, setup_default_schema};
use chrono::TimeZone;
use ldap3_proto::proto::{
LdapDerefAliases, LdapSearchScope, LdapSubstringFilter, LdapWhoamiRequest,
@@ -2308,11 +2310,13 @@ mod tests {
},
LdapPartialAttribute {
atype: "createtimestamp".to_string(),
vals: vec![chrono::Utc
.timestamp_opt(0, 0)
.unwrap()
.to_rfc3339()
.into_bytes()],
vals: vec![
chrono::Utc
.timestamp_opt(0, 0)
.unwrap()
.to_rfc3339()
.into_bytes(),
],
},
LdapPartialAttribute {
atype: "entryuuid".to_string(),

View File

@@ -8,9 +8,9 @@ use crate::{
};
use actix_rt::net::TcpStream;
use actix_server::ServerBuilder;
use actix_service::{fn_service, ServiceFactoryExt};
use anyhow::{anyhow, Context, Result};
use ldap3_proto::{control::LdapControl, proto::LdapMsg, proto::LdapOp, LdapCodec};
use actix_service::{ServiceFactoryExt, fn_service};
use anyhow::{Context, Result, anyhow};
use ldap3_proto::{LdapCodec, control::LdapControl, proto::LdapMsg, proto::LdapOp};
use lldap_domain::types::AttributeName;
use lldap_domain_handlers::handler::{BackendHandler, LoginHandler};
use rustls::PrivateKey;

View File

@@ -1,10 +1,10 @@
use crate::infra::configuration::Configuration;
use actix_web::{
dev::{ServiceRequest, ServiceResponse},
Error,
dev::{ServiceRequest, ServiceResponse},
};
use std::env;
use tracing::{debug, error, Span};
use tracing::{Span, debug, error};
use tracing_actix_web::RootSpanBuilder;
use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};

View File

@@ -1,8 +1,8 @@
use crate::infra::{cli::SmtpEncryption, configuration::MailOptions};
use anyhow::{anyhow, Ok, Result};
use anyhow::{Ok, Result, anyhow};
use lettre::{
message::Mailbox, transport::smtp::authentication::Credentials, AsyncSmtpTransport,
AsyncTransport, Message, Tokio1Executor,
AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor, message::Mailbox,
transport::smtp::authentication::Credentials,
};
use std::time::Duration;
use tokio::time::sleep;

View File

@@ -8,14 +8,14 @@ use lldap_domain_model::{
model::{self, JwtRefreshStorageColumn, JwtStorageColumn, PasswordResetTokensColumn},
};
use sea_orm::{
sea_query::{Cond, Expr},
ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, QuerySelect,
sea_query::{Cond, Expr},
};
use std::collections::HashSet;
use tracing::{debug, instrument};
fn gen_random_string(len: usize) -> String {
use rand::{distributions::Alphanumeric, rngs::SmallRng, Rng, SeedableRng};
use rand::{Rng, SeedableRng, distributions::Alphanumeric, rngs::SmallRng};
let mut rng = SmallRng::from_entropy();
std::iter::repeat(())
.map(|()| rng.sample(Alphanumeric))

View File

@@ -9,10 +9,10 @@ use crate::{
},
};
use actix_files::Files;
use actix_http::{header, HttpServiceBuilder};
use actix_http::{HttpServiceBuilder, header};
use actix_server::ServerBuilder;
use actix_service::map_config;
use actix_web::{dev::AppConfig, guard, web, App, HttpResponse, Responder};
use actix_web::{App, HttpResponse, Responder, dev::AppConfig, guard, web};
use anyhow::{Context, Result};
use hmac::Hmac;
use lldap_domain_handlers::handler::{BackendHandler, LoginHandler};
@@ -136,7 +136,7 @@ fn http_config<Backend>(
}))
.route(
"/health",
web::get().to(|| async { HttpResponse::Ok().finish() }),
web::get().to(async || HttpResponse::Ok().finish()),
)
.route("/settings", web::get().to(get_settings::<Backend>))
.service(
@@ -180,22 +180,22 @@ pub(crate) struct AppState<Backend> {
}
impl<Backend: BackendHandler> AppState<Backend> {
pub fn get_readonly_handler(&self) -> &impl ReadonlyBackendHandler {
pub fn get_readonly_handler(&self) -> &(impl ReadonlyBackendHandler + use<Backend>) {
self.backend_handler.unsafe_get_handler()
}
}
impl<Backend: TcpBackendHandler> AppState<Backend> {
pub fn get_tcp_handler(&self) -> &impl TcpBackendHandler {
pub fn get_tcp_handler(&self) -> &(impl TcpBackendHandler + use<Backend>) {
self.backend_handler.unsafe_get_handler()
}
}
impl<Backend: OpaqueHandler> AppState<Backend> {
pub fn get_opaque_handler(&self) -> &impl OpaqueHandler {
pub fn get_opaque_handler(&self) -> &(impl OpaqueHandler + use<Backend>) {
self.backend_handler.unsafe_get_handler()
}
}
impl<Backend: LoginHandler> AppState<Backend> {
pub fn get_login_handler(&self) -> &impl LoginHandler {
pub fn get_login_handler(&self) -> &(impl LoginHandler + use<Backend>) {
self.backend_handler.unsafe_get_handler()
}
}
@@ -218,7 +218,10 @@ where
let mail_options = config.smtp_options.clone();
let verbose = config.verbose;
if !assets_path.join("index.html").exists() {
warn!("Cannot find {}, please ensure that assets_path is set correctly and that the front-end files exist.", assets_path.to_string_lossy())
warn!(
"Cannot find {}, please ensure that assets_path is set correctly and that the front-end files exist.",
assets_path.to_string_lossy()
)
}
info!("Starting the API/web server on port {}", config.http_port);
server_builder

View File

@@ -13,7 +13,7 @@ use crate::{
},
infra::{
cli::*,
configuration::{compare_private_key_hashes, Configuration},
configuration::{Configuration, compare_private_key_hashes},
database_string::DatabaseUrl,
db_cleaner::Scheduler,
healthcheck, mail,
@@ -21,10 +21,10 @@ use crate::{
};
use actix::Actor;
use actix_server::ServerBuilder;
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{Context, Result, anyhow, bail};
use futures_util::TryFutureExt;
use sea_orm::{Database, DatabaseConnection};
use tracing::{debug, error, info, instrument, span, warn, Instrument, Level};
use tracing::{Instrument, Level, debug, error, info, instrument, span, warn};
use lldap_domain::requests::{CreateGroupRequest, CreateUserRequest};
use lldap_domain_handlers::handler::{
@@ -35,7 +35,7 @@ use lldap_domain_handlers::handler::{
mod domain;
mod infra;
const ADMIN_PASSWORD_MISSING_ERROR : &str = "The LDAP admin password must be initialized. \
const ADMIN_PASSWORD_MISSING_ERROR: &str = "The LDAP admin password must be initialized. \
Either set the `ldap_user_pass` config value or the `LLDAP_LDAP_USER_PASS` environment variable. \
A minimum of 8 characters is recommended.";
@@ -133,7 +133,9 @@ async fn set_up_server(config: Configuration) -> Result<ServerBuilder> {
force_update_private_key,
) {
(Ok(false), true) => {
bail!("The private key has not changed, but force_update_private_key/LLDAP_FORCE_UPDATE_PRIVATE_KEY is set to true. Please set force_update_private_key to false and restart the server.");
bail!(
"The private key has not changed, but force_update_private_key/LLDAP_FORCE_UPDATE_PRIVATE_KEY is set to true. Please set force_update_private_key to false and restart the server."
);
}
(Ok(true), _) | (Err(_), true) => {
set_private_key_info(&sql_pool, private_key_info).await?;
@@ -159,7 +161,9 @@ async fn set_up_server(config: Configuration) -> Result<ServerBuilder> {
false
};
if !admin_present {
warn!("Could not find an admin user, trying to create the user \"admin\" with the config-provided password");
warn!(
"Could not find an admin user, trying to create the user \"admin\" with the config-provided password"
);
create_admin_user(&backend_handler, &config)
.await
.map_err(|e| anyhow!("Error setting up admin login/account: {:#}", e))
@@ -189,7 +193,9 @@ async fn set_up_server(config: Configuration) -> Result<ServerBuilder> {
))?;
}
if config.force_update_private_key || config.force_ldap_user_pass_reset.is_yes() {
bail!("Restart the server without --force-update-private-key or --force-ldap-user-pass-reset to continue.");
bail!(
"Restart the server without --force-update-private-key or --force-ldap-user-pass-reset to continue."
);
}
let server_builder = infra::ldap_server::build_ldap_server(
&config,

View File

@@ -2,8 +2,8 @@ use crate::common::{
auth::get_token,
env,
graphql::{
add_user_to_group, create_group, create_user, delete_group_query, delete_user_query, post,
AddUserToGroup, CreateGroup, CreateUser, DeleteGroupQuery, DeleteUserQuery,
add_user_to_group, create_group, create_user, delete_group_query, delete_user_query, post,
},
};
use assert_cmd::prelude::*;

View File

@@ -1,5 +1,5 @@
use crate::common::env;
use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result, anyhow};
use graphql_client::GraphQLQuery;
use reqwest::blocking::Client;

View File

@@ -1,8 +1,8 @@
use crate::common::{
auth::get_token,
env,
fixture::{new_id, LLDAPFixture, User},
graphql::{get_user_details, list_users, post, GetUserDetails, ListUsers},
fixture::{LLDAPFixture, User, new_id},
graphql::{GetUserDetails, ListUsers, get_user_details, list_users, post},
};
use reqwest::blocking::ClientBuilder;
use serial_test::file_serial;

View File

@@ -2,7 +2,7 @@ use std::collections::HashSet;
use crate::common::{
env,
fixture::{new_id, LLDAPFixture, User},
fixture::{LLDAPFixture, User, new_id},
};
use ldap3::{LdapConn, Scope, SearchEntry};
use serial_test::file_serial;

View File

@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
use crate::common::{
env,
fixture::{new_id, LLDAPFixture, User},
fixture::{LLDAPFixture, User, new_id},
};
use ldap3::{LdapConn, Scope, SearchEntry, SearchResult};
use serial_test::file_serial;
@@ -43,19 +43,25 @@ fn basic_users_search() {
.expect("failed to find users"),
);
assert!(found_users.contains_key(&user1_name));
assert!(found_users
.get(&user1_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", &group1_name, base_dn).as_str()));
assert!(
found_users
.get(&user1_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", &group1_name, base_dn).as_str())
);
assert!(found_users.contains_key(&user2_name));
assert!(found_users
.get(&user2_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", &group1_name, base_dn).as_str()));
assert!(found_users
.get(&user2_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", &group2_name, base_dn).as_str()));
assert!(
found_users
.get(&user2_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", &group1_name, base_dn).as_str())
);
assert!(
found_users
.get(&user2_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", &group2_name, base_dn).as_str())
);
assert!(found_users.contains_key(&user3_name));
assert!(found_users.get(&user3_name).unwrap().is_empty());
ldap.unbind().expect("failed to unbind ldap connection");
@@ -87,10 +93,12 @@ fn admin_search() {
);
assert!(found_users.contains_key(&admin_name));
assert!(found_users
.get(&admin_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", admin_group_name, base_dn).as_str()));
assert!(
found_users
.get(&admin_name)
.unwrap()
.contains(format!("cn={},ou=groups,{}", admin_group_name, base_dn).as_str())
);
ldap.unbind().expect("failed to unbind ldap connection");
}

View File

@@ -2,7 +2,7 @@
name = "lldap_set_password"
version = "0.1.0"
description = "CLI tool to set a user password in LLDAP"
edition = "2021"
edition.workspace = true
authors.workspace = true
homepage.workspace = true
license.workspace = true

View File

@@ -1,4 +1,4 @@
use anyhow::{bail, ensure, Context, Result};
use anyhow::{Context, Result, bail, ensure};
use clap::Parser;
use lldap_auth::{opaque, registration};
use reqwest::Url;