fix(ui): isolate server-only auth headers

This commit is contained in:
Alan Buscaglia
2026-07-20 18:16:22 +02:00
parent 34079dcc09
commit b0b3ecec00
67 changed files with 227 additions and 64 deletions
+2 -1
View File
@@ -9,7 +9,8 @@ import {
SingleApiKeyResponse,
UpdateApiKeyPayload,
} from "@/components/users/profile/api-keys/types";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import { adaptApiKeysResponse } from "./api-keys.adapter";
+4
View File
@@ -13,6 +13,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiResponse: handleApiResponseMock,
}));
+2 -1
View File
@@ -2,8 +2,9 @@
import { z } from "zod";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { customAttackPathQuerySchema } from "@/lib/attack-paths/custom-query";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiResponse } from "@/lib/server-actions-helper";
import {
AttackPathCartographySchema,
+4
View File
@@ -19,6 +19,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiResponse: handleApiResponseMock,
}));
+2 -1
View File
@@ -2,7 +2,8 @@
import { z } from "zod";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiResponse } from "@/lib/server-actions-helper";
import { AttackPathScan, AttackPathScansResponse } from "@/types/attack-paths";
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiResponse } from "@/lib/server-actions-helper";
export const getCompliancesOverview = async ({
@@ -39,6 +39,10 @@ vi.mock("@/lib", () => ({
splitCsvFilterValues,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/provider-filters", () => ({
// Simulate real appendSanitizedProviderFilters: appends all non-undefined filters to the URL.
appendSanitizedProviderFilters: vi.fn(
+1 -1
View File
@@ -10,10 +10,10 @@ import {
FG_RECENT_LAST_SEEN,
FG_SEVERITY_HIGH_FIRST,
FINDING_GROUP_RESOURCES_DEFAULT_SORT,
getAuthHeaders,
includesMutedFindings,
splitCsvFilterValues,
} from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
@@ -35,6 +35,10 @@ vi.mock("@/lib", () => ({
RESOURCE_DRAWER_OTHER_FINDINGS_SORT,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/provider-filters", () => ({
appendSanitizedProviderTypeFilters: appendSanitizedProviderTypeFiltersMock,
}));
+2 -5
View File
@@ -4,11 +4,8 @@ import {
getFindingGroupResources,
getLatestFindingGroupResources,
} from "@/actions/finding-groups";
import {
apiBaseUrl,
getAuthHeaders,
RESOURCE_DRAWER_OTHER_FINDINGS_SORT,
} from "@/lib";
import { apiBaseUrl, RESOURCE_DRAWER_OTHER_FINDINGS_SORT } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { runWithConcurrencyLimit } from "@/lib/concurrency";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
@@ -23,6 +23,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiResponse: handleApiResponseMock,
}));
+2 -1
View File
@@ -2,7 +2,8 @@
import { adaptLatestFindingTriageNote } from "@/actions/findings/findings-triage.adapter";
import { createMuteRule } from "@/actions/mute-rules";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiResponse } from "@/lib/server-actions-helper";
import {
FINDING_TRIAGE_STATUS_LABELS,
+4
View File
@@ -23,6 +23,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/provider-filters", () => ({
appendSanitizedProviderTypeFilters: appendSanitizedProviderTypeFiltersMock,
}));
+2 -1
View File
@@ -4,7 +4,8 @@ import { redirect } from "next/navigation";
import { attachFindingTriageSummariesToResponse } from "@/actions/findings/findings-triage.adapter";
import { getFindingTriageAdapterOptions } from "@/actions/findings/findings-triage.options";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -3,7 +3,8 @@
import { revalidatePath } from "next/cache";
import { pollTaskUntilSettled } from "@/actions/task/poll";
import { apiBaseUrl, getAuthHeaders, parseStringify } from "@/lib";
import { apiBaseUrl, parseStringify } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import { IntegrationType } from "@/types/integrations";
import type { TaskState } from "@/types/tasks";
@@ -13,6 +13,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: vi.fn(),
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: vi.fn(),
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: vi.fn(),
}));
+2 -1
View File
@@ -1,7 +1,8 @@
"use server";
import { pollTaskUntilSettled } from "@/actions/task/poll";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError } from "@/lib/server-actions-helper";
import type {
IntegrationProps,
+2 -1
View File
@@ -2,7 +2,8 @@
import { revalidatePath } from "next/cache";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import { handleApiResponse } from "@/lib/server-actions-helper";
import { samlConfigFormSchema } from "@/types/formSchemas";
+2 -1
View File
@@ -4,7 +4,8 @@ import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { z } from "zod";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
const invitationTokenSchema = z.string().min(1).max(500);
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import {
validateBaseUrl,
validateCredentials,
@@ -26,6 +26,10 @@ vi.mock("@/lib", () => ({
getErrorMessage: vi.fn(),
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
@@ -111,6 +115,16 @@ describe("getAllProviderGroups", () => {
expect(result).toBeUndefined();
});
it("rethrows the framework redirect from authentication", async () => {
// Given
const redirectError = new Error("NEXT_REDIRECT");
getAuthHeadersMock.mockRejectedValueOnce(redirectError);
// When / Then
await expect(getAllProviderGroups()).rejects.toBe(redirectError);
expect(fetchMock).not.toHaveBeenCalled();
});
it("returns undefined when a later page resolves to an error payload", async () => {
handleApiResponseMock
.mockResolvedValueOnce(makePage([makeGroup("g1", "Group 1")], 1, 2))
+3 -2
View File
@@ -3,7 +3,8 @@
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { apiBaseUrl, getAuthHeaders, getErrorMessage } from "@/lib";
import { apiBaseUrl, getErrorMessage } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import { ManageGroupPayload, ProviderGroupsResponse } from "@/types/components";
@@ -65,9 +66,9 @@ export const getAllProviderGroups = async (): Promise<
const allGroups: ProviderGroupsResponse["data"] = [];
let lastResponse: ProviderGroupsResponse | undefined;
let hasMorePages = true;
const headers = await getAuthHeaders({ contentType: false });
try {
const headers = await getAuthHeaders({ contentType: false });
while (hasMorePages && currentPage <= maxPages) {
const url = new URL(`${apiBaseUrl}/provider-groups`);
url.searchParams.append("page[number]", currentPage.toString());
+2 -1
View File
@@ -2,7 +2,8 @@
import { revalidatePath } from "next/cache";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import {
DeleteMuteRuleActionState,
@@ -23,6 +23,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
+2 -1
View File
@@ -2,7 +2,8 @@
import { revalidatePath } from "next/cache";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import {
OrganizationListResponse,
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -2,7 +2,8 @@
import { redirect } from "next/navigation";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -2,7 +2,8 @@
import { redirect } from "next/navigation";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
@@ -4,7 +4,8 @@ import {
getDateFromForTimeRange,
type TimeRange,
} from "@/app/(prowler)/_overview/severity-over-time/_constants/time-range.constants";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import { mutedFindingsConfigFormSchema } from "@/types/formSchemas";
import {
DeleteMutedFindingsConfigActionState,
+4
View File
@@ -29,6 +29,10 @@ vi.mock("@/lib", () => ({
wait: vi.fn(),
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/provider-credentials/build-credentials", () => ({
buildSecretConfig: vi.fn(() => ({
secretType: "access-secret-key",
+2 -1
View File
@@ -3,7 +3,8 @@
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { apiBaseUrl, getAuthHeaders, getFormValue, wait } from "@/lib";
import { apiBaseUrl, getFormValue, wait } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { buildSecretConfig } from "@/lib/provider-credentials/build-credentials";
import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields";
import { appendSanitizedProviderInFilters } from "@/lib/provider-filters";
+4
View File
@@ -43,6 +43,10 @@ vi.mock("@/lib", () => ({
splitCsvFilterValues,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiResponse: handleApiResponseMock,
}));
+1 -1
View File
@@ -8,9 +8,9 @@ import {
apiBaseUrl,
FINDINGS_FILTERED_SORT,
GENERIC_SERVER_ERROR_MESSAGE,
getAuthHeaders,
sanitizeErrorMessage,
} from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { appendSanitizedProviderTypeFilters } from "@/lib/provider-filters";
import { handleApiResponse } from "@/lib/server-actions-helper";
import { OrganizationResource } from "@/types/organizations";
+4
View File
@@ -25,6 +25,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
+2 -1
View File
@@ -3,7 +3,8 @@
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
export const getRoles = async ({
@@ -4,7 +4,8 @@ import yaml from "js-yaml";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import { scanConfigurationFormSchema } from "@/types/formSchemas";
import {
DeleteScanConfigurationActionState,
+4
View File
@@ -21,6 +21,10 @@ vi.mock("@/lib", () => ({
error instanceof Error ? error.message : String(error),
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
+1 -1
View File
@@ -6,9 +6,9 @@ import { redirect } from "next/navigation";
import {
apiBaseUrl,
GENERIC_SERVER_ERROR_MESSAGE,
getAuthHeaders,
getErrorMessage,
} from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import {
COMPLIANCE_REPORT_DISPLAY_NAMES,
type ComplianceReportType,
+4
View File
@@ -28,6 +28,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
+2 -1
View File
@@ -3,7 +3,8 @@
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { scheduleUpdatePayloadSchema } from "@/lib/schedules";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import type {
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
export const getTask = async (taskId: string) => {
+2 -1
View File
@@ -4,7 +4,8 @@ import { revalidatePath } from "next/cache";
import { z } from "zod";
import { signOut } from "@/auth.config";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
export const getAllTenants = async () => {
+2 -1
View File
@@ -5,7 +5,8 @@ import { redirect } from "next/navigation";
import { z } from "zod";
import { auth } from "@/auth.config";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import {
TENANT_MEMBERSHIP_ROLE,
@@ -19,6 +19,10 @@ vi.mock("@/lib", () => ({
error instanceof Error ? error.message : String(error),
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
+2 -1
View File
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import {
@@ -19,6 +19,10 @@ vi.mock("@/lib", () => ({
error instanceof Error ? error.message : String(error),
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiError: handleApiErrorMock,
handleApiResponse: handleApiResponseMock,
@@ -1,6 +1,7 @@
"use server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
const RECIPIENTS_PATH = "/alerts/recipients";
@@ -20,6 +20,10 @@ vi.mock("@/lib", () => ({
GENERIC_SERVER_ERROR_MESSAGE: "Generic server error.",
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/server-actions-helper", () => ({
handleApiResponse: handleApiResponseMock,
}));
@@ -6,10 +6,10 @@ import type { ScanBinaryResult } from "@/actions/scans/scans";
import {
apiBaseUrl,
GENERIC_SERVER_ERROR_MESSAGE,
getAuthHeaders,
getErrorMessage,
} from "@/lib";
import { hasActionError } from "@/lib/action-errors";
import { getAuthHeaders } from "@/lib/auth-headers";
import { handleApiResponse } from "@/lib/server-actions-helper";
import { SentryErrorSource, SentryErrorType } from "@/sentry";
@@ -24,6 +24,12 @@ vi.mock("@/lib/helper", () => ({
GENERIC_SERVER_ERROR_MESSAGE: "Server error",
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: vi
.fn()
.mockResolvedValue({ Authorization: "Bearer token-123" }),
}));
import {
createLighthouseV2Session,
getLighthouseV2SupportedModels,
@@ -13,7 +13,8 @@ import type {
LighthouseV2SupportedModel,
LighthouseV2SupportedProvider,
} from "@/app/(prowler)/lighthouse/_types";
import { apiBaseUrl, getAuthHeaders } from "@/lib/helper";
import { getAuthHeaders } from "@/lib/auth-headers";
import { apiBaseUrl } from "@/lib/helper";
import { LIGHTHOUSE_ROUTE } from "@/lib/lighthouse-routes";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import type { JsonApiDocument } from "@/types/jsonapi";
@@ -11,6 +11,10 @@ vi.mock("@/lib", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
vi.mock("@/lib/auth-headers", () => ({
getAuthHeaders: getAuthHeadersMock,
}));
describe("GET /api/scans/[scanId]/report", () => {
afterEach(() => {
vi.unstubAllGlobals();
+2 -1
View File
@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import { apiBaseUrl, getAuthHeaders } from "@/lib";
import { apiBaseUrl } from "@/lib";
import { getAuthHeaders } from "@/lib/auth-headers";
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
+43
View File
@@ -0,0 +1,43 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const { authMock, getRequiredAuthHeadersMock } = vi.hoisted(() => ({
authMock: vi.fn(),
getRequiredAuthHeadersMock: vi.fn(),
}));
vi.mock("server-only", () => ({}));
vi.mock("@/auth.config", () => ({
auth: authMock,
}));
vi.mock("./server-auth", () => ({
getRequiredAuthHeaders: getRequiredAuthHeadersMock,
}));
import { getAuthHeaders } from "./auth-headers";
describe("getAuthHeaders", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("forwards the restored session and requested header options", async () => {
// Given
authMock.mockResolvedValue({
accessToken: "access-token",
error: "RefreshAccessTokenError",
});
const options = { contentType: true };
// When
await getAuthHeaders(options);
// Then
expect(getRequiredAuthHeadersMock).toHaveBeenCalledWith(
"access-token",
options,
"RefreshAccessTokenError",
);
});
});
+11
View File
@@ -0,0 +1,11 @@
import "server-only";
import { auth } from "@/auth.config";
import { getRequiredAuthHeaders } from "./server-auth";
export const getAuthHeaders = async (options?: { contentType?: boolean }) => {
const session = await auth();
return getRequiredAuthHeaders(session?.accessToken, options, session?.error);
};
-4
View File
@@ -15,10 +15,6 @@ vi.mock("@/actions/task", () => ({
getTask: vi.fn(),
}));
vi.mock("@/auth.config", () => ({
auth: vi.fn(),
}));
const createToast = () => vi.fn();
const getAnchor = () => {
-14
View File
@@ -5,7 +5,6 @@ import {
type ScanBinaryResult,
} from "@/actions/scans";
import { getTask } from "@/actions/task";
import { auth } from "@/auth.config";
import { useToast } from "@/components/shadcn";
import {
COMPLIANCE_REPORT_DISPLAY_NAMES,
@@ -14,8 +13,6 @@ import {
import { readEnv } from "@/lib/runtime-env";
import { AuthSocialProvider, MetaDataProps, PermissionInfo } from "@/types";
import { getRequiredAuthHeaders } from "./server-auth";
export const baseUrl = process.env.AUTH_URL;
export const apiBaseUrl = readEnv(
"UI_API_BASE_URL",
@@ -55,17 +52,6 @@ export function filterEmptyValues(
);
}
/**
* Returns the authentication headers for API requests
* @param options - Optional configuration options
* @returns Authentication headers with Accept and Authorization
*/
export const getAuthHeaders = async (options?: { contentType?: boolean }) => {
const session = await auth();
return getRequiredAuthHeaders(session?.accessToken, options, session?.error);
};
export const getAuthUrl = (provider: AuthSocialProvider) => {
const config = {
google: {
+2
View File
@@ -7,6 +7,8 @@ const { headersMock, redirectMock } = vi.hoisted(() => ({
}),
}));
vi.mock("server-only", () => ({}));
vi.mock("next/headers", () => ({
headers: headersMock,
}));
+2
View File
@@ -1,3 +1,5 @@
import "server-only";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
+2
View File
@@ -10,6 +10,8 @@ import { afterAll, afterEach, beforeAll, vi } from "vitest";
import { worker } from "./__tests__/msw/worker";
vi.mock("server-only", () => ({}));
// Server Actions ("use server") are bundled by Vite as plain async functions
// — the directive is a Next.js compiler concept, not part of Vite. When the
// page invokes one, it runs in the browser and reaches `auth()` from