refactor(platform-service): auth routes + types — add productId to login/register schemas
- LoginSchema and RegisterSchema now require productId field - Login/Register routes use productId from request body (not env var) - PRODUCT_ID import removed from auth/routes.ts - Test fixtures updated with productId: 'lysnrai'
This commit is contained in:
parent
8cc70db676
commit
8e5c6dc2d6
@ -10,6 +10,7 @@ describe('LoginSchema', () => {
|
|||||||
const result = LoginSchema.safeParse({
|
const result = LoginSchema.safeParse({
|
||||||
email: 'admin@lysnrai.com',
|
email: 'admin@lysnrai.com',
|
||||||
password: 'secret123',
|
password: 'secret123',
|
||||||
|
productId: 'lysnrai',
|
||||||
});
|
});
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
});
|
});
|
||||||
@ -37,6 +38,7 @@ describe('RegisterSchema', () => {
|
|||||||
email: 'new@lysnrai.com',
|
email: 'new@lysnrai.com',
|
||||||
password: 'password123',
|
password: 'password123',
|
||||||
displayName: 'New User',
|
displayName: 'New User',
|
||||||
|
productId: 'lysnrai',
|
||||||
});
|
});
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@ -50,6 +52,7 @@ describe('RegisterSchema', () => {
|
|||||||
password: 'password123',
|
password: 'password123',
|
||||||
displayName: 'Admin',
|
displayName: 'Admin',
|
||||||
role: 'admin',
|
role: 'admin',
|
||||||
|
productId: 'lysnrai',
|
||||||
});
|
});
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { FastifyInstance } from 'fastify';
|
import type { FastifyInstance } from 'fastify';
|
||||||
import { PRODUCT_ID } from '../../lib/product-config.js';
|
|
||||||
import { BadRequestError, UnauthorizedError } from '../../lib/errors.js';
|
import { BadRequestError, UnauthorizedError } from '../../lib/errors.js';
|
||||||
import * as repo from './repository.js';
|
import * as repo from './repository.js';
|
||||||
import * as jwt from './jwt.js';
|
import * as jwt from './jwt.js';
|
||||||
@ -22,7 +21,7 @@ export async function authRoutes(app: FastifyInstance) {
|
|||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
|
throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
|
||||||
}
|
}
|
||||||
const { email, password } = parsed.data;
|
const { email, password, productId } = parsed.data;
|
||||||
const user = await repo.getByEmail(email);
|
const user = await repo.getByEmail(email);
|
||||||
if (!user) throw new UnauthorizedError('Invalid email or password');
|
if (!user) throw new UnauthorizedError('Invalid email or password');
|
||||||
if (user.status !== 'active') throw new UnauthorizedError('Account is disabled');
|
if (user.status !== 'active') throw new UnauthorizedError('Account is disabled');
|
||||||
@ -36,9 +35,9 @@ export async function authRoutes(app: FastifyInstance) {
|
|||||||
sub: user.id,
|
sub: user.id,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
role: user.role,
|
role: user.role,
|
||||||
productId: PRODUCT_ID,
|
productId,
|
||||||
});
|
});
|
||||||
const refreshToken = await jwt.createRefreshToken({ sub: user.id, productId: PRODUCT_ID });
|
const refreshToken = await jwt.createRefreshToken({ sub: user.id, productId });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accessToken,
|
accessToken,
|
||||||
@ -53,7 +52,7 @@ export async function authRoutes(app: FastifyInstance) {
|
|||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
|
throw new BadRequestError(parsed.error.issues.map(i => i.message).join('; '));
|
||||||
}
|
}
|
||||||
const { email, password, displayName, role } = parsed.data;
|
const { email, password, displayName, role, productId } = parsed.data;
|
||||||
|
|
||||||
const existing = await repo.getByEmail(email);
|
const existing = await repo.getByEmail(email);
|
||||||
if (existing) throw new BadRequestError('Email already registered');
|
if (existing) throw new BadRequestError('Email already registered');
|
||||||
@ -61,7 +60,7 @@ export async function authRoutes(app: FastifyInstance) {
|
|||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
const user: UserDoc = {
|
const user: UserDoc = {
|
||||||
id: `usr_${crypto.randomUUID()}`,
|
id: `usr_${crypto.randomUUID()}`,
|
||||||
productId: PRODUCT_ID,
|
productId,
|
||||||
email: email.toLowerCase(),
|
email: email.toLowerCase(),
|
||||||
passwordHash: await repo.hashPassword(password),
|
passwordHash: await repo.hashPassword(password),
|
||||||
role,
|
role,
|
||||||
@ -77,9 +76,9 @@ export async function authRoutes(app: FastifyInstance) {
|
|||||||
sub: user.id,
|
sub: user.id,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
role: user.role,
|
role: user.role,
|
||||||
productId: PRODUCT_ID,
|
productId,
|
||||||
});
|
});
|
||||||
const refreshToken = await jwt.createRefreshToken({ sub: user.id, productId: PRODUCT_ID });
|
const refreshToken = await jwt.createRefreshToken({ sub: user.id, productId });
|
||||||
|
|
||||||
reply.code(201);
|
reply.code(201);
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -29,6 +29,7 @@ export interface TokenPayload {
|
|||||||
export const LoginSchema = z.object({
|
export const LoginSchema = z.object({
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
password: z.string().min(1),
|
password: z.string().min(1),
|
||||||
|
productId: z.string().min(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RegisterSchema = z.object({
|
export const RegisterSchema = z.object({
|
||||||
@ -36,6 +37,7 @@ export const RegisterSchema = z.object({
|
|||||||
password: z.string().min(8),
|
password: z.string().min(8),
|
||||||
displayName: z.string().min(1),
|
displayName: z.string().min(1),
|
||||||
role: z.enum(['admin', 'viewer', 'user']).default('user'),
|
role: z.enum(['admin', 'viewer', 'user']).default('user'),
|
||||||
|
productId: z.string().min(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RefreshSchema = z.object({
|
export const RefreshSchema = z.object({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user