Implement additionalGroups functionality #2
This commit is contained in:
parent
fac8e44b24
commit
c57d419f78
|
@ -43,6 +43,19 @@ pub struct AddUserToGroup {
|
||||||
pub add_user_to_group: Success,
|
pub add_user_to_group: Success,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryVariables, Debug)]
|
||||||
|
pub struct RemoveUserFromGroupVariables<'a> {
|
||||||
|
pub group: i32,
|
||||||
|
pub username: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Mutation", variables = "RemoveUserFromGroupVariables")]
|
||||||
|
pub struct RemoveUserFromGroup {
|
||||||
|
#[arguments(groupId: $group, userId: $username)]
|
||||||
|
pub remove_user_from_group: Success,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(cynic::QueryVariables, Debug)]
|
#[derive(cynic::QueryVariables, Debug)]
|
||||||
pub struct GetUserVariables<'a> {
|
pub struct GetUserVariables<'a> {
|
||||||
pub username: &'a str,
|
pub username: &'a str,
|
||||||
|
@ -64,6 +77,13 @@ pub struct User {
|
||||||
#[derive(cynic::QueryFragment, Debug)]
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
|
pub display_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Query")]
|
||||||
|
pub struct GetGroups {
|
||||||
|
pub groups: Vec<Group>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -96,10 +116,27 @@ mod tests {
|
||||||
insta::assert_snapshot!(operation.query);
|
insta::assert_snapshot!(operation.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_user_from_group_gql_output() {
|
||||||
|
let operation = RemoveUserFromGroup::build(RemoveUserFromGroupVariables {
|
||||||
|
group: 3,
|
||||||
|
username: "user",
|
||||||
|
});
|
||||||
|
|
||||||
|
insta::assert_snapshot!(operation.query);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_user_gql_output() {
|
fn get_user_gql_output() {
|
||||||
let operation = GetUser::build(GetUserVariables { username: "user" });
|
let operation = GetUser::build(GetUserVariables { username: "user" });
|
||||||
|
|
||||||
insta::assert_snapshot!(operation.query);
|
insta::assert_snapshot!(operation.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_groups_gql_output() {
|
||||||
|
let operation = GetGroups::build(());
|
||||||
|
|
||||||
|
insta::assert_snapshot!(operation.query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ mutation CreateUser($username: String!) {
|
||||||
id
|
id
|
||||||
groups {
|
groups {
|
||||||
id
|
id
|
||||||
|
displayName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
source: queries/src/lib.rs
|
||||||
|
expression: operation.query
|
||||||
|
---
|
||||||
|
query GetGroups {
|
||||||
|
groups {
|
||||||
|
id
|
||||||
|
displayName
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ query GetUser($username: String!) {
|
||||||
id
|
id
|
||||||
groups {
|
groups {
|
||||||
id
|
id
|
||||||
|
displayName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
source: queries/src/lib.rs
|
||||||
|
expression: operation.query
|
||||||
|
---
|
||||||
|
mutation RemoveUserFromGroup($group: Int!, $username: String!) {
|
||||||
|
removeUserFromGroup(groupId: $group, userId: $username) {
|
||||||
|
ok
|
||||||
|
}
|
||||||
|
}
|
46
src/lldap.rs
46
src/lldap.rs
|
@ -10,8 +10,9 @@ use cynic::http::{CynicReqwestError, ReqwestExt};
|
||||||
use cynic::{GraphQlError, GraphQlResponse, MutationBuilder, QueryBuilder};
|
use cynic::{GraphQlError, GraphQlResponse, MutationBuilder, QueryBuilder};
|
||||||
use lldap_auth::login::{ClientSimpleLoginRequest, ServerLoginResponse};
|
use lldap_auth::login::{ClientSimpleLoginRequest, ServerLoginResponse};
|
||||||
use queries::{
|
use queries::{
|
||||||
CreateUser, CreateUserVariables, DeleteUser, DeleteUserVariables, GetUser, GetUserVariables,
|
AddUserToGroup, AddUserToGroupVariables, CreateUser, CreateUserVariables, DeleteUser,
|
||||||
User,
|
DeleteUserVariables, GetGroups, GetUser, GetUserVariables, Group, RemoveUserFromGroup,
|
||||||
|
RemoveUserFromGroupVariables, User,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
@ -137,6 +138,47 @@ impl LldapClient {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_groups(&self) -> Result<Vec<Group>> {
|
||||||
|
let operation = GetGroups::build(());
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.client
|
||||||
|
.post(format!("{}/api/graphql", self.url))
|
||||||
|
.run_graphql(operation)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(check_graphql_errors(response)?.groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_user_to_group(&self, username: &str, group: i32) -> Result<()> {
|
||||||
|
let operation = AddUserToGroup::build(AddUserToGroupVariables { username, group });
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.client
|
||||||
|
.post(format!("{}/api/graphql", self.url))
|
||||||
|
.run_graphql(operation)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
check_graphql_errors(response)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn remove_user_from_group(&self, username: &str, group: i32) -> Result<()> {
|
||||||
|
let operation =
|
||||||
|
RemoveUserFromGroup::build(RemoveUserFromGroupVariables { username, group });
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.client
|
||||||
|
.post(format!("{}/api/graphql", self.url))
|
||||||
|
.run_graphql(operation)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
check_graphql_errors(response)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_password(&self, username: &str, password: &str) -> Result<()> {
|
pub async fn update_password(&self, username: &str, password: &str) -> Result<()> {
|
||||||
let mut rng = rand::rngs::OsRng;
|
let mut rng = rand::rngs::OsRng;
|
||||||
let registration_start_request =
|
let registration_start_request =
|
||||||
|
|
|
@ -199,7 +199,7 @@ impl Reconcile for ServiceUser {
|
||||||
let lldap_client = ctx.lldap_config.build_client().await?;
|
let lldap_client = ctx.lldap_config.build_client().await?;
|
||||||
|
|
||||||
trace!(name, "Creating user if needed");
|
trace!(name, "Creating user if needed");
|
||||||
let _user = match lldap_client.get_user(&username).await {
|
let user = match lldap_client.get_user(&username).await {
|
||||||
Err(lldap::Error::GraphQl(err))
|
Err(lldap::Error::GraphQl(err))
|
||||||
if err.message == format!("Entity not found: `{username}`") =>
|
if err.message == format!("Entity not found: `{username}`") =>
|
||||||
{
|
{
|
||||||
|
@ -218,6 +218,42 @@ impl Reconcile for ServiceUser {
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
let groups = lldap_client.get_groups().await?;
|
||||||
|
// TODO: Error when invalid name
|
||||||
|
let needed_groups: Vec<_> = self
|
||||||
|
.spec
|
||||||
|
.additional_groups
|
||||||
|
.iter()
|
||||||
|
.filter_map(|additional_group| {
|
||||||
|
groups
|
||||||
|
.iter()
|
||||||
|
.find(|group| &group.display_name == additional_group)
|
||||||
|
.map(|group| group.id)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let current_groups: Vec<_> = user.groups.iter().map(|group| group.id).collect();
|
||||||
|
|
||||||
|
let remove = current_groups
|
||||||
|
.iter()
|
||||||
|
.filter(|group| !needed_groups.contains(group));
|
||||||
|
for &group in remove {
|
||||||
|
trace!(name, username, group, "Removing user from group");
|
||||||
|
|
||||||
|
lldap_client
|
||||||
|
.remove_user_from_group(&username, group)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let add = needed_groups
|
||||||
|
.iter()
|
||||||
|
.filter(|group| !current_groups.contains(group));
|
||||||
|
for &group in add {
|
||||||
|
trace!(name, username, group, "Adding user to group");
|
||||||
|
|
||||||
|
lldap_client.add_user_to_group(&username, group).await?;
|
||||||
|
}
|
||||||
|
|
||||||
trace!(name, "Updating password");
|
trace!(name, "Updating password");
|
||||||
let password = secret.get().data.as_ref().unwrap().get("password").unwrap();
|
let password = secret.get().data.as_ref().unwrap().get("password").unwrap();
|
||||||
let password = from_utf8(&password.0).unwrap();
|
let password = from_utf8(&password.0).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user