mirror of https://github.com/lldap/lldap.git
server: Add missing unique indices on lowercase email/group names, fix memberof lookup
This commit is contained in:
parent
959bb907d8
commit
a1eb708cf3
|
@ -195,6 +195,10 @@ fn convert_user_filter(
|
|||
UserFieldType::PrimaryField(UserColumn::UserId) => {
|
||||
Ok(UserRequestFilter::UserId(UserId::new(&value)))
|
||||
}
|
||||
UserFieldType::PrimaryField(UserColumn::Email) => Ok(UserRequestFilter::Equality(
|
||||
UserColumn::LowercaseEmail,
|
||||
value,
|
||||
)),
|
||||
UserFieldType::PrimaryField(field) => Ok(UserRequestFilter::Equality(field, value)),
|
||||
UserFieldType::Attribute(field, typ, is_list) => {
|
||||
get_user_attribute_equality_filter(&field, typ, is_list, &value)
|
||||
|
@ -269,6 +273,10 @@ fn convert_user_filter(
|
|||
),
|
||||
}),
|
||||
UserFieldType::NoMatch => Ok(UserRequestFilter::from(false)),
|
||||
UserFieldType::PrimaryField(UserColumn::Email) => Ok(UserRequestFilter::SubString(
|
||||
UserColumn::LowercaseEmail,
|
||||
substring_filter.clone().into(),
|
||||
)),
|
||||
UserFieldType::PrimaryField(field) => Ok(UserRequestFilter::SubString(
|
||||
field,
|
||||
substring_filter.clone().into(),
|
||||
|
|
|
@ -67,7 +67,7 @@ fn get_group_filter_expr(filter: GroupRequestFilter) -> Cond {
|
|||
.into_condition(),
|
||||
DisplayNameSubString(filter) => SimpleExpr::FunctionCall(Func::lower(Expr::col((
|
||||
group_table,
|
||||
GroupColumn::DisplayName,
|
||||
GroupColumn::LowercaseDisplayName,
|
||||
))))
|
||||
.like(filter.to_sql_filter())
|
||||
.into_condition(),
|
||||
|
@ -606,4 +606,25 @@ mod tests {
|
|||
let details = fixture.handler.get_group_details(group_id).await.unwrap();
|
||||
assert_eq!(details.attributes, Vec::new());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_group_duplicate_name() {
|
||||
let fixture = TestFixture::new().await;
|
||||
fixture
|
||||
.handler
|
||||
.create_group(CreateGroupRequest {
|
||||
display_name: "New Group".into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
fixture
|
||||
.handler
|
||||
.create_group(CreateGroupRequest {
|
||||
display_name: "neW group".into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1090,6 +1090,47 @@ async fn migrate_to_v9(transaction: DatabaseTransaction) -> Result<DatabaseTrans
|
|||
Ok(transaction)
|
||||
}
|
||||
|
||||
async fn migrate_to_v10(transaction: DatabaseTransaction) -> Result<DatabaseTransaction, DbErr> {
|
||||
let builder = transaction.get_database_backend();
|
||||
if let Err(e) = transaction
|
||||
.execute(
|
||||
builder.build(
|
||||
Index::create()
|
||||
.if_not_exists()
|
||||
.name("unique-group-id")
|
||||
.table(Groups::Table)
|
||||
.col(Groups::LowercaseDisplayName)
|
||||
.unique(),
|
||||
),
|
||||
)
|
||||
.await
|
||||
{
|
||||
error!(
|
||||
r#"Found several groups with the same (case-insensitive) display name. Please delete the duplicates"#
|
||||
);
|
||||
return Err(e);
|
||||
}
|
||||
if let Err(e) = transaction
|
||||
.execute(
|
||||
builder.build(
|
||||
Index::create()
|
||||
.if_not_exists()
|
||||
.name("unique-user-lower-email")
|
||||
.table(Users::Table)
|
||||
.col(Users::LowercaseEmail)
|
||||
.unique(),
|
||||
),
|
||||
)
|
||||
.await
|
||||
{
|
||||
error!(
|
||||
r#"Found several users with the same (case-insensitive) email. Please delete the duplicates"#
|
||||
);
|
||||
return Err(e);
|
||||
}
|
||||
Ok(transaction)
|
||||
}
|
||||
|
||||
// This is needed to make an array of async functions.
|
||||
macro_rules! to_sync {
|
||||
($l:ident) => {
|
||||
|
@ -1119,6 +1160,7 @@ pub async fn migrate_from_version(
|
|||
to_sync!(migrate_to_v7),
|
||||
to_sync!(migrate_to_v8),
|
||||
to_sync!(migrate_to_v9),
|
||||
to_sync!(migrate_to_v10),
|
||||
];
|
||||
assert_eq!(migrations.len(), (LAST_SCHEMA_VERSION.0 - 1) as usize);
|
||||
for migration in 2..=last_version.0 {
|
||||
|
|
|
@ -11,7 +11,7 @@ pub type DbConnection = sea_orm::DatabaseConnection;
|
|||
#[derive(Copy, PartialEq, Eq, Debug, Clone, PartialOrd, Ord, DeriveValueType)]
|
||||
pub struct SchemaVersion(pub i16);
|
||||
|
||||
pub const LAST_SCHEMA_VERSION: SchemaVersion = SchemaVersion(9);
|
||||
pub const LAST_SCHEMA_VERSION: SchemaVersion = SchemaVersion(10);
|
||||
|
||||
#[derive(Copy, PartialEq, Eq, Debug, Clone, PartialOrd, Ord)]
|
||||
pub struct PrivateKeyHash(pub [u8; 32]);
|
||||
|
|
|
@ -67,8 +67,8 @@ fn get_user_filter_expr(filter: UserRequestFilter) -> Cond {
|
|||
}
|
||||
}
|
||||
AttributeEquality(column, value) => attribute_condition(column, value),
|
||||
MemberOf(group) => Expr::col((group_table, GroupColumn::DisplayName))
|
||||
.eq(group)
|
||||
MemberOf(group) => Expr::col((group_table, GroupColumn::LowercaseDisplayName))
|
||||
.eq(group.as_str().to_lowercase())
|
||||
.into_condition(),
|
||||
MemberOfId(group_id) => Expr::col((group_table, GroupColumn::GroupId))
|
||||
.eq(group_id)
|
||||
|
@ -542,6 +542,12 @@ mod tests {
|
|||
)
|
||||
.await;
|
||||
assert_eq!(users, vec!["bob", "patrick"]);
|
||||
let users = get_user_names(
|
||||
&fixture.handler,
|
||||
Some(UserRequestFilter::MemberOf("best grOUp".into())),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(users, vec!["bob", "patrick"]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -1121,4 +1127,29 @@ mod tests {
|
|||
.await
|
||||
.expect_err("Should have failed");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user_duplicate_email() {
|
||||
let fixture = TestFixture::new().await;
|
||||
|
||||
fixture
|
||||
.handler
|
||||
.create_user(CreateUserRequest {
|
||||
user_id: UserId::new("james"),
|
||||
email: "email".into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
fixture
|
||||
.handler
|
||||
.create_user(CreateUserRequest {
|
||||
user_id: UserId::new("john"),
|
||||
email: "eMail".into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue