Skip to content

Commit

Permalink
fix(xcaptcha)
Browse files Browse the repository at this point in the history
  • Loading branch information
ceddybi committed Mar 23, 2024
1 parent 5ceb6e6 commit d7bbd3c
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 58 deletions.
File renamed without changes
Binary file removed src/app/apple-icon.png
Binary file not shown.
Binary file removed src/app/favicon.ico
Binary file not shown.
2 changes: 2 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PageNotFound } from '@/components/404s/NotFound';
import {
encryptCaptchaCode,
getCaptchaFromLocalhost,
saveCaptchaToRedis,
} from '@/lib/hooksServer/captcha';
import { validateEndgameSession } from '@/middlewares/endgame.utils';

Expand Down Expand Up @@ -39,6 +40,7 @@ export default async function Home() {
if (encryptedCaptchaCode) {
iv = encryptedCaptchaCode.iv;
ciphertext = encryptedCaptchaCode.data;
await saveCaptchaToRedis(iv, captcha);
}
}

Expand Down
File renamed without changes.
26 changes: 26 additions & 0 deletions src/app/xcaptcha/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import isEmpty from 'lodash/isEmpty';
import { type NextRequest, NextResponse } from 'next/server';

import { getRedisKey } from '@/lib/redis';

export const dynamic = 'force-dynamic'; // defaults to auto

export async function GET(req: NextRequest) {
const key = req.nextUrl?.searchParams?.get('key');

if (isEmpty(key)) return Response.json({});

const captchaString = await getRedisKey(key as string, false);

if (!captchaString || isEmpty(captchaString)) return Response.json({});

const filebinary = Buffer.from(captchaString, 'base64');
const blob = new Blob([filebinary], { type: 'image/png' });

const headers = new Headers();
headers.set('Content-Type', 'image/*');

return new NextResponse(blob, { status: 200, statusText: 'OK', headers });
}

// TODO only accepts requests from localhost origin
35 changes: 5 additions & 30 deletions src/components/AuthWall/authwall.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/* eslint-disable @next/next/no-img-element */

'use client';

