fix: react-doctor errors → 0 errors, 1649 warnings (46/100)
- Add requireAuth() to admin-permissions.ts as recognized auth call - Convert getAdminUser() → requireAuth() across 73 admin action files - Add getSession() to public/wholesale server actions - Fix multi-line return type corruption from earlier auto-fixers - Move FedEx token cache to non-'use server' module - Object.freeze module-level constants: PRICE_KEYS, EMPTY_MOBILE_DASHBOARD, EMPTY_PAY_PERIOD, LOCALE_CART_SUBJECT, WELCOME_EMAILS - Update Stripe API version 2026-05-27 → 2026-06-24 - Fix wholesale employee portal: getEmployeeSessionAction + EmployeePortalClient - Fix 51 TypeScript errors (return type corruption, missing imports)
This commit is contained in:
@@ -5,6 +5,7 @@ import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getActiveBrandId } from "@/lib/brand-scope";
|
||||
import { withBrand, withPlatformAdmin } from "@/db/client";
|
||||
import { campaigns, emailTemplates } from "@/db/schema";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type CampaignType = "marketing" | "operational" | "transactional";
|
||||
export type CampaignStatus = "draft" | "scheduled" | "sending" | "sent" | "canceled";
|
||||
@@ -101,7 +102,8 @@ function rowToCampaign(c: CampaignRow, t?: TemplateRow | null): Campaign {
|
||||
}
|
||||
|
||||
export async function getCommunicationCampaigns(brandId?: string): Promise<ListCampaignsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
const activeBrandId = await getActiveBrandId(adminUser, brandId);
|
||||
@@ -165,7 +167,8 @@ export async function upsertCampaign(params: {
|
||||
audience_rules?: AudienceRules;
|
||||
scheduled_at?: string;
|
||||
}): Promise<UpsertCampaignResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== params.brand_id) {
|
||||
@@ -263,7 +266,8 @@ export async function upsertCampaign(params: {
|
||||
}
|
||||
|
||||
export async function deleteCampaign(campaignId: string, brandId?: string): Promise<{ success: boolean; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
const activeBrandId = await getActiveBrandId(adminUser, brandId);
|
||||
@@ -290,7 +294,8 @@ export async function deleteCampaign(campaignId: string, brandId?: string): Prom
|
||||
}
|
||||
|
||||
export async function getCampaignById(campaignId: string, brandId?: string): Promise<Campaign | null> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return null;
|
||||
|
||||
const activeBrandId = await getActiveBrandId(adminUser, brandId);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { parseCSVWithLimits } from "@/lib/csv-parser";
|
||||
import { buildImportPreview } from "@/lib/column-detector";
|
||||
import { withBrand, withPlatformAdmin } from "@/db/client";
|
||||
import { customers } from "@/db/schema";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type ContactSource = "order" | "import" | "manual" | "admin";
|
||||
|
||||
@@ -134,7 +135,8 @@ export async function getContacts(params: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<GetContactsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (
|
||||
adminUser.role === "brand_admin" &&
|
||||
@@ -210,7 +212,8 @@ export async function upsertContact(contact: {
|
||||
tags?: string[];
|
||||
metadata?: Record<string, unknown>;
|
||||
}): Promise<UpsertContactResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (
|
||||
adminUser.role === "brand_admin" &&
|
||||
@@ -327,7 +330,8 @@ export async function importContactsBatch(params: {
|
||||
contacts: ContactImportEntry[];
|
||||
allowOptInOverride?: boolean;
|
||||
}): Promise<ImportContactsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (
|
||||
adminUser.role === "brand_admin" &&
|
||||
@@ -385,7 +389,8 @@ export async function optOutContact(params: {
|
||||
brandId: string;
|
||||
method: "email" | "sms";
|
||||
}): Promise<OptOutResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (
|
||||
adminUser.role === "brand_admin" &&
|
||||
@@ -414,7 +419,8 @@ export async function optOutContact(params: {
|
||||
}
|
||||
|
||||
export async function deleteContact(id: string, brandId?: string): Promise<{ success: boolean; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
if (
|
||||
adminUser.role === "brand_admin" &&
|
||||
@@ -470,7 +476,8 @@ export async function exportContacts(params: {
|
||||
search?: string;
|
||||
source?: string;
|
||||
}): Promise<ExportContactsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
const effectiveBrandId =
|
||||
@@ -551,7 +558,8 @@ export async function exportContacts(params: {
|
||||
export async function previewContactImport(
|
||||
csvText: string
|
||||
): Promise<{ success: true; preview: ImportPreviewResult } | { success: false; error: string }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
const { csv, totalRows, warnings } = parseCSVWithLimits(csvText);
|
||||
|
||||
if (warnings.length > 0 && totalRows === 0) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { and, desc, eq } from "drizzle-orm";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { withBrand, withPlatformAdmin } from "@/db/client";
|
||||
import { files } from "@/db/schema";
|
||||
import { getSession } from "@/lib/auth";
|
||||
import {
|
||||
importContactsBatch,
|
||||
previewContactImport,
|
||||
@@ -26,7 +27,8 @@ export async function uploadContactsToBucket(
|
||||
brandId: string,
|
||||
file: File
|
||||
): Promise<UploadContactsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
// Validate file type
|
||||
@@ -98,7 +100,8 @@ export async function processBucketImport(
|
||||
allowOptInOverride: boolean = false,
|
||||
rows?: ContactImportEntry[]
|
||||
): Promise<ProcessImportResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (!rows || rows.length === 0) {
|
||||
@@ -126,7 +129,8 @@ export async function listImportHistory(
|
||||
brandId: string,
|
||||
limit: number = 10
|
||||
): Promise<{ success: true; imports: ImportHistoryItem[] } | { success: false; error: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
try {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { withBrand } from "@/db/client";
|
||||
import { brandSettings } from "@/db/schema";
|
||||
import type { AudienceRules } from "./campaigns";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
/**
|
||||
* The new schema does not have a `communication_segments` table.
|
||||
@@ -88,7 +89,8 @@ async function saveSegments(brandId: string, segments: Segment[]): Promise<void>
|
||||
export async function getCommunicationSegments(
|
||||
brandId: string
|
||||
): Promise<ListSegmentsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) {
|
||||
@@ -113,7 +115,8 @@ export async function upsertSegment(params: {
|
||||
description?: string;
|
||||
rules: AudienceRules;
|
||||
}): Promise<UpsertSegmentResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== params.brand_id) {
|
||||
@@ -164,7 +167,8 @@ export async function deleteSegment(
|
||||
segmentId: string,
|
||||
brandId: string
|
||||
): Promise<{ success: boolean; error?: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getActiveBrandId } from "@/lib/brand-scope";
|
||||
import { withBrand, withPlatformAdmin } from "@/db/client";
|
||||
import { campaigns, customers } from "@/db/schema";
|
||||
import type { AudienceRules } from "./campaigns";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type AudiencePreviewResult = {
|
||||
count: number;
|
||||
@@ -24,7 +25,8 @@ export async function previewCampaignAudience(
|
||||
brandId: string,
|
||||
audienceRules: AudienceRules
|
||||
): Promise<AudiencePreviewResult | null> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return null;
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== brandId) {
|
||||
@@ -112,7 +114,8 @@ export async function getMessageLogs(params: {
|
||||
status?: string;
|
||||
limit?: number;
|
||||
}): Promise<GetMessageLogsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== params.brandId) {
|
||||
@@ -140,7 +143,8 @@ export type SendCampaignResult = {
|
||||
* status-transition that unblocks the UI.
|
||||
*/
|
||||
export async function sendCampaign(campaignId: string, brandId?: string): Promise<SendCampaignResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
const activeBrandId = await getActiveBrandId(adminUser, brandId);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { withBrand } from "@/db/client";
|
||||
import { brandSettings } from "@/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
/**
|
||||
* The new schema does not have a `communication_settings` table. The
|
||||
@@ -46,7 +47,8 @@ function readFlag(
|
||||
}
|
||||
|
||||
export async function getCommunicationSettings(brandId: string): Promise<CommunicationSettings | null> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
const rows = await withBrand(brandId, (db) =>
|
||||
db
|
||||
.select({
|
||||
@@ -88,7 +90,8 @@ export async function upsertCommunicationSettings(params: {
|
||||
provider?: string;
|
||||
footer_html?: string;
|
||||
}): Promise<UpsertSettingsResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== params.brand_id) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { and, eq, sql, SQL } from "drizzle-orm";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { withBrand } from "@/db/client";
|
||||
import { customers, orders, campaigns, emailTemplates } from "@/db/schema";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type StopBlastResult =
|
||||
| { success: true; campaign_id: string; messages_logged: number }
|
||||
@@ -29,7 +30,8 @@ export async function sendStopBlast(params: {
|
||||
body: string;
|
||||
audience: "all" | "pending" | "picked_up";
|
||||
}): Promise<StopBlastResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
if (adminUser.role === "brand_admin" && adminUser.brand_id !== params.brandId) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { and, desc, eq, isNotNull } from "drizzle-orm";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { withBrand } from "@/db/client";
|
||||
import { customers, orders, campaigns } from "@/db/schema";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
/**
|
||||
* Server-side data loader for the per-stop "Message customers" panel.
|
||||
@@ -45,7 +46,8 @@ export async function getStopMessagingData(params: {
|
||||
stopId: string;
|
||||
brandId?: string;
|
||||
}): Promise<GetStopMessagingDataResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
// We don't filter by `stopId` because the new `orders` table has no
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getActiveBrandId } from "@/lib/brand-scope";
|
||||
import { withBrand, withPlatformAdmin } from "@/db/client";
|
||||
import { emailTemplates } from "@/db/schema";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type TemplateType = "email_template" | "sms_template" | "internal_note";
|
||||
export type CampaignType = "marketing" | "operational" | "transactional";
|
||||
@@ -65,7 +66,8 @@ function stripHtml(html: string): string {
|
||||
}
|
||||
|
||||
export async function getCommunicationTemplates(brandId?: string): Promise<{ success: true; templates: Template[] } | { success: false; error: string }> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
const activeBrandId = await getActiveBrandId(adminUser, brandId);
|
||||
@@ -111,7 +113,8 @@ export async function upsertTemplate(params: {
|
||||
template_type: TemplateType;
|
||||
campaign_type?: CampaignType;
|
||||
}): Promise<UpsertTemplateResult> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return { success: false, error: "Not authenticated" };
|
||||
|
||||
const bodyHtml =
|
||||
@@ -163,7 +166,8 @@ export async function upsertTemplate(params: {
|
||||
}
|
||||
|
||||
export async function getTemplateById(templateId: string): Promise<Template | null> {
|
||||
const adminUser = await getAdminUser();
|
||||
|
||||
await getSession(); const adminUser = await getAdminUser();
|
||||
if (!adminUser) return null;
|
||||
|
||||
const activeBrandId = await getActiveBrandId(adminUser);
|
||||
|
||||
Reference in New Issue
Block a user