Phases 2-4: Auth, providers, stream management
This commit is contained in:
74
src/routes/auth/meta.ts
Normal file
74
src/routes/auth/meta.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { FastifyPluginAsync } from 'fastify';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { exchangeMetaCode, fetchMetaProfile } from '../../services/meta-auth.service.js';
|
||||
import { signAccessToken } from '../../plugins/auth.js';
|
||||
import { hashToken } from '../../services/crypto.service.js';
|
||||
import { config } from '../../config.js';
|
||||
import { AppError } from '../../plugins/error-handler.js';
|
||||
import type { MetaCallbackBody, AuthTokensResponse } from '../../types/api.js';
|
||||
|
||||
const metaAuthRoutes: FastifyPluginAsync = async (fastify) => {
|
||||
fastify.post<{ Body: MetaCallbackBody }>('/auth/meta/callback', {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['code'],
|
||||
properties: {
|
||||
code: { type: 'string', minLength: 1 },
|
||||
deviceInfo: { type: 'string' },
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
}, async (request, reply) => {
|
||||
const { code, deviceInfo } = request.body;
|
||||
|
||||
// Exchange code for Meta access token
|
||||
const { accessToken: metaToken } = await exchangeMetaCode(code);
|
||||
|
||||
// Fetch user profile
|
||||
const profile = await fetchMetaProfile(metaToken);
|
||||
|
||||
// Upsert user
|
||||
const user = await fastify.prisma.user.upsert({
|
||||
where: { metaId: profile.metaId },
|
||||
update: {
|
||||
displayName: profile.displayName,
|
||||
email: profile.email,
|
||||
avatarUrl: profile.avatarUrl,
|
||||
},
|
||||
create: {
|
||||
metaId: profile.metaId,
|
||||
displayName: profile.displayName,
|
||||
email: profile.email,
|
||||
avatarUrl: profile.avatarUrl,
|
||||
},
|
||||
});
|
||||
|
||||
// Create session with hashed refresh token
|
||||
const refreshToken = randomUUID();
|
||||
const expiresAt = new Date(Date.now() + config.jwt.refreshTtl * 1000);
|
||||
|
||||
await fastify.prisma.session.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
refreshToken: hashToken(refreshToken),
|
||||
expiresAt,
|
||||
deviceInfo: deviceInfo ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
// Sign JWT
|
||||
const accessToken = await signAccessToken(user.id);
|
||||
|
||||
const response: AuthTokensResponse = {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: config.jwt.accessTtl,
|
||||
};
|
||||
|
||||
reply.status(200).send(response);
|
||||
});
|
||||
};
|
||||
|
||||
export default metaAuthRoutes;
|
||||
Reference in New Issue
Block a user