Implement messenger login tokens and bot login endpoint

This commit is contained in:
Ruslan Bakiev
2026-04-01 19:20:42 +07:00
parent 8c8689a877
commit 23edfbe7ff
5 changed files with 172 additions and 41 deletions

View File

@@ -1,6 +1,7 @@
import crypto from 'node:crypto';
import {
consumeTemporaryLoginToken,
createLoginChallenge,
getStaticAuthCode,
issueAccessToken,
@@ -257,34 +258,23 @@ export const resolvers = {
Mutation: {
requestLoginCode: async (_, { input }, context) => {
if (input.channel !== 'EMAIL') {
throw new Error('Code login is supported only for EMAIL channel.');
}
const destination = input.destination.trim();
if (!destination) {
throw new Error('Destination is required.');
}
let user = null;
if (input.channel === 'EMAIL') {
user = await context.prisma.user.findFirst({
where: {
email: {
equals: destination,
mode: 'insensitive',
},
const user = await context.prisma.user.findFirst({
where: {
email: {
equals: destination,
mode: 'insensitive',
},
});
} else {
const connection = await context.prisma.messengerConnection.findFirst({
where: {
type: input.channel,
channelId: destination,
isActive: true,
},
include: { user: true },
orderBy: { createdAt: 'desc' },
});
user = connection?.user ?? null;
}
},
});
if (!user) {
throw new Error('User for this destination was not found.');
@@ -297,20 +287,7 @@ export const resolvers = {
});
const code = getStaticAuthCode();
const authMessage = `Код входа в Fregat: ${code}`;
if (input.channel === 'EMAIL') {
console.info(`[auth] login code for ${destination}: ${code}`);
} else {
const dispatch = await sendMessengerMessage({
type: input.channel,
channelId: destination,
message: authMessage,
});
if (!dispatch.success) {
throw new Error(`Unable to send login code: ${dispatch.detail}`);
}
}
console.info(`[auth] login code for ${destination}: ${code}`);
return {
challengeToken: challenge.challengeToken,
@@ -341,6 +318,23 @@ export const resolvers = {
};
},
consumeLoginToken: async (_, { token }, context) => {
const login = consumeTemporaryLoginToken(token);
const user = await context.prisma.user.findUnique({
where: { id: login.userId },
});
if (!user) {
throw new Error('User for this login token was not found.');
}
const session = issueAccessToken(user.id);
return {
accessToken: session.accessToken,
expiresAt: session.expiresAt,
user,
};
},
registerSelf: (_, { input }, context) =>
context.prisma.registrationRequest.create({
data: {