admin login fixed.
Build & Push / Pipeline Tests (push) Failing after 1m34s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 56s
Test / API Unit Tests (push) Successful in 1m8s
Test / Homepage Unit Tests (push) Successful in 47s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 46s
Test / Dashboard Unit Tests (push) Failing after 43s
Test / API Integration Tests (push) Successful in 1m8s

This commit is contained in:
root
2026-07-28 22:56:18 -04:00
parent 5649ab02c7
commit 50c74b9007
29 changed files with 1155 additions and 118 deletions
+40 -9
View File
@@ -52,6 +52,23 @@ function normalizeApiBase(value) {
return base.endsWith('/api/v1') ? base : `${base}/api/v1`
}
function readArg(name) {
const prefix = `--${name}=`
const match = process.argv.slice(2).find((arg) => arg.startsWith(prefix))
return match ? match.slice(prefix.length) : undefined
}
function readValue(env, argName, envNames, fallback) {
const argValue = readArg(argName)
if (argValue !== undefined) return argValue
for (const envName of envNames) {
if (env[envName] !== undefined) return env[envName]
}
return fallback
}
function updateCookieJar(cookieJar, setCookieHeaders) {
for (const header of setCookieHeaders) {
const pair = header.split(';')[0]
@@ -71,10 +88,23 @@ function cookieHeader(cookieJar) {
.join('; ')
}
async function request(apiBase, cookieJar, pathName, options = {}) {
function originFromUrl(value) {
try {
return new URL(value).origin
} catch {
return undefined
}
}
function isMutatingMethod(method) {
return ['POST', 'PUT', 'PATCH', 'DELETE'].includes(String(method || 'GET').toUpperCase())
}
async function request(apiBase, cookieJar, pathName, options = {}, trustedOrigin) {
const headers = {
...(options.body ? { 'Content-Type': 'application/json' } : {}),
...(cookieJar.size ? { Cookie: cookieHeader(cookieJar) } : {}),
...(trustedOrigin && isMutatingMethod(options.method) ? { Origin: trustedOrigin } : {}),
...options.headers,
}
@@ -102,12 +132,13 @@ async function main() {
const localEnv = loadLocalEnv()
const env = { ...localEnv, ...process.env }
const email = env.ADMIN_SEED_EMAIL || 'admin@rentaldrivego.ma'
const password = env.ADMIN_SEED_PASSWORD
const apiBase = normalizeApiBase(env.NEXT_PUBLIC_API_URL || env.API_URL)
const email = readValue(env, 'email', ['ADMIN_EMAIL', 'ADMIN_SEED_EMAIL'], 'admin@rentaldrivego.ma')
const password = readValue(env, 'password', ['ADMIN_PASSWORD', 'ADMIN_SEED_PASSWORD'])
const apiBase = normalizeApiBase(readValue(env, 'api-url', ['NEXT_PUBLIC_API_URL', 'API_URL']))
const trustedOrigin = originFromUrl(readValue(env, 'origin', ['ADMIN_URL', 'NEXT_PUBLIC_ADMIN_URL', 'DASHBOARD_URL', 'NEXT_PUBLIC_DASHBOARD_URL'], 'http://localhost:3000/admin'))
if (!password || /^(placeholder|changeme|change-me)$/i.test(password)) {
throw new Error('Set ADMIN_SEED_PASSWORD in .env.local or in the command environment.')
throw new Error('Set ADMIN_PASSWORD or ADMIN_SEED_PASSWORD, or pass --password=...')
}
const cookieJar = new Map()
@@ -115,7 +146,7 @@ async function main() {
const login = await request(apiBase, cookieJar, '/admin/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password }),
})
}, trustedOrigin)
if (!login.response.ok) {
const error = login.json?.error || login.response.status
@@ -125,14 +156,14 @@ async function main() {
throw new Error(login.json?.message || `Admin login failed: ${error}`)
}
const me = await request(apiBase, cookieJar, '/admin/auth/me')
const me = await request(apiBase, cookieJar, '/admin/auth/me', {}, trustedOrigin)
const admin = me.json?.data ?? me.json
if (admin?.totpEnabled) {
console.log(`Admin 2FA is already enabled for ${email}.`)
return
}
const setup = await request(apiBase, cookieJar, '/admin/auth/2fa/setup', { method: 'POST' })
const setup = await request(apiBase, cookieJar, '/admin/auth/2fa/setup', { method: 'POST' }, trustedOrigin)
if (!setup.response.ok) {
throw new Error(setup.json?.message || 'Failed to create admin 2FA setup secret.')
}
@@ -144,7 +175,7 @@ async function main() {
const verify = await request(apiBase, cookieJar, '/admin/auth/2fa/verify', {
method: 'POST',
body: JSON.stringify({ code }),
})
}, trustedOrigin)
if (!verify.response.ok) {
throw new Error(verify.json?.message || 'Failed to verify generated 2FA code.')