154 lines
4.0 KiB
TypeScript
154 lines
4.0 KiB
TypeScript
import type { UserRole } from './types'
|
|
|
|
const AUTH_COOKIE = 'balout.auth'
|
|
const AUTH_HASH_PREFIX = '#balout_auth='
|
|
|
|
export type AuthUser = {
|
|
id: string
|
|
title: string
|
|
firstName: string
|
|
lastName: string
|
|
cellNumber: string
|
|
role: UserRole
|
|
name: string
|
|
}
|
|
|
|
export type AuthSession = {
|
|
accessToken: string
|
|
refreshToken: string
|
|
user: AuthUser
|
|
}
|
|
|
|
function isSession(value: unknown): value is AuthSession {
|
|
if (!value || typeof value !== 'object') return false
|
|
const session = value as Partial<AuthSession>
|
|
return (
|
|
typeof session.accessToken === 'string' &&
|
|
typeof session.refreshToken === 'string' &&
|
|
!!session.user &&
|
|
typeof session.user === 'object' &&
|
|
typeof session.user.name === 'string' &&
|
|
typeof session.user.id === 'string'
|
|
)
|
|
}
|
|
|
|
function cookieDomain() {
|
|
const host = window.location.hostname
|
|
if (host === 'localhost' || host === '127.0.0.1') return undefined
|
|
const configured = import.meta.env.VITE_COOKIE_DOMAIN as string | undefined
|
|
if (configured) return configured
|
|
if (host.endsWith('.baloutpastry.com') || host === 'baloutpastry.com') {
|
|
return '.baloutpastry.com'
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
function readCookie(name: string) {
|
|
const prefix = `${encodeURIComponent(name)}=`
|
|
for (const part of document.cookie.split(';')) {
|
|
const trimmed = part.trim()
|
|
if (trimmed.startsWith(prefix)) {
|
|
return decodeURIComponent(trimmed.slice(prefix.length))
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
function writeCookie(name: string, value: string, maxAgeSeconds: number) {
|
|
const domain = cookieDomain()
|
|
const parts = [
|
|
`${encodeURIComponent(name)}=${encodeURIComponent(value)}`,
|
|
'Path=/',
|
|
`Max-Age=${maxAgeSeconds}`,
|
|
'SameSite=Lax',
|
|
]
|
|
if (domain) parts.push(`Domain=${domain}`)
|
|
document.cookie = parts.join('; ')
|
|
}
|
|
|
|
function clearCookie(name: string) {
|
|
const domain = cookieDomain()
|
|
const parts = [
|
|
`${encodeURIComponent(name)}=`,
|
|
'Path=/',
|
|
'Max-Age=0',
|
|
'SameSite=Lax',
|
|
]
|
|
if (domain) parts.push(`Domain=${domain}`)
|
|
document.cookie = parts.join('; ')
|
|
}
|
|
|
|
export function getSession(): AuthSession | null {
|
|
try {
|
|
const raw = readCookie(AUTH_COOKIE)
|
|
if (!raw) return null
|
|
const parsed = JSON.parse(raw) as unknown
|
|
return isSession(parsed) ? parsed : null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function setSession(session: AuthSession) {
|
|
writeCookie(AUTH_COOKIE, JSON.stringify(session), 60 * 60 * 24 * 7)
|
|
}
|
|
|
|
export function clearSession() {
|
|
clearCookie(AUTH_COOKIE)
|
|
}
|
|
|
|
export function getAuthUser(): AuthUser | null {
|
|
return getSession()?.user ?? null
|
|
}
|
|
|
|
export function getAccessToken(): string | null {
|
|
return getSession()?.accessToken ?? null
|
|
}
|
|
|
|
export function isAuthenticated(): boolean {
|
|
return getSession() !== null
|
|
}
|
|
|
|
/** Import session handed off from customer login via URL hash. */
|
|
export function consumeAuthHashFromUrl() {
|
|
const hash = window.location.hash
|
|
if (!hash.startsWith(AUTH_HASH_PREFIX)) return false
|
|
try {
|
|
const raw = decodeURIComponent(hash.slice(AUTH_HASH_PREFIX.length))
|
|
const parsed = JSON.parse(raw) as unknown
|
|
if (isSession(parsed)) {
|
|
setSession(parsed)
|
|
return true
|
|
}
|
|
} catch {
|
|
// ignore malformed payload
|
|
} finally {
|
|
const clean = `${window.location.pathname}${window.location.search}`
|
|
window.history.replaceState(null, '', clean)
|
|
}
|
|
return false
|
|
}
|
|
|
|
export function getCustomerAppUrl() {
|
|
return (
|
|
(import.meta.env.VITE_CUSTOMER_APP_URL as string | undefined)?.replace(/\/$/, '') ||
|
|
'http://customer.baloutpastry.com:5173'
|
|
)
|
|
}
|
|
|
|
export function getCustomerLoginUrl(returnUrl = window.location.origin + '/') {
|
|
const url = new URL(`${getCustomerAppUrl()}/login`)
|
|
url.searchParams.set('returnUrl', returnUrl)
|
|
return url.toString()
|
|
}
|
|
|
|
export function getCustomerDashboardUrl(path = '/') {
|
|
const base = getCustomerAppUrl()
|
|
return `${base}${path.startsWith('/') ? path : `/${path}`}`
|
|
}
|
|
|
|
export function displayName(user: AuthUser) {
|
|
const short = [user.firstName, user.lastName].filter(Boolean).join(' ').trim()
|
|
return short || user.name
|
|
}
|