From ac0fdc7a23cd32c0e1ecc96a9c256893c84d0fd0 Mon Sep 17 00:00:00 2001 From: Mickael Kerjean Date: Mon, 9 Oct 2023 07:14:19 +0200 Subject: [PATCH] fix (admin): prepare for release --- public/pages/adminpage/ctrl_backend.js | 2 + .../ctrl_backend_component_authentication.js | 56 ++--------------- .../ctrl_backend_component_storage.js | 30 +++------- public/pages/adminpage/ctrl_backend_state.js | 60 +++++++++++++++++++ public/pages/adminpage/ctrl_log.js | 8 +-- public/pages/adminpage/ctrl_settings.js | 5 +- public/pages/adminpage/model_config.js | 6 +- 7 files changed, 88 insertions(+), 79 deletions(-) diff --git a/public/pages/adminpage/ctrl_backend.js b/public/pages/adminpage/ctrl_backend.js index 3a9433da1..6d1e970be 100644 --- a/public/pages/adminpage/ctrl_backend.js +++ b/public/pages/adminpage/ctrl_backend.js @@ -4,6 +4,7 @@ import { CSS } from "../../helpers/loader.js"; import transition from "./animate.js"; import AdminHOC from "./decorator.js"; +import { initConfig } from "./model_config.js"; import componentStorageBackend from "./ctrl_backend_component_storage.js"; import componentAuthenticationMiddleware from "./ctrl_backend_component_authentication.js"; @@ -16,6 +17,7 @@ export default AdminHOC(async function(render) { `); render(transition($page)); + await initConfig(); componentStorageBackend(createRender(qs($page, `[data-bind="backend"]`))); componentAuthenticationMiddleware(createRender(qs($page, `[data-bind="authentication_middleware"]`))); diff --git a/public/pages/adminpage/ctrl_backend_component_authentication.js b/public/pages/adminpage/ctrl_backend_component_authentication.js index 13e66abbf..63a0b89c6 100644 --- a/public/pages/adminpage/ctrl_backend_component_authentication.js +++ b/public/pages/adminpage/ctrl_backend_component_authentication.js @@ -8,7 +8,7 @@ import { generateSkeleton } from "../../components/skeleton.js"; import { get as getConfig } from "../../model/config.js"; import { - initMiddleware, initStorage, + initMiddleware, initStorage, getState, getMiddlewareAvailable, getMiddlewareEnabled, toggleMiddleware, getBackendAvailable, getBackendEnabled, } from "./ctrl_backend_state.js"; @@ -65,7 +65,7 @@ export default async function(render) { rxjs.mergeMap(($nodes) => $nodes), rxjs.mergeMap(($node) => onClick($node)), rxjs.map(($node) => toggleMiddleware($node.getAttribute("data-label"))), - saveMiddleware, + saveMiddleware(), )); // feature: setup forms - we insert everything in the DOM so we don't lose @@ -237,57 +237,11 @@ export default async function(render) { effect(setupAMForm$.pipe( rxjs.switchMap(() => rxjs.fromEvent($page, "input")), rxjs.mergeMap(() => getMiddlewareEnabled().pipe(rxjs.first())), - saveMiddleware, + saveMiddleware(), )); } -const saveMiddleware = rxjs.pipe( - rxjs.map((authType) => { - const middleware = { - identity_provider: {}, - attribute_mapping: {}, - }; - if (!authType) return middleware; - - let formValues = [...new FormData(document.querySelector(`[data-bind="idp"]`))]; - middleware.identity_provider = { - type: authType, - params: JSON.stringify( - formValues - .filter(([key, value]) => key.startsWith(`${authType}.`)) // remove elements that aren't in scope - .map(([key, value]) => [key.replace(new RegExp(`^${authType}\.`), ""), value]) // format the relevant keys - .reduce((acc, [key, value]) => { // transform onto something ready to be saved - if (key === "type") return acc; - return { - ...acc, - [key]: value, - }; - }, {}), - ), - }; - - formValues = [...new FormData(document.querySelector(`[data-bind="attribute-mapping"]`))]; - middleware.attribute_mapping = { - related_backend: formValues.shift()[1], - params: JSON.stringify(formValues.reduce((acc, [key, value]) => { - const k = key.split("."); - if (k.length !== 2) return acc; - if (!acc[k[0]]) acc[k[0]] = {}; - if (value !== "") acc[k[0]][k[1]] = value; - return acc; - }, {})), - }; - return middleware; - }), - rxjs.mergeMap((middleware) => getAdminConfig().pipe( - rxjs.first(), - formObjToJSON$(), - rxjs.map((config) => [middleware, config]), - )), - rxjs.map(([middleware, config]) => ({...config, middleware})), - rxjs.mergeMap((newConfig) => getConfig().pipe( - rxjs.first(), - rxjs.map(({ connections }) => ({ ...newConfig, connections })), - )), +const saveMiddleware = () => rxjs.pipe( + rxjs.mergeMap(() => getState()), saveConfig(), ); diff --git a/public/pages/adminpage/ctrl_backend_component_storage.js b/public/pages/adminpage/ctrl_backend_component_storage.js index 29b1443f3..473768261 100644 --- a/public/pages/adminpage/ctrl_backend_component_storage.js +++ b/public/pages/adminpage/ctrl_backend_component_storage.js @@ -5,7 +5,7 @@ import { qs, qsa } from "../../lib/dom.js"; import { formTmpl } from "../../components/form.js"; import { generateSkeleton } from "../../components/skeleton.js"; -import { initStorage, getBackendAvailable, getBackendEnabled, addBackendEnabled, removeBackendEnabled } from "./ctrl_backend_state.js"; +import { initStorage, getState, getBackendAvailable, getBackendEnabled, addBackendEnabled, removeBackendEnabled } from "./ctrl_backend_state.js"; import { formObjToJSON$ } from "./helper_form.js"; import { get as getAdminConfig, save as saveConfig } from "./model_config.js"; @@ -57,7 +57,7 @@ export default async function(render) { rxjs.mergeMap(($nodes) => $nodes), rxjs.mergeMap(($node) => onClick($node)), rxjs.map(($node) => addBackendEnabled($node.getAttribute("data-label"))), - saveConnections, + saveConnections(), )); // feature: setup form @@ -105,33 +105,21 @@ export default async function(render) { rxjs.mergeMap(($node) => onClick($node.querySelector(".icons"))), rxjs.map(($node) => qs($node.parentElement, "input").value), rxjs.map((label) => removeBackendEnabled(label)), - saveConnections, + saveConnections(), )); // feature: form input change handler effect(setupForm$.pipe( rxjs.mergeMap((forms) => forms), rxjs.mergeMap(($el) => rxjs.fromEvent($el, "input")), - rxjs.map(() => new FormData(qs($page, `[data-bind="backend-enabled"]`))), - rxjs.map((formData) => { - const connections = []; - for (const [type, label] of formData.entries()) { - connections.push({ type, label }); - } - return connections; - }), - saveConnections, + saveConnections(), )); } -const saveConnections = rxjs.pipe( - rxjs.mergeMap((connections) => getAdminConfig().pipe( - rxjs.first(), - formObjToJSON$(), - rxjs.map((config) => ({ - ...config, - connections, - })), - )), +const saveConnections = () => rxjs.pipe( + rxjs.mergeMap((connections) => getState().pipe(rxjs.map((config) => { + config.connections = connections; + return config; + }))), saveConfig(), ); diff --git a/public/pages/adminpage/ctrl_backend_state.js b/public/pages/adminpage/ctrl_backend_state.js index 0c86eb2bf..5a0ef4e79 100644 --- a/public/pages/adminpage/ctrl_backend_state.js +++ b/public/pages/adminpage/ctrl_backend_state.js @@ -1,4 +1,5 @@ import rxjs from "../../lib/rx.js"; +import { qs } from "../../lib/dom.js"; import { get as getConfig } from "../../model/config.js"; import { get as getAdminConfig } from "./model_config.js"; import { formObjToJSON$ } from "./helper_form.js"; @@ -66,3 +67,62 @@ export function toggleMiddleware(type) { middlewareEnabled$.next(newValue); return newValue; } + +export function getState() { + return getAdminConfig().pipe( + rxjs.first(), + formObjToJSON$(), + rxjs.map((config) => { // connections + const connections = []; + const formData = new FormData(qs(document, `[data-bind="backend-enabled"]`)); + for (const [type, label] of formData.entries()) { + connections.push({ type, label }); + } + config.connections = connections; + return config; + }), + rxjs.map((config) => { // middleware + const authType = document + .querySelector(`[data-bind="authentication_middleware"] [is="box-item"].active`) + .getAttribute("data-label"); + + const middleware = { + identity_provider: {}, + attribute_mapping: {}, + }; + if (!authType) return config; + + let formValues = [...new FormData(document.querySelector(`[data-bind="idp"]`))]; + middleware.identity_provider = { + type: authType, + params: JSON.stringify( + formValues + .filter(([key, value]) => key.startsWith(`${authType}.`)) // remove elements that aren't in scope + .map(([key, value]) => [key.replace(new RegExp(`^${authType}\.`), ""), value]) // format the relevant keys + .reduce((acc, [key, value]) => { // transform onto something ready to be saved + if (key === "type") return acc; + return { + ...acc, + [key]: value, + }; + }, {}), + ), + }; + + formValues = [...new FormData(document.querySelector(`[data-bind="attribute-mapping"]`))]; + middleware.attribute_mapping = { + related_backend: formValues.shift()[1], + params: JSON.stringify(formValues.reduce((acc, [key, value]) => { + const k = key.split("."); + if (k.length !== 2) return acc; + if (!acc[k[0]]) acc[k[0]] = {}; + if (value !== "") acc[k[0]][k[1]] = value; + return acc; + }, {})), + }; + + config.middleware = middleware; + return config; + }), + ); +} diff --git a/public/pages/adminpage/ctrl_log.js b/public/pages/adminpage/ctrl_log.js index 3b5388879..158a98ed4 100644 --- a/public/pages/adminpage/ctrl_log.js +++ b/public/pages/adminpage/ctrl_log.js @@ -1,12 +1,13 @@ import { createElement, createRender } from "../../lib/skeleton/index.js"; +import { initConfig } from "./model_config.js"; import componentLogForm from "./ctrl_log_form.js"; import componentLogViewer from "./ctrl_log_viewer.js"; import componentAuditor from "./ctrl_log_audit.js"; import transition from "./animate.js"; import AdminHOC from "./decorator.js"; -function Page(render) { +export default AdminHOC(async function (render) { const $page = createElement(`

Logging

@@ -18,10 +19,9 @@ function Page(render) {
`); render(transition($page)); + await initConfig(); componentLogViewer(createRender($page.querySelector(".component_logviewer"))); componentLogForm(createRender($page.querySelector(".component_logger"))); componentAuditor(createRender($page.querySelector(".component_reporter"))); -} - -export default AdminHOC(Page); +}); diff --git a/public/pages/adminpage/ctrl_settings.js b/public/pages/adminpage/ctrl_settings.js index d69fb5ff2..1fd598b99 100644 --- a/public/pages/adminpage/ctrl_settings.js +++ b/public/pages/adminpage/ctrl_settings.js @@ -7,12 +7,12 @@ import { generateSkeleton } from "../../components/skeleton.js"; import notification from "../../components/notification.js"; import { get as getConfig } from "../../model/config.js"; -import { get as getAdminConfig, save as saveConfig } from "./model_config.js"; +import { get as getAdminConfig, save as saveConfig, initConfig } from "./model_config.js"; import { renderLeaf, useForm$, formObjToJSON$ } from "./helper_form.js"; import transition from "./animate.js"; import AdminHOC from "./decorator.js"; -export default AdminHOC(function(render) { +export default AdminHOC(async function(render) { const $container = createElement(`
@@ -22,6 +22,7 @@ export default AdminHOC(function(render) {
`); render(transition($container)); + await initConfig(); const config$ = getAdminConfig().pipe( rxjs.first(), diff --git a/public/pages/adminpage/model_config.js b/public/pages/adminpage/model_config.js index 73095a881..a2bc22b82 100644 --- a/public/pages/adminpage/model_config.js +++ b/public/pages/adminpage/model_config.js @@ -14,6 +14,10 @@ const config$ = isSaving$.pipe( rxjs.shareReplay(1), ) +export async function initConfig() { + if (isSaving$.value === true) isSaving$.next(false); +} + export function isSaving() { return isSaving$.asObservable(); } @@ -25,7 +29,7 @@ export function get() { export function save() { return rxjs.pipe( rxjs.tap(() => isSaving$.next(true)), - rxjs.debounceTime(2000), + rxjs.debounceTime(1500), rxjs.mergeMap((formData) => ajax({ url: "/admin/api/config", method: "POST",