mirror of
https://github.com/Steffo99/festa.git
synced 2024-12-22 14:44:21 +00:00
123 lines
4.7 KiB
TypeScript
123 lines
4.7 KiB
TypeScript
import { database } from "../../../utils/prismaClient";
|
|
import { NextApiRequest, NextApiResponse } from "next";
|
|
import { TelegramLoginObject } from "../../../components/auth/telegram/processing";
|
|
import { default as cryptoRandomString } from "crypto-random-string"
|
|
import { festaAPI } from "../../../utils/api";
|
|
import { festaNoAuth } from "../../../utils/api/authenticator";
|
|
import { festaJsonSchemaBody } from "../../../utils/api/bodyValidator";
|
|
import { TelegramLoginResponse } from "react-telegram-login";
|
|
import { Response } from "../../../utils/api/throwables";
|
|
import { festaNoQuery } from "../../../utils/api/queryValidator";
|
|
|
|
|
|
type Config = {
|
|
botToken: string,
|
|
hashExpirationMs: number,
|
|
tokenExpirationMs: number,
|
|
}
|
|
|
|
|
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
await festaAPI(req, res, {
|
|
|
|
configurator: {
|
|
perform: async () => {
|
|
const botToken = process.env.TELEGRAM_TOKEN
|
|
if (!botToken) {
|
|
throw Response.error({ status: 503, message: "`TELEGRAM_TOKEN` was not set up" })
|
|
}
|
|
const hashExpirationMs = parseInt(process.env.TELEGRAM_HASH_EXPIRATION_MS!) // TypeScript type is wrong?
|
|
if (!hashExpirationMs) {
|
|
throw Response.error({ status: 503, message: "`TELEGRAM_HASH_EXPIRATION_MS` was not set up" })
|
|
}
|
|
const tokenExpirationMs = parseInt(process.env.FESTA_TOKEN_EXPIRATION_MS!) // TypeScript type is wrong?
|
|
if (!tokenExpirationMs) {
|
|
throw Response.error({ status: 503, message: "`FESTA_TOKEN_EXPIRATION_MS` was not set up" })
|
|
}
|
|
|
|
return { botToken, hashExpirationMs, tokenExpirationMs }
|
|
}
|
|
},
|
|
|
|
authenticator: festaNoAuth,
|
|
|
|
queryValidator: festaNoQuery,
|
|
|
|
bodyValidator: festaJsonSchemaBody<TelegramLoginResponse>({
|
|
type: "object",
|
|
properties: {
|
|
id: { type: "integer" },
|
|
first_name: { type: "string" },
|
|
auth_date: { type: "integer" },
|
|
hash: { type: "string" },
|
|
last_name: { type: "string", nullable: true },
|
|
username: { type: "string", nullable: true },
|
|
photo_url: { type: "string", nullable: true },
|
|
lang: { type: "string", nullable: true },
|
|
},
|
|
required: [
|
|
"id",
|
|
"first_name",
|
|
"auth_date",
|
|
"hash",
|
|
]
|
|
}),
|
|
|
|
executor: {
|
|
methods: ["POST"],
|
|
perform: async ({ config, body }) => {
|
|
try {
|
|
var tlo: TelegramLoginObject = new TelegramLoginObject(body!)
|
|
}
|
|
catch (e) {
|
|
throw Response.error({ status: 422, message: "Telegram Login response validation failed" })
|
|
}
|
|
|
|
if (!tlo.isRecent(config.hashExpirationMs)) {
|
|
throw Response.error({ status: 408, message: "Telegram login data is not recent" })
|
|
}
|
|
|
|
if (!tlo.isValid(config.botToken)) {
|
|
throw Response.error({ status: 401, message: "Telegram login data has been tampered" })
|
|
}
|
|
|
|
const accountTelegram = await database.accountTelegram.upsert({
|
|
where: {
|
|
telegramId: tlo.id
|
|
},
|
|
create: {
|
|
...tlo.toDatabase(),
|
|
user: {
|
|
create: {
|
|
displayName: tlo.toTelegramName(),
|
|
displayAvatarURL: tlo.photoUrl,
|
|
}
|
|
}
|
|
},
|
|
update: {
|
|
...tlo.toDatabase(),
|
|
user: {
|
|
update: {
|
|
displayName: tlo.toTelegramName(),
|
|
displayAvatarURL: tlo.photoUrl,
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
const token = await database.token.create({
|
|
data: {
|
|
userId: accountTelegram.userId,
|
|
token: cryptoRandomString({ length: 16, type: "base64" }),
|
|
expiresAt: new Date(tlo.authDate.getTime() + config.tokenExpirationMs)
|
|
},
|
|
include: {
|
|
user: true,
|
|
}
|
|
})
|
|
|
|
return token
|
|
}
|
|
},
|
|
})
|
|
}
|