/** * Copyright 2025 LY Corporation * * LY Corporation licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ import type { NextApiRequest } from 'next'; import { supportExternalUrl } from './support-external'; type StoredJwt = { accessToken?: string }; export interface SupportPrincipal { user_id: string; tenant_id: string; email?: string | null; name?: string | null; department?: string | null; phone_number?: string | null; is_admin?: boolean; is_system_admin?: boolean; roles?: string[]; } const SUPPORT_MANAGER_ROLES = new Set([ 'SYSTEM_ADMIN', 'SUPER_ADMIN', 'PROJECT_MANAGER', ]); export const isSupportAdmin = (principal: SupportPrincipal) => principal.is_admin === true || principal.is_system_admin === true || (Array.isArray(principal.roles) && principal.roles.some((role) => SUPPORT_MANAGER_ROLES.has(role))); export const applySupportCommentPermissions = < T extends { author_id: string; author_tenant_id: string; }, >(comment: T, principal: SupportPrincipal) => { const isAuthor = comment.author_id === principal.user_id && comment.author_tenant_id === principal.tenant_id; const canManage = isSupportAdmin(principal); return { ...comment, can_edit: canManage || isAuthor, can_delete: canManage || isAuthor, }; }; export const getSupportAuthHeaders = ( req: NextApiRequest, ): Record => { const authorization = req.headers.authorization; if (authorization) return { Authorization: authorization }; const rawCookie = req.cookies.jwt; if (!rawCookie) return {}; try { const parsed = JSON.parse(decodeURIComponent(rawCookie)) as StoredJwt; return parsed.accessToken ? { Authorization: 'Bearer ' + parsed.accessToken } : {}; } catch { return {}; } }; export const getSupportPrincipal = async ( req: NextApiRequest, ): Promise => { const headers = getSupportAuthHeaders(req); if (!headers.Authorization) return null; try { const response = await fetch(supportExternalUrl('/access'), { headers, }); if (!response.ok) return null; const data = (await response.json()) as Partial; if ( typeof data.user_id !== 'string' || typeof data.tenant_id !== 'string' || !data.user_id || !data.tenant_id ) { return null; } return data as SupportPrincipal; } catch { return null; } };