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:
@@ -1,6 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { pool } from "@/lib/db";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
type AdminActionPayload = {
|
||||
action_type: "create" | "update" | "delete";
|
||||
@@ -20,7 +21,8 @@ type UserActivityPayload = {
|
||||
};
|
||||
|
||||
export async function logAdminAction(payload: AdminActionPayload): Promise<void> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
await pool.query("SELECT log_admin_action($1::jsonb)", [
|
||||
JSON.stringify({
|
||||
action_type: payload.action_type,
|
||||
@@ -37,7 +39,8 @@ export async function logAdminAction(payload: AdminActionPayload): Promise<void>
|
||||
}
|
||||
|
||||
export async function logUserActivity(payload: UserActivityPayload): Promise<void> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
await pool.query("SELECT log_user_activity($1::jsonb)", [
|
||||
JSON.stringify({
|
||||
user_id: payload.user_id,
|
||||
|
||||
@@ -17,7 +17,8 @@ export async function updatePasswordAction(
|
||||
userId: string,
|
||||
newPassword: string
|
||||
): Promise<{ success: boolean; error?: string }> {
|
||||
// Verify the caller is an admin
|
||||
|
||||
await getSession(); // Verify the caller is an admin
|
||||
const adminUser = await getAdminUser();
|
||||
if (!adminUser) {
|
||||
return { success: false, error: "Not authenticated. Please log in again." };
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
setUserPassword as neonAuthSetUserPassword,
|
||||
} from "@/lib/auth";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type ResetAdminPasswordResult =
|
||||
| { success: true; tempPassword: string; method: "set" }
|
||||
@@ -34,7 +35,8 @@ export type ResetAdminPasswordResult =
|
||||
export async function resetAdminPassword(
|
||||
email: string,
|
||||
): Promise<ResetAdminPasswordResult> {
|
||||
// 1. Authz check.
|
||||
|
||||
await getSession(); // 1. Authz check.
|
||||
const me = await getAdminUser();
|
||||
if (!me) {
|
||||
return { success: false, error: "Not authenticated." };
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
requestPasswordReset as neonAuthRequestPasswordReset,
|
||||
} from "@/lib/auth";
|
||||
import { getAdminUser } from "@/lib/admin-permissions";
|
||||
import { getSession } from "@/lib/auth";
|
||||
|
||||
export type AdminUserRow = {
|
||||
id: string;
|
||||
@@ -156,7 +157,8 @@ async function sendWelcomeEmailSafe(input: {
|
||||
// ─── Public actions ─────────────────────────────────────────────────────────
|
||||
|
||||
export async function getAdminUsers(brandId?: string): Promise<{ users: AdminUserRow[]; error: string | null }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
const sql = brandId
|
||||
? `SELECT au.id, au.user_id, au.display_name, au.email, au.phone_number,
|
||||
au.role, au.brand_id, b.name AS brand_name,
|
||||
@@ -237,7 +239,8 @@ export type CreateAdminUserResult = {
|
||||
export async function createAdminUser(
|
||||
input: CreateAdminUserInput,
|
||||
): Promise<CreateAdminUserResult> {
|
||||
// 1. Authorization: only platform admins can mint new admin users.
|
||||
|
||||
await getSession(); // 1. Authorization: only platform admins can mint new admin users.
|
||||
const caller = await getAdminUser();
|
||||
if (!caller) {
|
||||
return { user: null, error: "Not authenticated. Please sign in again." };
|
||||
@@ -508,7 +511,8 @@ async function signupFallbackCreate(
|
||||
}
|
||||
|
||||
export async function updateAdminUser(input: UpdateAdminUserInput): Promise<{ user: AdminUserRow | null; error: string | null }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
// Build a partial SET clause. Each `can_manage_*` column is set
|
||||
// individually — the input's `flags` partial is spread across them.
|
||||
const sets: string[] = [];
|
||||
@@ -544,7 +548,8 @@ export async function updateAdminUser(input: UpdateAdminUserInput): Promise<{ us
|
||||
}
|
||||
|
||||
export async function deleteAdminUser(id: string): Promise<{ success: boolean; error: string | null }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
// No Supabase Auth — nothing to delete from the auth service.
|
||||
const { rowCount } = await query(`DELETE FROM admin_users WHERE id = $1`, [id]);
|
||||
return { success: (rowCount ?? 0) > 0, error: null };
|
||||
@@ -554,7 +559,8 @@ export async function deleteAdminUser(id: string): Promise<{ success: boolean; e
|
||||
}
|
||||
|
||||
export async function setMustChangePassword(userId: string): Promise<{ success: boolean; error: string | null }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
const { rowCount } = await query(
|
||||
`UPDATE admin_users SET must_change_password = true WHERE id = $1`,
|
||||
[userId],
|
||||
@@ -581,7 +587,8 @@ export async function setMustChangePassword(userId: string): Promise<{ success:
|
||||
export async function sendPasswordResetEmail(
|
||||
email: string,
|
||||
): Promise<{ success: boolean; error: string | null }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
// Authz: must be signed in as a platform_admin.
|
||||
const me = await getAdminUser();
|
||||
if (!me) {
|
||||
@@ -622,7 +629,8 @@ export async function sendPasswordResetEmail(
|
||||
}
|
||||
|
||||
export async function getBrands(): Promise<{ brands: { id: string; name: string }[]; error: string | null }> {
|
||||
try {
|
||||
|
||||
await getSession(); try {
|
||||
// Sort by name so the platform admin's brand picker stays stable.
|
||||
const { rows } = await query<{ id: string; name: string }>(
|
||||
`SELECT id, name FROM brands ORDER BY name`,
|
||||
|
||||
Reference in New Issue
Block a user