Commit 8b2592fa authored by guillecxb's avatar guillecxb
Browse files

Capif configuraiton ready

parent e353ea88
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
    "@reduxjs/toolkit": "1.9.5",
    "@tanstack/react-query": "^5.8.9",
    "aes-js": "^3.1.2",
    "ajv": "^8.17.1",
    "apexcharts-clevision": "3.28.5",
    "axios": "1.4.0",
    "axios-mock-adapter": "1.21.4",
+271 −0
Original line number Diff line number Diff line
import React, { useEffect, useState } from 'react';
import { useQuery, useMutation } from '@tanstack/react-query';
import { getConfiguration, updateConfigParam, replaceConfiguration } from 'src/configs/apiService';
import {
  Grid,
  Card,
  Typography,
  CardHeader,
  CardContent,
  TextField,
  Button,
  Accordion,
  AccordionSummary,
  AccordionDetails,
  Box
} from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import Ajv from 'ajv';

const ajv = new Ajv();

// Esquema de validación para la configuración
const configSchema = {
  type: "object",
  properties: {
    config_name: { type: "string" },
    version: { type: "string" },
    description: { type: "string" },
    settings: {
      type: "object",
      properties: {
        ttl_superadmin_cert: { type: "string" },
        ttl_invoker_cert: { type: "string" },
        ttl_provider_cert: { type: "string" },
        security_method_priority: {
          type: "object",
          properties: {
            oauth: { type: "number" },
            pki: { type: "number" },
            psk: { type: "number" }
          },
          required: ["oauth", "pki", "psk"]
        },
        acl_policy_settings: {
          type: "object",
          properties: {
            allowedTotalInvocations: { type: "number" },
            allowedInvocationsPerSecond: { type: "number" },
            allowedInvocationTimeRangeDays: { type: "number" }
          },
          required: ["allowedTotalInvocations", "allowedInvocationsPerSecond", "allowedInvocationTimeRangeDays"]
        }
      },
      required: ["ttl_superadmin_cert", "ttl_invoker_cert", "ttl_provider_cert", "security_method_priority", "acl_policy_settings"]
    }
  },
  required: ["config_name", "version", "description", "settings"]
};

const ConfigCapif = () => {
  // Obtener configuración desde el backend
  const { data: configData, isLoading, isError, refetch } = useQuery({
    queryKey: ['configuration'],
    queryFn: getConfiguration,
  });

  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: updateConfigParam,
    onSuccess: () => refetch(),
  });

  const replaceConfigMutation = useMutation({
    mutationFn: replaceConfiguration,
    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 });
  };

  const handleJsonChange = (e) => {
    const value = e.target.value;
    setJsonConfig(value);

    try {
      const parsedJson = JSON.parse(value);
      const validate = ajv.compile(configSchema);
      setIsJsonValid(validate(parsedJson));
    } catch (error) {
      setIsJsonValid(false);
    }
  };

  const handleJsonSubmit = () => {
    try {
      const parsedJson = JSON.parse(jsonConfig);
      const validate = ajv.compile(configSchema);
      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>;

  return (
    <Grid container spacing={3} marginTop={2}>
      {/* Cuadro principal con datos generales y secciones desplegables */}
      <Grid item xs={12}>
        <Card>
          <CardHeader title="General 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?.configuration_name || ''} 
                onChange={(e) => handleValueChange('configuration_name', e.target.value)} 
                onBlur={(e) => handleBlur('configuration_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)} 
              />
            </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)} 
              />
            </Box>

            {/* ACL Policy Settings */}
            <Accordion disableGutters>
              <AccordionSummary expandIcon={<ExpandMoreIcon />}>
                <Typography variant="h6">ACL Policy Settings</Typography>
              </AccordionSummary>
              <AccordionDetails>
                {editableConfig?.settings?.acl_policy_settings &&
                  Object.entries(editableConfig.settings.acl_policy_settings).map(([key, value]) => (
                    <Box key={key} display="flex" alignItems="center" mb={1}>
                      <Typography variant="subtitle1" sx={{ flex: 1 }}>{key}</Typography>
                      <TextField 
                        sx={{ width: '700px' }} 
                        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)}
                      />
                    </Box>
                  ))
                }
              </AccordionDetails>
            </Accordion>

            {/* Security Method Priority */}
            <Accordion disableGutters>
              <AccordionSummary expandIcon={<ExpandMoreIcon />}>
                <Typography variant="h6">Security Method Priority</Typography>
              </AccordionSummary>
              <AccordionDetails>
                {editableConfig?.settings?.security_method_priority &&
                  Object.entries(editableConfig.settings.security_method_priority).map(([key, value]) => (
                    <Box key={key} display="flex" alignItems="center" mb={1}>
                      <Typography variant="subtitle1" sx={{ flex: 1 }}>{key}</Typography>
                      <TextField 
                        sx={{ width: '700px' }} 
                        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)}
                      />
                    </Box>
                  ))
                }
              </AccordionDetails>
            </Accordion>

            {/* Certificate Expiration Period */}
            <Accordion disableGutters>
              <AccordionSummary expandIcon={<ExpandMoreIcon />}>
                <Typography variant="h6">Certificate Expiration Period</Typography>
              </AccordionSummary>
              <AccordionDetails>
                {['ttl_invoker_cert', 'ttl_provider_cert', 'ttl_superadmin_cert'].map((key) => (
                  <Box key={key} display="flex" alignItems="center" mb={1}>
                    <Typography variant="subtitle1" sx={{ flex: 1 }}>{key.replace('_', ' ')}</Typography>
                    <TextField 
                      sx={{ width: '700px' }} 
                      value={editableConfig?.settings?.[key] || ''} 
                      onChange={(e) => handleValueChange(`settings.${key}`, e.target.value)}
                      onBlur={(e) => handleBlur(`settings.${key}`, e.target.value)}
                    />
                  </Box>
                ))}
              </AccordionDetails>
            </Accordion>
          </CardContent>
        </Card>
      </Grid>

      {/* Upload JSON Configuration */}
      <Grid item xs={12}>
        <Card>
          <CardHeader title="Upload New Configuration" />
          <CardContent>
            <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 Configuration
            </Button>
          </CardContent>
        </Card>
      </Grid>
    </Grid>
  );
};

