mirror of
https://github.com/lldap/lldap.git
synced 2026-03-31 15:07:48 +01:00
chore: Migrate all the crates to edition 2024
This commit is contained in:
committed by
nitnelave
parent
e18f2af54f
commit
ba9bcb3894
+1
-1
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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!();
|
||||
|
||||
@@ -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::{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
+13
-7
@@ -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,
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+25
-17
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user