Improved get/create user
This commit is contained in:
parent
b12f3d4457
commit
f3010febdc
|
@ -1,17 +1,6 @@
|
||||||
#[cynic::schema("lldap")]
|
#[cynic::schema("lldap")]
|
||||||
pub(crate) mod schema {}
|
pub(crate) mod schema {}
|
||||||
|
|
||||||
#[derive(cynic::QueryFragment, Debug)]
|
|
||||||
#[cynic(graphql_type = "Query")]
|
|
||||||
pub struct ListUsers {
|
|
||||||
pub users: Vec<User>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(cynic::QueryFragment, Debug)]
|
|
||||||
pub struct User {
|
|
||||||
pub id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(cynic::QueryVariables, Debug)]
|
#[derive(cynic::QueryVariables, Debug)]
|
||||||
pub struct DeleteUserVariables<'a> {
|
pub struct DeleteUserVariables<'a> {
|
||||||
pub id: &'a str,
|
pub id: &'a str,
|
||||||
|
@ -54,19 +43,35 @@ pub struct AddUserToGroup {
|
||||||
pub add_user_to_group: Success,
|
pub add_user_to_group: Success,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryVariables, Debug)]
|
||||||
|
pub struct GetUserVariables<'a> {
|
||||||
|
pub id: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
#[cynic(graphql_type = "Query", variables = "GetUserVariables")]
|
||||||
|
pub struct GetUser {
|
||||||
|
#[arguments(userId: $id)]
|
||||||
|
pub user: User,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct User {
|
||||||
|
pub id: String,
|
||||||
|
pub groups: Vec<Group>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(cynic::QueryFragment, Debug)]
|
||||||
|
pub struct Group {
|
||||||
|
pub id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cynic::MutationBuilder;
|
use cynic::MutationBuilder;
|
||||||
use cynic::QueryBuilder;
|
use cynic::QueryBuilder;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn list_users_gql_output() {
|
|
||||||
let operation = ListUsers::build(());
|
|
||||||
|
|
||||||
insta::assert_snapshot!(operation.query);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn delete_user_gql_output() {
|
fn delete_user_gql_output() {
|
||||||
let operation = DeleteUser::build(DeleteUserVariables { id: "user" });
|
let operation = DeleteUser::build(DeleteUserVariables { id: "user" });
|
||||||
|
@ -90,4 +95,11 @@ mod tests {
|
||||||
|
|
||||||
insta::assert_snapshot!(operation.query);
|
insta::assert_snapshot!(operation.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_user_gql_output() {
|
||||||
|
let operation = GetUser::build(GetUserVariables { id: "user" });
|
||||||
|
|
||||||
|
insta::assert_snapshot!(operation.query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,8 @@ expression: operation.query
|
||||||
mutation CreateUser($id: String!) {
|
mutation CreateUser($id: String!) {
|
||||||
createUser(user: {email: $id, id: $id}) {
|
createUser(user: {email: $id, id: $id}) {
|
||||||
id
|
id
|
||||||
|
groups {
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
source: queries/src/lib.rs
|
||||||
|
expression: operation.query
|
||||||
|
---
|
||||||
|
query GetUser($id: String!) {
|
||||||
|
user(userId: $id) {
|
||||||
|
id
|
||||||
|
groups {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
source: queries/src/lib.rs
|
|
||||||
expression: operation.query
|
|
||||||
---
|
|
||||||
query ListUsers {
|
|
||||||
users {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
32
src/lldap.rs
32
src/lldap.rs
|
@ -9,7 +9,10 @@ use tracing::debug;
|
||||||
use cynic::http::{CynicReqwestError, ReqwestExt};
|
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::{CreateUser, CreateUserVariables, DeleteUser, DeleteUserVariables, ListUsers};
|
use queries::{
|
||||||
|
CreateUser, CreateUserVariables, DeleteUser, DeleteUserVariables, GetUser, GetUserVariables,
|
||||||
|
User,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -25,14 +28,16 @@ pub enum Error {
|
||||||
|
|
||||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||||
|
|
||||||
fn check_graphql_errors<T>(response: &GraphQlResponse<T>) -> Result<()> {
|
fn check_graphql_errors<T>(response: GraphQlResponse<T>) -> Result<T> {
|
||||||
if let Some(errors) = &response.errors {
|
if let Some(errors) = &response.errors {
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
Err(errors.first().expect("Should not be empty").clone())?;
|
Err(errors.first().expect("Should not be empty").clone())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(response
|
||||||
|
.data
|
||||||
|
.expect("Data should be valid if there are no error"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LldapConfig {
|
pub struct LldapConfig {
|
||||||
|
@ -95,25 +100,18 @@ pub struct LldapClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LldapClient {
|
impl LldapClient {
|
||||||
pub async fn list_users(&self) -> Result<impl Iterator<Item = String>> {
|
pub async fn get_user(&self, username: &str) -> Result<User> {
|
||||||
let operation = ListUsers::build(());
|
let operation = GetUser::build(GetUserVariables { id: username });
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
.post(format!("{}/api/graphql", self.url))
|
.post(format!("{}/api/graphql", self.url))
|
||||||
.run_graphql(operation)
|
.run_graphql(operation)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
check_graphql_errors(&response)?;
|
Ok(check_graphql_errors(response)?.user)
|
||||||
|
|
||||||
Ok(response
|
|
||||||
.data
|
|
||||||
.expect("Data should be valid if there are no error")
|
|
||||||
.users
|
|
||||||
.into_iter()
|
|
||||||
.map(|user| user.id))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_user(&self, username: &str) -> Result<()> {
|
pub async fn create_user(&self, username: &str) -> Result<User> {
|
||||||
let operation = CreateUser::build(CreateUserVariables { id: username });
|
let operation = CreateUser::build(CreateUserVariables { id: username });
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
|
@ -122,7 +120,7 @@ impl LldapClient {
|
||||||
.run_graphql(operation)
|
.run_graphql(operation)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
check_graphql_errors(&response)
|
Ok(check_graphql_errors(response)?.create_user)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_user(&self, username: &str) -> Result<()> {
|
pub async fn delete_user(&self, username: &str) -> Result<()> {
|
||||||
|
@ -134,7 +132,9 @@ impl LldapClient {
|
||||||
.run_graphql(operation)
|
.run_graphql(operation)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
check_graphql_errors(&response)
|
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<()> {
|
||||||
|
|
|
@ -199,14 +199,24 @@ 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");
|
||||||
if lldap_client.list_users().await?.any(|id| id == username) {
|
let _user = match lldap_client.get_user(&username).await {
|
||||||
debug!(name, username, "User already exists");
|
Err(lldap::Error::GraphQl(err))
|
||||||
} else {
|
if err.message == format!("Entity not found: `{username}`") =>
|
||||||
debug!(name, username, "Creating new user");
|
{
|
||||||
|
debug!(name, username, "Creating new user");
|
||||||
|
|
||||||
lldap_client.create_user(&username).await?;
|
let user = lldap_client.create_user(&username).await?;
|
||||||
ctx.recorder.user_created(self.as_ref(), &username).await?;
|
ctx.recorder.user_created(self.as_ref(), &username).await?;
|
||||||
}
|
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
|
Ok(user) => {
|
||||||
|
debug!(name, username, "User already exists");
|
||||||
|
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}?;
|
||||||
|
|
||||||
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();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user