export default ConfigCapif;
+22 −0
Original line number Diff line number Diff line
import React from 'react';
import { Card, CardHeader, CardContent, TextField, Button, Typography, Box } from '@mui/material';

const RegisterApplication = () => {
  return (
    <Box p={3}>
      <Typography variant="h6">Register Application</Typography>
      
      <Card>
        <CardHeader title="New Application Registration" />
        <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>
        </CardContent>
      </Card>
    </Box>
  );
};

export default RegisterApplication;
+21 −66
Original line number Diff line number Diff line
@@ -9,7 +9,12 @@ import {
  CardContent,
  TextField,
  Button,
  Tabs,
  Tab,
  Box
} from '@mui/material';
import ConfigCapif from 'src/components/ConfigCapif';
import ConfigRegister from 'src/components/ConfigRegister';

const Configuration = () => {
  // Obtener configuración desde el backend
@@ -20,6 +25,7 @@ const Configuration = () => {

  const [editableConfig, setEditableConfig] = useState(null);
  const [jsonConfig, setJsonConfig] = useState('');
  const [selectedTab, setSelectedTab] = useState(0); // Estado para las pestañas

  useEffect(() => {
    if (configData) {
@@ -64,78 +70,27 @@ const Configuration = () => {
    }
  };

  const handleTabChange = (event, newValue) => {
    setSelectedTab(newValue);
  };

  if (isLoading) return <Typography>Loading...</Typography>;
  if (isError) return <Typography>Error loading configuration</Typography>;

  return (
    <Grid container spacing={3}>
      {/* General Info */}
      <Grid item xs={12} md={4}>
        <Card>
          <CardHeader title="General Configuration" />
          <CardContent>
            <Typography variant="subtitle1">Configuration Name</Typography>
            <TextField fullWidth value={editableConfig?.configuration_name || ''} onChange={(e) => handleValueChange('configuration_name', e.target.value)} onBlur={(e) => handleBlur('configuration_name', e.target.value)} />
            <Typography variant="subtitle1">Description</Typography>
            <TextField fullWidth value={editableConfig?.description || ''} onChange={(e) => handleValueChange('description', e.target.value)} onBlur={(e) => handleBlur('description', e.target.value)} />
            <Typography variant="subtitle1">Version</Typography>
            <TextField fullWidth value={editableConfig?.version || ''} onChange={(e) => handleValueChange('version', e.target.value)} onBlur={(e) => handleBlur('version', e.target.value)} />
          </CardContent>
        </Card>
      </Grid>

      {/* ACL Policy Settings */}
      <Grid item xs={12} md={4}>
        <Card>
          <CardHeader title="ACL Policy Settings" />
          <CardContent>
            {editableConfig?.settings?.acl_policy_settings && Object.entries(editableConfig.settings.acl_policy_settings).map(([key, value]) => (
              <div key={key}>
                <Typography variant="subtitle1">{key}</Typography>
                <TextField fullWidth 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)} />
              </div>
            ))}
          </CardContent>
        </Card>
      </Grid>

      {/* Security Method Priority */}
      <Grid item xs={12} md={4}>
        <Card>
          <CardHeader title="Security Method Priority" />
          <CardContent>
            {editableConfig?.settings?.security_method_priority && Object.entries(editableConfig.settings.security_method_priority).map(([key, value]) => (
              <div key={key}>
                <Typography variant="subtitle1">{key}</Typography>
                <TextField fullWidth 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)} />
              </div>
            ))}
          </CardContent>
        </Card>
      </Grid>
    <Box>
      {/* Barra de Tabs */}
      <Tabs value={selectedTab} onChange={handleTabChange} variant="fullWidth">
        <Tab label="Capif Configuration" />
        <Tab label="Register Configuration" />
      </Tabs>

      {/* Certify Expiration Period */}
      <Grid item xs={12} md={4}>
        <Card>
          <CardHeader title="Certify Expiration Period" />
          <CardContent>
            <Typography variant="subtitle1">certify_expiration_period</Typography>
            <TextField fullWidth value={String(editableConfig?.settings?.certify_expiration_period || '')} onChange={(e) => handleValueChange('settings.certify_expiration_period', e.target.value)} onBlur={(e) => handleBlur('settings.certify_expiration_period', e.target.value)} />
          </CardContent>
        </Card>
      </Grid>
      {/* CConfiguración de Capif*/}
      {selectedTab === 0 && <ConfigCapif />}

      {/* Upload JSON Configuration */}
      <Grid item xs={12}>
        <Card>
          <CardHeader title="Upload New Configuration" />
          <CardContent>
            <TextField fullWidth label="Paste JSON here" multiline rows={8} variant="outlined" value={jsonConfig} onChange={(e) => setJsonConfig(e.target.value)} />
            <Button variant="contained" fullWidth onClick={handleJsonSubmit} disabled={replaceConfigMutation.isLoading}>{replaceConfigMutation.isLoading ? 'Updating...' : 'Replace Configuration'}</Button>
          </CardContent>
        </Card>
      </Grid>
    </Grid>
      {/* Configuración del Register */}
      {selectedTab === 1 && <ConfigRegister />}
    </Box>
  );
};

+0 −0

File changed.

Preview suppressed by a .gitattributes entry or the file's encoding is unsupported.