123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- import { Request as ExpressRequest, Response as ExpressResponse } from "express";
- import { Option, tryDo } from "@shared/common/async_utils";
- import { rpcClient } from "src/utils/rpc";
- import got from "got";
- import { logger } from "src/utils/logging";
- import { ENV } from "src/utils/environment";
- export interface VerifyInfo {
- captchaSitekey: string;
- userVerified: boolean;
- needsCaptcha: boolean;
- }
- export interface VerifyRequest {
- captchaResponse: string;
- }
- interface HCaptchaResponse {
- success: boolean;
- "error-codes"?: string[];
- }
- const VERIFY_URL = "https://hcaptcha.com/siteverify";
- type GetResult = Promise<ExpressResponse<VerifyInfo>>;
- export const get = async (req: ExpressRequest, res: ExpressResponse): GetResult => {
- if (!req.session?.userId) {
- return res.json({
- captchaSitekey: ENV.HCAPTCHA_SITEKEY,
- userVerified: true,
- });
- }
- const verifiedResult = await tryDo(rpcClient.userVerified({ userId: req.session.userId }));
- let verified = true;
- if (!verifiedResult.ok) {
- logger.error("Failed to check verified state: %s", verifiedResult.error);
- } else {
- verified = verifiedResult.result.verified;
- logger.verbose("User %s (%s) verified: %s", req.session.username, req.session.userId, verified);
- }
- return res.json({
- captchaSitekey: ENV.HCAPTCHA_SITEKEY,
- userVerified: verified,
- needsCaptcha: ENV.HCAPTCHA_ENABLED === "TRUE",
- });
- };
- type PostResult = Promise<ExpressResponse<Option<unknown, { error: string }>>>;
- export const post = async (req: ExpressRequest, res: ExpressResponse): PostResult => {
- const needVerify = ENV.HCAPTCHA_ENABLED === "TRUE";
- if (!req.session?.userId) {
- return res.json({
- ok: false,
- error: "Not logged in, please log in",
- });
- }
- if (needVerify) {
- const hasToken = (body: unknown):
- body is VerifyRequest => body instanceof Object
- && (body as VerifyRequest).captchaResponse !== undefined;
- if (needVerify && !hasToken(req.body)) {
- return res.json({
- ok: false,
- error: "No user token provided, please try again",
- });
- }
- const response = await tryDo(got<HCaptchaResponse>(VERIFY_URL, {
- method: "post",
- responseType: "json",
- form: {
- secret: ENV.HCAPTCHA_SECRET,
- response: req.body.captchaResponse,
- },
- }));
- if (!response.ok) {
- logger.error("Failed to hCaptcha user %s: %s", req.session.userId, response.error);
- return res.json({
- ok: false,
- error: "Failed to verify hCaptcha response. Please try again.",
- });
- }
- const captchaResponse = response.result.body;
- if (!captchaResponse.success) {
- const errors = captchaResponse["error-codes"] ?? [];
- logger.error("Failed hCaptcha verify on user %s. Got errors: %s", req.session.userId, errors.join(";"));
- return res.json({
- ok: false,
- error: "Failed to verify hCaptcha response. Please try again.",
- });
- }
- }
- const verifyResponse = await rpcClient.verifyUser({ userId: req.session.userId });
- if (!verifyResponse.ok) {
- logger.error("Failed to verify user %s (%s)", req.session.userId, req.session.username);
- return res.json({
- ok: false,
- error: "Failed to verify your account. Please try again or contact server owners.",
- });
- }
- return res.json({
- ok: true,
- });
- };
|