Loading capif_frontend/src/components/ConfigCapif.js +13 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,13 @@ const ConfigCapif = () => { updateParamMutation.mutate({ param_path: path, new_value: value }); }; // Manejar el evento de presionar Enter const handleKeyDown = (event, path, value) => { if (event.key === 'Enter') { handleBlur(path, value); } }; const handleJsonChange = (e) => { const value = e.target.value; setJsonConfig(value); Loading Loading @@ -154,6 +161,7 @@ const ConfigCapif = () => { value={editableConfig?.configuration_name || ''} onChange={(e) => handleValueChange('configuration_name', e.target.value)} onBlur={(e) => handleBlur('configuration_name', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'configuration_name', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> Loading @@ -163,6 +171,7 @@ const ConfigCapif = () => { value={editableConfig?.description || ''} onChange={(e) => handleValueChange('description', e.target.value)} onBlur={(e) => handleBlur('description', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'description', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> Loading @@ -172,6 +181,7 @@ const ConfigCapif = () => { value={editableConfig?.version || ''} onChange={(e) => handleValueChange('version', e.target.value)} onBlur={(e) => handleBlur('version', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'version', e.target.value)} /> </Box> Loading @@ -190,6 +200,7 @@ const ConfigCapif = () => { value={String(value)} onChange={(e) => handleValueChange(`settings.acl_policy_settings.${key}`, e.target.value)} onBlur={(e) => handleBlur(`settings.acl_policy_settings.${key}`, e.target.value)} onKeyDown={(e) => handleKeyDown(e, `settings.acl_policy_settings.${key}`, e.target.value)} /> </Box> )) Loading @@ -212,6 +223,7 @@ const ConfigCapif = () => { value={String(value)} onChange={(e) => handleValueChange(`settings.security_method_priority.${key}`, e.target.value)} onBlur={(e) => handleBlur(`settings.security_method_priority.${key}`, e.target.value)} onKeyDown={(e) => handleKeyDown(e, `settings.security_method_priority.${key}`, e.target.value)} /> </Box> )) Loading @@ -233,6 +245,7 @@ const ConfigCapif = () => { value={editableConfig?.settings?.[key] || ''} onChange={(e) => handleValueChange(`settings.${key}`, e.target.value)} onBlur={(e) => handleBlur(`settings.${key}`, e.target.value)} onKeyDown={(e) => handleKeyDown(e, `settings.${key}`, e.target.value)} /> </Box> ))} Loading capif_frontend/src/components/ConfigRegister.js +201 −17 Original line number Diff line number Diff line import React from 'react'; import { Card, CardHeader, CardContent, TextField, Button, Typography, Box } from '@mui/material'; import React, { useEffect, useState } from 'react'; import { useQuery, useMutation } from '@tanstack/react-query'; import { getRegisterConfiguration, updateRegisterConfigParam, replaceRegisterConfiguration } from 'src/configs/apiService'; import { Grid, Card, Typography, CardHeader, CardContent, TextField, Button, Box } from '@mui/material'; import Ajv from 'ajv'; const ajv = new Ajv(); // Esquema de validación para la configuración del Register const registerConfigSchema = { type: "object", properties: { config_name: { type: "string" }, version: { type: "string" }, description: { type: "string" }, settings: { type: "object", properties: { ttl_superadmin_cert: { type: "string" } }, required: ["ttl_superadmin_cert"] } }, required: ["config_name", "version", "description", "settings"] }; const ConfigRegister = () => { // Obtener configuración desde el backend const { data: configData, isLoading, isError, refetch } = useQuery({ queryKey: ['registerConfiguration'], queryFn: getRegisterConfiguration, }); const [editableConfig, setEditableConfig] = useState(null); const [jsonConfig, setJsonConfig] = useState(''); const [isJsonValid, setIsJsonValid] = useState(true); useEffect(() => { if (configData) { setEditableConfig(configData); } }, [configData]); // Mutaciones para actualizar parámetros individuales y reemplazar la configuración const updateParamMutation = useMutation({ mutationFn: updateRegisterConfigParam, onSuccess: () => refetch(), }); const replaceConfigMutation = useMutation({ mutationFn: replaceRegisterConfiguration, onSuccess: () => refetch(), }); const handleValueChange = (path, value) => { setEditableConfig((prev) => { const newConfig = { ...prev }; const keys = path.split('.'); let current = newConfig; for (let i = 0; i < keys.length - 1; i++) { current = current[keys[i]]; } current[keys[keys.length - 1]] = value; return { ...newConfig }; }); }; const handleBlur = (path, value) => { updateParamMutation.mutate({ param_path: path, new_value: value }); }; // Manejar el evento de presionar Enter const handleKeyDown = (event, path, value) => { if (event.key === 'Enter') { handleBlur(path, value); } }; const handleJsonChange = (e) => { const value = e.target.value; setJsonConfig(value); try { const parsedJson = JSON.parse(value); const validate = ajv.compile(registerConfigSchema); setIsJsonValid(validate(parsedJson)); } catch (error) { setIsJsonValid(false); } }; const handleJsonSubmit = () => { try { const parsedJson = JSON.parse(jsonConfig); const validate = ajv.compile(registerConfigSchema); const valid = validate(parsedJson); if (!valid) { setIsJsonValid(false); console.error("Errores de validación:", validate.errors); alert("JSON inválido: No cumple con la estructura requerida."); return; } setIsJsonValid(true); replaceConfigMutation.mutate(parsedJson); } catch (error) { setIsJsonValid(false); alert("Formato de JSON inválido"); } }; if (isLoading) return <Typography>Loading...</Typography>; if (isError) return <Typography>Error loading configuration</Typography>; const RegisterApplication = () => { return ( <Box p={3}> <Typography variant="h6">Register Application</Typography> <Grid container spacing={3} marginTop={2}> <Grid item xs={12}> <Card> <CardHeader title="Register Configuration" /> <CardContent> {/* General Configuration */} <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>Configuration Name</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.config_name || ''} onChange={(e) => handleValueChange('config_name', e.target.value)} onBlur={(e) => handleBlur('config_name', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'config_name', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>Description</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.description || ''} onChange={(e) => handleValueChange('description', e.target.value)} onBlur={(e) => handleBlur('description', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'description', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>Version</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.version || ''} onChange={(e) => handleValueChange('version', e.target.value)} onBlur={(e) => handleBlur('version', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'version', e.target.value)} /> </Box> {/* Certificate Expiration Period */} <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>TTL Superadmin Cert</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.settings?.ttl_superadmin_cert || ''} onChange={(e) => handleValueChange('settings.ttl_superadmin_cert', e.target.value)} onBlur={(e) => handleBlur('settings.ttl_superadmin_cert', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'settings.ttl_superadmin_cert', e.target.value)} /> </Box> </CardContent> </Card> </Grid> {/* Upload JSON Configuration */} <Grid item xs={12}> <Card> <CardHeader title="New Application Registration" /> <CardHeader title="Upload New Register Configuration" /> <CardContent> <TextField fullWidth label="Application Name" variant="outlined" /> <TextField fullWidth label="Owner" variant="outlined" sx={{ mt: 2 }} /> <TextField fullWidth label="Description" multiline rows={4} variant="outlined" sx={{ mt: 2 }} /> <Button variant="contained" fullWidth sx={{ mt: 2 }}>Register</Button> <TextField fullWidth label="Paste JSON here" multiline rows={8} variant="outlined" value={jsonConfig} onChange={handleJsonChange} error={!isJsonValid} helperText={!isJsonValid ? "Invalid JSON format" : ""} /> <Button variant="contained" fullWidth sx={{ mt: 2 }} onClick={handleJsonSubmit} disabled={!isJsonValid}> Replace Register Configuration </Button> </CardContent> </Card> </Box> </Grid> </Grid> ); }; export default RegisterApplication; export default ConfigRegister; capif_frontend/src/configs/apiService.js +34 −0 Original line number Diff line number Diff line Loading @@ -444,3 +444,37 @@ export const replaceConfiguration = async (newConfig) => { throw new Error(`Error replacing configuration: ${error.message}`); } } export const getRegisterConfiguration = async () => { try { const response = await axiosInstance.get(`/configuration/register`); return response.data; } catch (error) { throw new Error(`Error fetching register configuration: ${error.message}`); } } export const updateRegisterConfigParam = async ({ param_path, new_value }) => { try { const response = await axiosInstance.patch(`/configuration/register/update-param`, { param_path, new_value }); return response.data; } catch (error) { throw new Error(`Error updating configuration parameter: ${error.message}`); } } export const replaceRegisterConfiguration = async (newConfig) => { try { const response = await axiosInstance.put(`/configuration/register/replace-config`, newConfig); return response.data; } catch (error) { throw new Error(`Error replacing configuration: ${error.message}`); } } No newline at end of file Loading
capif_frontend/src/components/ConfigCapif.js +13 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,13 @@ const ConfigCapif = () => { updateParamMutation.mutate({ param_path: path, new_value: value }); }; // Manejar el evento de presionar Enter const handleKeyDown = (event, path, value) => { if (event.key === 'Enter') { handleBlur(path, value); } }; const handleJsonChange = (e) => { const value = e.target.value; setJsonConfig(value); Loading Loading @@ -154,6 +161,7 @@ const ConfigCapif = () => { value={editableConfig?.configuration_name || ''} onChange={(e) => handleValueChange('configuration_name', e.target.value)} onBlur={(e) => handleBlur('configuration_name', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'configuration_name', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> Loading @@ -163,6 +171,7 @@ const ConfigCapif = () => { value={editableConfig?.description || ''} onChange={(e) => handleValueChange('description', e.target.value)} onBlur={(e) => handleBlur('description', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'description', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> Loading @@ -172,6 +181,7 @@ const ConfigCapif = () => { value={editableConfig?.version || ''} onChange={(e) => handleValueChange('version', e.target.value)} onBlur={(e) => handleBlur('version', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'version', e.target.value)} /> </Box> Loading @@ -190,6 +200,7 @@ const ConfigCapif = () => { value={String(value)} onChange={(e) => handleValueChange(`settings.acl_policy_settings.${key}`, e.target.value)} onBlur={(e) => handleBlur(`settings.acl_policy_settings.${key}`, e.target.value)} onKeyDown={(e) => handleKeyDown(e, `settings.acl_policy_settings.${key}`, e.target.value)} /> </Box> )) Loading @@ -212,6 +223,7 @@ const ConfigCapif = () => { value={String(value)} onChange={(e) => handleValueChange(`settings.security_method_priority.${key}`, e.target.value)} onBlur={(e) => handleBlur(`settings.security_method_priority.${key}`, e.target.value)} onKeyDown={(e) => handleKeyDown(e, `settings.security_method_priority.${key}`, e.target.value)} /> </Box> )) Loading @@ -233,6 +245,7 @@ const ConfigCapif = () => { value={editableConfig?.settings?.[key] || ''} onChange={(e) => handleValueChange(`settings.${key}`, e.target.value)} onBlur={(e) => handleBlur(`settings.${key}`, e.target.value)} onKeyDown={(e) => handleKeyDown(e, `settings.${key}`, e.target.value)} /> </Box> ))} Loading
capif_frontend/src/components/ConfigRegister.js +201 −17 Original line number Diff line number Diff line import React from 'react'; import { Card, CardHeader, CardContent, TextField, Button, Typography, Box } from '@mui/material'; import React, { useEffect, useState } from 'react'; import { useQuery, useMutation } from '@tanstack/react-query'; import { getRegisterConfiguration, updateRegisterConfigParam, replaceRegisterConfiguration } from 'src/configs/apiService'; import { Grid, Card, Typography, CardHeader, CardContent, TextField, Button, Box } from '@mui/material'; import Ajv from 'ajv'; const ajv = new Ajv(); // Esquema de validación para la configuración del Register const registerConfigSchema = { type: "object", properties: { config_name: { type: "string" }, version: { type: "string" }, description: { type: "string" }, settings: { type: "object", properties: { ttl_superadmin_cert: { type: "string" } }, required: ["ttl_superadmin_cert"] } }, required: ["config_name", "version", "description", "settings"] }; const ConfigRegister = () => { // Obtener configuración desde el backend const { data: configData, isLoading, isError, refetch } = useQuery({ queryKey: ['registerConfiguration'], queryFn: getRegisterConfiguration, }); const [editableConfig, setEditableConfig] = useState(null); const [jsonConfig, setJsonConfig] = useState(''); const [isJsonValid, setIsJsonValid] = useState(true); useEffect(() => { if (configData) { setEditableConfig(configData); } }, [configData]); // Mutaciones para actualizar parámetros individuales y reemplazar la configuración const updateParamMutation = useMutation({ mutationFn: updateRegisterConfigParam, onSuccess: () => refetch(), }); const replaceConfigMutation = useMutation({ mutationFn: replaceRegisterConfiguration, onSuccess: () => refetch(), }); const handleValueChange = (path, value) => { setEditableConfig((prev) => { const newConfig = { ...prev }; const keys = path.split('.'); let current = newConfig; for (let i = 0; i < keys.length - 1; i++) { current = current[keys[i]]; } current[keys[keys.length - 1]] = value; return { ...newConfig }; }); }; const handleBlur = (path, value) => { updateParamMutation.mutate({ param_path: path, new_value: value }); }; // Manejar el evento de presionar Enter const handleKeyDown = (event, path, value) => { if (event.key === 'Enter') { handleBlur(path, value); } }; const handleJsonChange = (e) => { const value = e.target.value; setJsonConfig(value); try { const parsedJson = JSON.parse(value); const validate = ajv.compile(registerConfigSchema); setIsJsonValid(validate(parsedJson)); } catch (error) { setIsJsonValid(false); } }; const handleJsonSubmit = () => { try { const parsedJson = JSON.parse(jsonConfig); const validate = ajv.compile(registerConfigSchema); const valid = validate(parsedJson); if (!valid) { setIsJsonValid(false); console.error("Errores de validación:", validate.errors); alert("JSON inválido: No cumple con la estructura requerida."); return; } setIsJsonValid(true); replaceConfigMutation.mutate(parsedJson); } catch (error) { setIsJsonValid(false); alert("Formato de JSON inválido"); } }; if (isLoading) return <Typography>Loading...</Typography>; if (isError) return <Typography>Error loading configuration</Typography>; const RegisterApplication = () => { return ( <Box p={3}> <Typography variant="h6">Register Application</Typography> <Grid container spacing={3} marginTop={2}> <Grid item xs={12}> <Card> <CardHeader title="Register Configuration" /> <CardContent> {/* General Configuration */} <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>Configuration Name</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.config_name || ''} onChange={(e) => handleValueChange('config_name', e.target.value)} onBlur={(e) => handleBlur('config_name', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'config_name', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>Description</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.description || ''} onChange={(e) => handleValueChange('description', e.target.value)} onBlur={(e) => handleBlur('description', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'description', e.target.value)} /> </Box> <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>Version</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.version || ''} onChange={(e) => handleValueChange('version', e.target.value)} onBlur={(e) => handleBlur('version', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'version', e.target.value)} /> </Box> {/* Certificate Expiration Period */} <Box display="flex" alignItems="center" mb={2}> <Typography variant="subtitle1" sx={{ flex: 1 }}>TTL Superadmin Cert</Typography> <TextField sx={{ width: '700px' }} value={editableConfig?.settings?.ttl_superadmin_cert || ''} onChange={(e) => handleValueChange('settings.ttl_superadmin_cert', e.target.value)} onBlur={(e) => handleBlur('settings.ttl_superadmin_cert', e.target.value)} onKeyDown={(e) => handleKeyDown(e, 'settings.ttl_superadmin_cert', e.target.value)} /> </Box> </CardContent> </Card> </Grid> {/* Upload JSON Configuration */} <Grid item xs={12}> <Card> <CardHeader title="New Application Registration" /> <CardHeader title="Upload New Register Configuration" /> <CardContent> <TextField fullWidth label="Application Name" variant="outlined" /> <TextField fullWidth label="Owner" variant="outlined" sx={{ mt: 2 }} /> <TextField fullWidth label="Description" multiline rows={4} variant="outlined" sx={{ mt: 2 }} /> <Button variant="contained" fullWidth sx={{ mt: 2 }}>Register</Button> <TextField fullWidth label="Paste JSON here" multiline rows={8} variant="outlined" value={jsonConfig} onChange={handleJsonChange} error={!isJsonValid} helperText={!isJsonValid ? "Invalid JSON format" : ""} /> <Button variant="contained" fullWidth sx={{ mt: 2 }} onClick={handleJsonSubmit} disabled={!isJsonValid}> Replace Register Configuration </Button> </CardContent> </Card> </Box> </Grid> </Grid> ); }; export default RegisterApplication; export default ConfigRegister;
capif_frontend/src/configs/apiService.js +34 −0 Original line number Diff line number Diff line Loading @@ -444,3 +444,37 @@ export const replaceConfiguration = async (newConfig) => { throw new Error(`Error replacing configuration: ${error.message}`); } } export const getRegisterConfiguration = async () => { try { const response = await axiosInstance.get(`/configuration/register`); return response.data; } catch (error) { throw new Error(`Error fetching register configuration: ${error.message}`); } } export const updateRegisterConfigParam = async ({ param_path, new_value }) => { try { const response = await axiosInstance.patch(`/configuration/register/update-param`, { param_path, new_value }); return response.data; } catch (error) { throw new Error(`Error updating configuration parameter: ${error.message}`); } } export const replaceRegisterConfiguration = async (newConfig) => { try { const response = await axiosInstance.put(`/configuration/register/replace-config`, newConfig); return response.data; } catch (error) { throw new Error(`Error replacing configuration: ${error.message}`); } } No newline at end of file