[pdm-devel] [PATCH yew-comp 5/5] auth_view: implement syncing ldap and ad realms

Shannon Sterz s.sterz at proxmox.com
Tue Sep 16 16:48:22 CEST 2025


by adding an EditWindow that allows specifying the sync options and
then calling the specified sync endpoint.

Signed-off-by: Shannon Sterz <s.sterz at proxmox.com>
---
 src/auth_view.rs | 106 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 102 insertions(+), 4 deletions(-)

diff --git a/src/auth_view.rs b/src/auth_view.rs
index a70e80b..a414ed6 100644
--- a/src/auth_view.rs
+++ b/src/auth_view.rs
@@ -4,6 +4,8 @@ use std::rc::Rc;
 
 use anyhow::Error;
 
+use pwt::widget::form::{Checkbox, FormContext, TristateBoolean};
+use serde_json::Value;
 use yew::html::IntoPropValue;
 use yew::virtual_dom::{VComp, VNode};
 
@@ -12,13 +14,13 @@ use pwt::state::{Selection, Store};
 use pwt::widget::data_table::{DataTable, DataTableColumn, DataTableHeader};
 use pwt::widget::menu::{Menu, MenuButton, MenuItem};
 
-use pwt::widget::{Button, Fa, Toolbar};
+use pwt::widget::{Button, Container, Fa, InputPanel, Toolbar};
 
 use pwt_macros::builder;
 
 use crate::{
-    AuthEditLDAP, AuthEditOpenID, LoadableComponent, LoadableComponentContext,
-    LoadableComponentMaster,
+    AuthEditLDAP, AuthEditOpenID, EditWindow, LoadableComponent, LoadableComponentContext,
+    LoadableComponentLink, LoadableComponentMaster,
 };
 
 use crate::common_api_types::BasicRealmInfo;
@@ -69,6 +71,7 @@ pub enum ViewState {
     EditOpenID(AttrValue),
     EditLDAP(AttrValue),
     EditAd(AttrValue),
+    Sync(AttrValue),
 }
 
 pub enum Msg {
@@ -89,6 +92,44 @@ async fn delete_item(base_url: AttrValue, realm: AttrValue) -> Result<(), Error>
     Ok(())
 }
 
+async fn sync_realm(
+    form_ctx: FormContext,
+    link: LoadableComponentLink<ProxmoxAuthView>,
+    url: impl Into<String>,
+) -> Result<(), Error> {
+    let mut data = form_ctx.get_submit_data();
+
+    let mut remove_vanished = Vec::new();
+
+    for prop in ["acl", "entry", "properties"] {
+        let prop_name = format!("remove-vanished-{prop}");
+        if data[&prop_name] == Value::Bool(true) {
+            remove_vanished.push(prop);
+        }
+
+        data[&prop_name] = Value::Null;
+    }
+
+    if !remove_vanished.is_empty() {
+        data["remove-vanished"] = Value::String(remove_vanished.join(";"));
+    }
+
+    let mut new = serde_json::json!({});
+
+    for (param, v) in data.as_object().unwrap().iter() {
+        if !v.is_null() {
+            new[param] = v.clone();
+        }
+    }
+
+    match crate::http_post::<String>(url, Some(new)).await {
+        Ok(upid) => link.show_task_log(upid, None),
+        Err(err) => link.show_error(tr!("Sync Failed"), err, true),
+    };
+
+    Ok(())
+}
+
 impl ProxmoxAuthView {
     fn get_selected_record(&self) -> Option<BasicRealmInfo> {
         let selected_key = self.selection.selected_key();
@@ -171,7 +212,18 @@ impl LoadableComponent for ProxmoxAuthView {
                 true
             }
             Msg::Sync => {
-                // fixme: do something
+                let info = match self.get_selected_record() {
+                    Some(info) => info,
+                    None => return true,
+                };
+
+                let view = match info.ty.as_str() {
+                    "ldap" if props.ldap_base_url.is_some() => info.realm,
+                    "ad" if props.ad_base_url.is_some() => info.realm,
+                    _ => return true,
+                };
+
+                ctx.link().change_view(Some(ViewState::Sync(view.into())));
                 true
             }
         }
@@ -312,6 +364,52 @@ impl LoadableComponent for ProxmoxAuthView {
                     .on_close(ctx.link().change_view_callback(|_| None))
                     .into(),
             ),
+            ViewState::Sync(realm) => {
+                let link = ctx.link();
+                let url = format!("/access/domains/{}/sync", percent_encode_component(realm));
+
+                Some(
+                    EditWindow::new(tr!("Realm Sync"))
+                        .renderer(|_form_ctx| {
+                            InputPanel::new()
+                                .padding(4)
+                                .with_field(tr!("Preview Only"), Checkbox::new().name("dry-run"))
+                                .with_field(
+                                    tr!("Enable new"),
+                                    TristateBoolean::new()
+                                        .name("enable-new")
+                                        .null_text(tr!("Default") + " (" + &tr!("Yes") + ")"),
+                                )
+                                .with_large_custom_child(
+                                    Container::new()
+                                        .key("remove-vanished-options")
+                                        .class("pwt-font-title-medium")
+                                        .padding_top(2)
+                                        .with_child(tr!("Remove Vanished Options")),
+                                )
+                                .with_field(
+                                    tr!("Remove ACLs of vanished users"),
+                                    Checkbox::new().name("remove-vanished-acl"),
+                                )
+                                .with_field(
+                                    tr!("Remove vanished user"),
+                                    Checkbox::new().name("remove-vanished-entry"),
+                                )
+                                .with_field(
+                                    tr!("Remove vanished properties"),
+                                    Checkbox::new().name("remove-vanished-properties"),
+                                )
+                                .into()
+                        })
+                        .on_close(link.change_view_callback(|_| None))
+                        .on_submit(move |form_context| {
+                            let link = link.clone();
+                            let url = url.clone();
+                            sync_realm(form_context, link, url)
+                        })
+                        .into(),
+                )
+            }
         }
     }
 }
-- 
2.47.3





More information about the pdm-devel mailing list