//! MNOTE 管理员目录授权页面组件 use crate::ssr::pages::layout::PageLayout; use leptos::prelude::*; #[component] pub fn AdminAccessPolicyPage( #[prop(optional)] workspace_name: Option, #[prop(optional)] policy_path: Option, #[prop(optional)] share_grants_path: Option, ) -> impl IntoView { let workspace_name = workspace_name .unwrap_or_else(|| "开发用户 的空间".to_string()) .trim() .to_string(); let policy_path = policy_path .unwrap_or_else(|| "/mnt/Data1T/Mnote_data/control-plane/access-policy.json".to_string()); let share_grants_path = share_grants_path .unwrap_or_else(|| "/mnt/Data1T/Mnote_data/control-plane/share-grants.json".to_string()); view! {

"目录授权"

"管理员可以查看、验证和管理本地目录授权,普通用户不会看到入口。"

"工作区" {workspace_name.clone()}
"策略文件" {policy_path.clone()}
"分享授权文件" {share_grants_path.clone()}

"当前策略"

{""}

"验证目录"


                    

"新增授权"


                    

"删除授权"


                    

"分享授权"

{""}

"新增分享授权"


                    

"撤销分享授权"


                    
} } const ADMIN_POLICY_SCRIPT: &str = r#" (function () { var root = document.querySelector('[data-testid="mnote-admin-access-policy-page"]'); if (!root) return; var message = root.querySelector('[data-testid="mnote-admin-policy-message"]'); var policyJson = root.querySelector('[data-testid="mnote-admin-policy-json"]'); var shareGrantsJson = root.querySelector('[data-testid="mnote-admin-share-grants-json"]'); var validateResult = root.querySelector('[data-testid="mnote-admin-validate-result"]'); var createResult = root.querySelector('[data-testid="mnote-admin-create-result"]'); var deleteResult = root.querySelector('[data-testid="mnote-admin-delete-result"]'); var shareGrantsMessage = root.querySelector('[data-testid="mnote-admin-share-grants-message"]'); var createShareGrantResult = root.querySelector('[data-testid="mnote-admin-create-share-grant-result"]'); var deleteShareGrantResult = root.querySelector('[data-testid="mnote-admin-delete-share-grant-result"]'); var refreshButton = root.querySelector('[data-admin-action="refresh-policy"]'); var refreshShareGrantsButton = root.querySelector('[data-admin-action="refresh-share-grants"]'); function setText(node, value) { if (!node) return; node.textContent = typeof value === 'string' ? value : JSON.stringify(value, null, 2); } function formValues(form) { var data = new FormData(form); var capabilities = String(data.get('capabilities') || '') .split(/[,\s]+/) .map(function (item) { return item.trim(); }) .filter(Boolean); return { id: String(data.get('grantId') || '').trim(), userId: String(data.get('userId') || '').trim(), rootUri: String(data.get('rootUri') || '').trim(), rootPath: String(data.get('rootPath') || '').trim(), permission: String(data.get('permission') || 'read').trim(), recursive: data.get('recursive') === 'on' || data.get('recursive') === 'true', capabilities: capabilities, }; } function splitList(value) { return String(value || '') .split(/[,\s]+/) .map(function (item) { return item.trim(); }) .filter(Boolean); } function shareGrantFormValues(form) { var data = new FormData(form); return { id: String(data.get('shareGrantId') || '').trim(), shareId: String(data.get('shareId') || '').trim(), ownerUserId: String(data.get('ownerUserId') || '').trim(), targetUserId: String(data.get('targetUserId') || '').trim(), rootUri: String(data.get('shareRootUri') || '').trim(), rootPath: String(data.get('shareRootPath') || '').trim(), documentId: String(data.get('documentId') || '').trim(), allowedResourceIds: splitList(data.get('allowedResourceIds')), permission: String(data.get('sharePermission') || 'read').trim(), capabilities: splitList(data.get('shareCapabilities')), }; } async function requestJson(url, options) { var response = await fetch(url, { credentials: 'include', headers: { 'content-type': 'application/json' }, ...options, }); var payload = await response.json().catch(function () { return {}; }); if (!response.ok || payload.ok === false) { throw new Error((payload && payload.message) || ('请求失败: ' + response.status)); } return payload; } async function refreshPolicy() { var payload = await requestJson('/api/admin/access-policy', { method: 'GET', headers: {} }); setText(policyJson, payload); setText(message, '已刷新策略'); } async function refreshShareGrants() { var payload = await requestJson('/api/admin/share-grants', { method: 'GET', headers: {} }); setText(shareGrantsJson, payload); setText(shareGrantsMessage, '已刷新分享授权'); } refreshButton && refreshButton.addEventListener('click', function () { setText(message, '正在刷新策略...'); refreshPolicy().catch(function (error) { setText(message, error.message || '刷新失败'); }); }); refreshShareGrantsButton && refreshShareGrantsButton.addEventListener('click', function () { setText(shareGrantsMessage, '正在刷新分享授权...'); refreshShareGrants().catch(function (error) { setText(shareGrantsMessage, error.message || '刷新失败'); }); }); root.querySelector('[data-admin-form="validate-root"]').addEventListener('submit', function (event) { event.preventDefault(); var values = formValues(event.currentTarget); setText(validateResult, '正在验证...'); requestJson('/api/admin/access-policy/validate-root', { method: 'POST', body: JSON.stringify({ rootUri: values.rootUri, rootPath: values.rootPath }), }).then(function (payload) { setText(validateResult, payload); setText(message, '目录验证完成'); }).catch(function (error) { setText(validateResult, { ok: false, error: error.message || '验证失败' }); setText(message, error.message || '验证失败'); }); }); root.querySelector('[data-admin-form="create-grant"]').addEventListener('submit', function (event) { event.preventDefault(); var values = formValues(event.currentTarget); setText(createResult, '正在创建...'); requestJson('/api/admin/access-policy/grants', { method: 'POST', body: JSON.stringify(values), }).then(function (payload) { setText(createResult, payload); setText(message, '授权已创建'); return refreshPolicy(); }).catch(function (error) { setText(createResult, { ok: false, error: error.message || '创建失败' }); setText(message, error.message || '创建失败'); }); }); root.querySelector('[data-admin-form="delete-grant"]').addEventListener('submit', function (event) { event.preventDefault(); var values = formValues(event.currentTarget); var grantId = values.id; setText(deleteResult, '正在删除...'); requestJson('/api/admin/access-policy/grants/' + encodeURIComponent(grantId), { method: 'DELETE', headers: {}, }).then(function (payload) { setText(deleteResult, payload); setText(message, '授权已删除'); return refreshPolicy(); }).catch(function (error) { setText(deleteResult, { ok: false, error: error.message || '删除失败' }); setText(message, error.message || '删除失败'); }); }); root.querySelector('[data-admin-form="create-share-grant"]').addEventListener('submit', function (event) { event.preventDefault(); var values = shareGrantFormValues(event.currentTarget); setText(createShareGrantResult, '正在创建...'); requestJson('/api/admin/share-grants', { method: 'POST', body: JSON.stringify(values), }).then(function (payload) { setText(createShareGrantResult, payload); setText(shareGrantsMessage, '分享授权已创建'); return refreshShareGrants(); }).catch(function (error) { setText(createShareGrantResult, { ok: false, error: error.message || '创建失败' }); setText(shareGrantsMessage, error.message || '创建失败'); }); }); root.querySelector('[data-admin-form="delete-share-grant"]').addEventListener('submit', function (event) { event.preventDefault(); var data = new FormData(event.currentTarget); var shareId = String(data.get('deleteShareId') || '').trim(); setText(deleteShareGrantResult, '正在撤销...'); requestJson('/api/admin/share-grants/' + encodeURIComponent(shareId), { method: 'DELETE', headers: {}, }).then(function (payload) { setText(deleteShareGrantResult, payload); setText(shareGrantsMessage, '分享授权已撤销'); return refreshShareGrants(); }).catch(function (error) { setText(deleteShareGrantResult, { ok: false, error: error.message || '撤销失败' }); setText(shareGrantsMessage, error.message || '撤销失败'); }); }); refreshPolicy().catch(function (error) { setText(message, error.message || '加载策略失败'); }); refreshShareGrants().catch(function (error) { setText(shareGrantsMessage, error.message || '加载分享授权失败'); }); })(); "#; #[cfg(test)] mod tests { use super::*; use crate::ssr::render_view; #[test] fn admin_access_policy_page_renders_admin_controls() { let html = render_view(view! { }); assert!(html.contains("mnote-admin-access-policy-page")); assert!(html.contains("mnote-admin-policy-json")); assert!(html.contains("mnote-admin-share-grants-panel")); assert!(html.contains("mnote-admin-share-grants-json")); assert!(html.contains("mnote-admin-validate-root-submit")); assert!(html.contains("mnote-admin-create-grant-submit")); assert!(html.contains("mnote-admin-delete-grant-submit")); assert!(html.contains("mnote-admin-create-share-grant-submit")); assert!(html.contains("mnote-admin-delete-share-grant-submit")); } }