Commit 8d780146 authored by Dimitrios Gogos's avatar Dimitrios Gogos
Browse files

feat: enhance API handling with federation support and operator checks

parent 23445681
Loading
Loading
Loading
Loading
+12 −4
Changes for portal-gui/src/hooks/useAPIs.ts: 12 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -2,8 +2,15 @@ import { useEffect, useState } from 'react';

import type { Api, ApiState } from '@/types/api';
import { getApi, getApis } from '@/services/openapi/apis';
import { useAuth } from '@/features/auth/auth-context';

function useIsOperator() {
  const { user } = useAuth();
  return user?.roles.includes('operator') ?? false;
}

export function useApis() {
  const isOperator = useIsOperator();
  const [apis, setApis] = useState<Api[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
@@ -13,7 +20,7 @@ export function useApis() {

    async function loadApis() {
      try {
        const result = await getApis();
        const result = await getApis(isOperator);

        if (!cancelled) {
          setApis(result);
@@ -34,7 +41,7 @@ export function useApis() {
    return () => {
      cancelled = true;
    };
  }, []);
  }, [isOperator]);

  return {
    apis,
@@ -44,6 +51,7 @@ export function useApis() {
}

export function useApi(id?: string) {
  const isOperator = useIsOperator();
  const [state, setState] = useState<ApiState>({
    api: null,
    loading: Boolean(id),
@@ -58,7 +66,7 @@ export function useApi(id?: string) {
    let cancelled = false;
    async function loadApi() {
      try {
        const result = await getApi(apiId);
        const result = await getApi(apiId, isOperator);
        if (!cancelled) {
          setState({
            api: result,
@@ -81,7 +89,7 @@ export function useApi(id?: string) {
    return () => {
      cancelled = true;
    };
  }, [id]);
  }, [id, isOperator]);

  return state;
}
+14 −5
Changes for portal-gui/src/services/openapi/apis.ts: 14 added lines, 5 removed lines.
Original line number Diff line number Diff line
import type { Api } from '@/types/api';
import { transformOpenApiToCatalog } from '@/services/openapi/transform';
import type { OpenApiSpec } from '@/types/api';
import { oeg } from '@/app/config/api';
import { federation, oeg } from '@/app/config/api';
import { apiFetch } from '@/lib/api-fetch';

const federationPath = federation.baseUrl.replace(/^\/api\/oeg/, '');

const catalogPaths = (includeFederation: boolean) => (path: string) =>
  includeFederation ||
  (path !== federationPath && !path.startsWith(`${federationPath}/`));

async function fetchOpenApiSpec(): Promise<OpenApiSpec> {
  const response = await apiFetch(oeg.jsonUrl);

@@ -16,15 +22,18 @@ async function fetchOpenApiSpec(): Promise<OpenApiSpec> {
  return response.json();
}

export async function getApis(): Promise<Api[]> {
export async function getApis(includeFederation: boolean): Promise<Api[]> {
  const spec = await fetchOpenApiSpec();

  return transformOpenApiToCatalog(spec);
  return transformOpenApiToCatalog(spec, catalogPaths(includeFederation));
}

export async function getApi(id: string): Promise<Api> {
export async function getApi(
  id: string,
  includeFederation: boolean,
): Promise<Api> {
  const spec = await fetchOpenApiSpec();
  const apis = transformOpenApiToCatalog(spec);
  const apis = transformOpenApiToCatalog(spec, catalogPaths(includeFederation));

  const api = apis.find((item) => item.id === id);

+5 −1
Changes for portal-gui/src/services/openapi/transform.ts: 5 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -5,10 +5,14 @@ function slugify(text: string) {
  return text.toLowerCase().replace(/\s+/g, '-');
}

export function transformOpenApiToCatalog(spec: OpenApiSpec): Api[] {
export function transformOpenApiToCatalog(
  spec: OpenApiSpec,
  includePath: (path: string) => boolean = () => true,
): Api[] {
  const tagMap: Record<string, ApiTaggedOperation[]> = {};

  Object.entries(spec.paths).forEach(([path, methods]) => {
    if (!includePath(path)) return;
    Object.entries(methods).forEach(([method, operation]) => {
      const tags = operation.tags ?? ['General'];