Merge pull request 'ldap tests' (#52) from Backend-ldap into main

Reviewed-on: #52
This commit is contained in:
Schuhmacher 2025-04-07 11:34:22 +02:00
commit f4ce83b5c2
3 changed files with 95 additions and 8 deletions

View file

@ -13,21 +13,26 @@ struct LoginRequest {
// HTTP POST endpoint for user login
#[post("/login")]
async fn login(credentials: web::Json<LoginRequest>) -> impl Responder {
// Get LDAP server and base DN from environment variables or use defaults
let ldap_server = env::var("LDAP_SERVER").unwrap_or("ldap://127.0.0.1:389".to_string());
let base_dn = env::var("LDAP_BASE_DN").unwrap_or("dc=schule,dc=local".to_string());
// Authenticate user and return appropriate response
match authenticate_user(&credentials.username, &credentials.password) {
match authenticate_user(&ldap_server, &base_dn, &credentials.username, &credentials.password) {
Ok(true) => HttpResponse::Ok().body("Login erfolgreich"), // Login successful
_ => HttpResponse::Unauthorized().body("Login fehlgeschlagen"), // Login failed
}
}
// Function to authenticate user against LDAP server
fn authenticate_user(username: &str, password: &str) -> Result<bool, Box<dyn std::error::Error>> {
// Get LDAP server and base DN from environment variables or use defaults
let ldap_server = env::var("LDAP_SERVER").unwrap_or("ldap://127.0.0.1:389".to_string());
let base_dn = env::var("LDAP_BASE_DN").unwrap_or("dc=schule,dc=local".to_string());
fn authenticate_user(
ldap_server: &str,
base_dn: &str,
username: &str,
password: &str,
) -> Result<bool, Box<dyn std::error::Error>> {
// Establish connection to LDAP server
let ldap = LdapConn::new(&ldap_server)?;
let ldap = LdapConn::new(ldap_server)?;
// Search for the user in the LDAP directory
let (rs, _res) = ldap
@ -44,7 +49,7 @@ fn authenticate_user(username: &str, password: &str) -> Result<bool, Box<dyn std
let user_dn = SearchEntry::construct(entry).dn; // Extract user DN
// Reconnect and bind with user credentials
let user_ldap = LdapConn::new(&ldap_server)?;
let user_ldap = LdapConn::new(ldap_server)?;
let auth_result = user_ldap.simple_bind(&user_dn, password)?.success();
return Ok(auth_result.is_ok()); // Return true if authentication succeeds
}

View file

@ -1 +1,46 @@
use ldap3::{LdapConn, Scope, SearchEntry};
/// Authenticates a user against an LDAP server.
///
/// # Arguments
/// * `ldap_server` - The LDAP server URL.
/// * `base_dn` - The base DN for the LDAP directory.
/// * `username` - The username to authenticate.
/// * `password` - The password for the user.
///
/// # Returns
/// * `Ok(true)` if authentication is successful.
/// * `Ok(false)` if authentication fails.
/// * `Err` if an error occurs during the process.
pub fn authenticate_user(
ldap_server: &str,
base_dn: &str,
username: &str,
password: &str,
) -> Result<bool, Box<dyn std::error::Error>> {
// Establish connection to LDAP server
let ldap = LdapConn::new(ldap_server)?;
// Search for the user in the LDAP directory
let (rs, _res) = ldap
.search(
&format!("ou=users,{}", base_dn), // Search under "ou=users"
Scope::Subtree, // Search all levels
&format!("(uid={})", username), // Filter by username
vec!["dn"], // Retrieve the distinguished name (DN)
)?
.success()?;
// If user is found, attempt to authenticate with their DN and password
if let Some(entry) = rs.into_iter().next() {
let user_dn = SearchEntry::construct(entry).dn; // Extract user DN
// Reconnect and bind with user credentials
let user_ldap = LdapConn::new(ldap_server)?;
let auth_result = user_ldap.simple_bind(&user_dn, password)?.success();
return Ok(auth_result.is_ok()); // Return true if authentication succeeds
}
Ok(false) // Return false if user is not found
}

37
crates/ldap/src/main.rs Normal file
View file

@ -0,0 +1,37 @@
use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
use serde::Deserialize;
use ldap::authenticate_user; // Import the library function
use std::env;
// Struct to deserialize login request payload
#[derive(Deserialize)]
struct LoginRequest {
username: String,
password: String,
}
// HTTP POST endpoint for user login
#[post("/login")]
async fn login(credentials: web::Json<LoginRequest>) -> impl Responder {
// Get LDAP server and base DN from environment variables or use defaults
let ldap_server = env::var("LDAP_SERVER").unwrap_or("ldap://127.0.0.1:389".to_string());
let base_dn = env::var("LDAP_BASE_DN").unwrap_or("dc=schule,dc=local".to_string());
// Authenticate user and return appropriate response
match authenticate_user(&ldap_server, &base_dn, &credentials.username, &credentials.password) {
Ok(true) => HttpResponse::Ok().body("Login erfolgreich"), // Login successful
_ => HttpResponse::Unauthorized().body("Login fehlgeschlagen"), // Login failed
}
}
// Main function to start the Actix Web server
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init(); // Initialize logger
// Start HTTP server and bind to localhost:8080
HttpServer::new(|| App::new().service(login))
.bind(("127.0.0.1", 8080))?
.run()
.await
}