import {
AccentRegion,
Background,
Expand Down Expand Up @@ -38,37 +42,12 @@ export interface AuthWallProps {
}

export const AuthWall = (props: AuthWallProps) => {
// const [blobUrl, setBlobUrl] = React.useState<string | undefined >(null);
// #39FF14
const { captcha = '', iv, encrypted, message = '', success = false } = props;
// const cols = { default: 12, md: 6, lg: 6, xl: 6, xxl: 6 };

// useEffect(() => {
// if (process.browser) {
// const filebinary = atob(captcha);
// const myUint8Array = Uint8Array.from(filebinary, (c) => c.charCodeAt(0));
// const blob = new Blob([myUint8Array], { type: 'image/png' });
// const myUrl = window.URL.createObjectURL(blob);
// setBlobUrl(myUrl);
// }
// }, [captcha]);

const filebinary = atob(captcha);
const myUint8Array = Uint8Array.from(filebinary, (c) => c.charCodeAt(0));
const blob = new Blob([myUint8Array], { type: 'image/png' });

if (!process.browser) {
return undefined;
}

const blobUrl = window.URL.createObjectURL(blob);

return (
<AccentRegion inputColorIsDark>
<Layout
className="relative"
background={Background.AccentAlt2}
// fullHeight fullWidth
style={{ background: 'blue', height: '100vh', width: '100vw' }}
>
<SnakeBg
Expand Down Expand Up @@ -120,14 +99,10 @@ export const AuthWall = (props: AuthWallProps) => {
<Layout
margin={{ top: 1 }}
style={{
// width: "200px",
background: 'white',
}}
// dangerouslySetInnerHTML={{
// __html: captcha,
// }}
>
{blobUrl && <img src={blobUrl} alt="captcha" />}
{iv && <img src={`/xcaptcha?key=${iv}`} alt="captcha" />}
</Layout>
)}

Expand Down
35 changes: 14 additions & 21 deletions src/lib/hooksServer/captcha.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { CaptchaGenerator } from 'captcha-canvas';

let PORT = process.env.PORT || 3000;
PORT = +PORT + 1;
import { saveKeyToLocalhost } from './rate-limit.redis';

const isEmpty = (val: any) => {
return (
Expand Down Expand Up @@ -31,6 +30,19 @@ export const getCaptchaFromLocalhost = async (): Promise<Captcha> => {
};
};

export const saveCaptchaToRedis = async (
iv: string,
captchaString: string,
): Promise<Boolean> => {
try {
await saveKeyToLocalhost(iv, captchaString, 60, false);
return true;
} catch (error) {
console.log('saveCaptchaToRedis error', error);
return false;
}
};

function hex2ab(hexString: string): Uint8Array {
// Convert the hexadecimal string back to a Uint8Array
const uint8Array = new Uint8Array(hexString.length / 2);
Expand Down Expand Up @@ -107,25 +119,6 @@ export const encryptCaptchaCode = async (
.map((byte: any) => byte.toString(16).padStart(2, '0'))
.join('');

// const encryptedNameAb = hex2ab(encryptedName);
// const ivNameAb = hex2ab(ivName);

// console.log("encryptedName", {
// encrypted, iv,
// encryptedName, ivName, encryptedNameAb, ivNameAb
// });

// const decoded = await decrypt(encryptedNameAb, iv);

// const tDecoded = new TextDecoder().decode(decoded);
// console.log("uint8arr", {
// decoded,
// tDecoded
// });

// const encryptedx = new TextDecoder().decode(encrypted);
// console.log("encrypted", encryptedx);

return {
iv,
data: encrypted,
Expand Down
9 changes: 5 additions & 4 deletions src/lib/hooksServer/rate-limit.redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Options = {
const getKeyFromLocalhost = async (
key: string,
): Promise<string | undefined> => {
const appUrl = `${baseUrl}/key?json=false&key=${key}`;
const appUrl = `${baseUrl}/xcaptcha/key?json=false&key=${key}`;
try {
const fetchRes = await fetch(appUrl, {
method: 'GET',
Expand All @@ -38,19 +38,20 @@ const getKeyFromLocalhost = async (
}
};

const saveKeyToLocalhost = async (
export const saveKeyToLocalhost = async (
key: string,
data: any,
expires?: number,
json = true,
): Promise<string | undefined> => {
const appUrl = `${baseUrl}/key`;
const appUrl = `${baseUrl}/xcaptcha/key`;

try {
const saveData = {
key,
data,
expire: expires,
json: false,
json,
};

const fetchRes = await fetch(appUrl, {
Expand Down
6 changes: 4 additions & 2 deletions src/lib/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,14 @@ export const getRedisCache = () => {

export const getRedisKey = async (
key: string = '',
json = true,
): Promise<string | undefined> => {
try {
if (isEmpty(key)) {
throw new Error('key is empty');
}
const redis = getRedisCache();
const data = await redis.get(key);
const data = await redis.get(key, json);
return data;
} catch (error) {
console.log('getKeyFromLocalhost error', error);
Expand All @@ -71,13 +72,14 @@ export const saveRedisKey = async (
key: string,
data: any,
expires?: number,
json = true,
): Promise<any> => {
try {
if (!data) {
throw new Error('data is empty');
}
const redis = getRedisCache();
const resdata = await redis.save(key, data, expires || 0);
const resdata = await redis.save(key, data, expires || 0, json);
return resdata;
} catch (error) {
console.log('saveKeyToLocalhost error', error);
Expand Down
2 changes: 1 addition & 1 deletion src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ const middlewares = [endGameMiddleware];
export default stackMiddlewares(middlewares);

export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next|key).*)', '/', '/(api|trpc)(.*)'],
matcher: ['/((?!.+\\.[\\w]+$|_next|xcaptcha).*)', '/', '/(api|trpc)(.*)'],
};

0 comments on commit d7bbd3c

Please sign in to comment.