Update admin session, gateway, jobs/leads routes, login, and add API me endpoint
This commit is contained in:
parent
b117514df7
commit
394046fdb3
6 changed files with 73 additions and 5 deletions
|
|
@ -4,7 +4,18 @@ const SESSION_TTL_SECONDS = 60 * 60 * 12;
|
||||||
|
|
||||||
export function hasAdminSession(): boolean {
|
export function hasAdminSession(): boolean {
|
||||||
if (typeof document === 'undefined') return false;
|
if (typeof document === 'undefined') return false;
|
||||||
return document.cookie.split(';').some((entry) => entry.trim() === `${SESSION_COOKIE}=${SESSION_VALUE}`);
|
// Check cookie exists
|
||||||
|
const hasCookie = document.cookie.split(';').some((entry) => entry.trim() === `${SESSION_COOKIE}=${SESSION_VALUE}`);
|
||||||
|
// Also check if sessionStorage has a valid token as fallback
|
||||||
|
const hasToken = (() => {
|
||||||
|
try {
|
||||||
|
const token = sessionStorage.getItem('nxtgauge_admin_access_token');
|
||||||
|
return Boolean(token && token.trim().length > 0);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return hasCookie || hasToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAdminSession(): void {
|
export function setAdminSession(): void {
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,18 @@ export function forwardCookies(request: Request): Record<string, string> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge auth + cookie headers from the incoming request with any extra headers provided.
|
* Merge auth + cookie headers from the incoming request with any extra headers provided.
|
||||||
|
* Extra headers (e.g. Content-Type: multipart/form-data for file uploads) take precedence
|
||||||
|
* over the default application/json.
|
||||||
*/
|
*/
|
||||||
export function withAuthHeaders(
|
export function withAuthHeaders(
|
||||||
request: Request,
|
request: Request,
|
||||||
extra: Record<string, string> = {},
|
extra: Record<string, string> = {},
|
||||||
): Record<string, string> {
|
): Record<string, string> {
|
||||||
return {
|
return {
|
||||||
'Content-Type': 'application/json',
|
|
||||||
...forwardAuth(request),
|
...forwardAuth(request),
|
||||||
...forwardCookies(request),
|
...forwardCookies(request),
|
||||||
...extra,
|
...extra,
|
||||||
|
// Default Content-Type only if extra didn't already provide one
|
||||||
|
...(extra['Content-Type'] ? {} : { 'Content-Type': 'application/json' }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,16 @@ export default function JobsManagementPage() {
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API}/api/admin/companies/jobs`);
|
const accessToken = typeof sessionStorage !== 'undefined'
|
||||||
|
? sessionStorage.getItem('nxtgauge_admin_access_token') || ''
|
||||||
|
: '';
|
||||||
|
const res = await fetch('/api/admin/companies/jobs', {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
});
|
||||||
if (!res.ok) throw new Error('Fetch failed');
|
if (!res.ok) throw new Error('Fetch failed');
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const list = Array.isArray(data) ? data : (data.jobs || []);
|
const list = Array.isArray(data) ? data : (data.jobs || []);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,16 @@ const ROLE_OPTIONS = [
|
||||||
|
|
||||||
async function loadLeads(): Promise<any[]> {
|
async function loadLeads(): Promise<any[]> {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API}/api/admin/leads`);
|
const accessToken = typeof sessionStorage !== 'undefined'
|
||||||
|
? sessionStorage.getItem('nxtgauge_admin_access_token') || ''
|
||||||
|
: '';
|
||||||
|
const res = await fetch('/api/admin/leads', {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
});
|
||||||
if (!res.ok) throw new Error('Failed to load');
|
if (!res.ok) throw new Error('Failed to load');
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return Array.isArray(data) ? data : (data.leads || []);
|
return Array.isArray(data) ? data : (data.leads || []);
|
||||||
|
|
|
||||||
36
src/routes/api/me/notifications/unread-count.ts
Normal file
36
src/routes/api/me/notifications/unread-count.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { gatewayUrl, forwardAuth } from '~/lib/server/gateway';
|
||||||
|
|
||||||
|
export async function GET({ request }: { request: Request }) {
|
||||||
|
try {
|
||||||
|
const upstreamUrl = gatewayUrl('/api/me/notifications/unread-count');
|
||||||
|
const upstreamInit: RequestInit = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
...forwardAuth(request),
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(upstreamUrl, upstreamInit);
|
||||||
|
const responseHeaders = new Headers();
|
||||||
|
response.headers.forEach((value, key) => {
|
||||||
|
if (!['server', 'transfer-encoding', 'connection'].includes(key.toLowerCase())) {
|
||||||
|
responseHeaders.set(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
responseHeaders.set('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
const responseBody = await response.text();
|
||||||
|
return new Response(responseBody, {
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: responseHeaders,
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({ success: false, unread_count: 0 }),
|
||||||
|
{ status: 200, headers: { 'Content-Type': 'application/json' } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ export default function LoginPage() {
|
||||||
const body = JSON.stringify({ email: email().trim().toLowerCase(), password: password(), loginTarget: 'admin' });
|
const body = JSON.stringify({ email: email().trim().toLowerCase(), password: password(), loginTarget: 'admin' });
|
||||||
const headers = { 'Content-Type': 'application/json', Accept: 'application/json', 'x-portal-target': 'admin' };
|
const headers = { 'Content-Type': 'application/json', Accept: 'application/json', 'x-portal-target': 'admin' };
|
||||||
let payload: any = {}; let status = 500; let success = false;
|
let payload: any = {}; let status = 500; let success = false;
|
||||||
const r = await fetch('/api/auth/login', { method: 'POST', headers, credentials: 'include', body });
|
const r = await fetch('/api/admin/auth/login', { method: 'POST', headers, credentials: 'include', body });
|
||||||
status = r.status; payload = await r.json().catch(() => ({}));
|
status = r.status; payload = await r.json().catch(() => ({}));
|
||||||
if (r.ok) { success = true; }
|
if (r.ok) { success = true; }
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue