mirror of
https://git.suyu.dev/suyu/website.git
synced 2025-12-25 00:34:38 +01:00
fix captcha remove shitty ratelimit
This commit is contained in:
parent
0cb5723c75
commit
5e6ad9c8d9
6 changed files with 57 additions and 24 deletions
7
src/routes/api/limit/+server.ts
Normal file
7
src/routes/api/limit/+server.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { RateLimiter, json } from "$lib/server/util/index.js";
|
||||
|
||||
export function POST({ request, getClientAddress }) {
|
||||
return json({
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { userRepo } from "$lib/server/repo";
|
||||
import type { SuyuUser } from "$lib/server/schema";
|
||||
import { RateLimiter, json } from "$lib/server/util";
|
||||
import { json } from "$lib/server/util";
|
||||
import { useAuth } from "$lib/util/api";
|
||||
import type {
|
||||
CreateAccountRequest,
|
||||
|
|
@ -18,8 +18,6 @@ import { HCAPTCHA_KEY } from "$env/static/private";
|
|||
import validator from "validator";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
const rateLimit = new RateLimiter();
|
||||
|
||||
const randomBytes = promisify(crypto.randomBytes);
|
||||
|
||||
async function genKey(username: string) {
|
||||
|
|
@ -35,12 +33,6 @@ async function genKey(username: string) {
|
|||
}
|
||||
|
||||
export async function POST({ request, getClientAddress }) {
|
||||
if (rateLimit.isLimited(getClientAddress())) {
|
||||
return json<CreateAccountResponse>({
|
||||
success: false,
|
||||
error: "rate limited",
|
||||
});
|
||||
}
|
||||
const body: CreateAccountRequest = await request.json();
|
||||
if (!body.username || !body.email || !body.captchaToken || !body.password) {
|
||||
return json<CreateAccountResponse>({
|
||||
|
|
@ -111,11 +103,6 @@ export async function POST({ request, getClientAddress }) {
|
|||
}
|
||||
|
||||
export async function GET({ request, getClientAddress }) {
|
||||
if (rateLimit.isLimited(getClientAddress()))
|
||||
return json<GetUserResponse>({
|
||||
success: false,
|
||||
error: "rate limited",
|
||||
});
|
||||
const user = await useAuth(request);
|
||||
if (!user) {
|
||||
return json<GetUserResponse>({
|
||||
|
|
@ -130,11 +117,6 @@ export async function GET({ request, getClientAddress }) {
|
|||
}
|
||||
|
||||
export async function DELETE({ request, getClientAddress }) {
|
||||
if (rateLimit.isLimited(getClientAddress()))
|
||||
return json<DeleteAccountResponse>({
|
||||
success: false,
|
||||
error: "rate limited",
|
||||
});
|
||||
const user = await useAuth(request);
|
||||
if (!user) {
|
||||
return json<DeleteAccountResponse>({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { HCAPTCHA_KEY } from "$env/static/private";
|
||||
import { PUBLIC_SITE_KEY } from "$env/static/public";
|
||||
import { userRepo } from "$lib/server/repo";
|
||||
import { RateLimiter, json } from "$lib/server/util/index.js";
|
||||
import { json } from "$lib/server/util/index.js";
|
||||
import type { LoginResponse, LoginRequest } from "$types/api";
|
||||
import bcrypt from "bcrypt";
|
||||
import { verify } from "hcaptcha";
|
||||
|
||||
export async function POST({ request, getClientAddress }) {
|
||||
const body: LoginRequest = await request.json();
|
||||
|
|
@ -11,12 +14,20 @@ export async function POST({ request, getClientAddress }) {
|
|||
body.email.trim() === "" ||
|
||||
body.password.trim() === "" ||
|
||||
body.email.length > 320 ||
|
||||
body.password.length > 320
|
||||
body.password.length > 320 ||
|
||||
!body.captchaToken
|
||||
)
|
||||
return json<LoginResponse>({
|
||||
success: false,
|
||||
error: "missing fields",
|
||||
});
|
||||
const res = await verify(HCAPTCHA_KEY, body.captchaToken, getClientAddress(), PUBLIC_SITE_KEY);
|
||||
if (!res.success) {
|
||||
return json<LoginResponse>({
|
||||
success: false,
|
||||
error: "invalid captcha",
|
||||
});
|
||||
}
|
||||
const user = await userRepo.findOne({
|
||||
where: {
|
||||
email: body.email,
|
||||
|
|
|
|||
|
|
@ -13,16 +13,20 @@
|
|||
|
||||
let emailInput = "";
|
||||
let passwordInput = "";
|
||||
$: disabled = !emailInput || !passwordInput;
|
||||
let captchaToken = "";
|
||||
$: disabled = !emailInput || !passwordInput || !captchaToken;
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
if (Object.keys(data.user).length !== 0 && browser) goto("/account");
|
||||
|
||||
let shouldLoadCaptcha = false;
|
||||
|
||||
async function logIn() {
|
||||
const res = await SuyuAPI.users.login({
|
||||
email: emailInput,
|
||||
password: passwordInput,
|
||||
captchaToken,
|
||||
});
|
||||
if (!res.success) {
|
||||
// TODO: modal
|
||||
|
|
@ -38,6 +42,15 @@
|
|||
function enter(e: KeyboardEvent) {
|
||||
if (e.key === "Enter") logIn();
|
||||
}
|
||||
async function captchaComplete(event: CustomEvent<any>) {
|
||||
captchaToken = event.detail.token;
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
setTimeout(() => {
|
||||
shouldLoadCaptcha = true;
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
|
|
@ -67,6 +80,11 @@
|
|||
placeholder="Password"
|
||||
on:keydown={enter}
|
||||
/>
|
||||
<div class="h-[78px]">
|
||||
{#if shouldLoadCaptcha}
|
||||
<HCaptcha on:success={captchaComplete} theme="dark" sitekey={PUBLIC_SITE_KEY} />
|
||||
{/if}
|
||||
</div>
|
||||
<button {disabled} on:click={logIn} class="cta-button mt-2">Log in</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import { SuyuAPI } from "$lib/client/api";
|
||||
import type { PageData } from "./$types";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { getContext } from "svelte";
|
||||
import { getContext, onMount } from "svelte";
|
||||
|
||||
const token = getContext<Writable<string>>("token");
|
||||
if ($token) goto("/account");
|
||||
|
|
@ -42,6 +42,14 @@
|
|||
async function captchaComplete(event: CustomEvent<any>) {
|
||||
captchaToken = event.detail.token;
|
||||
}
|
||||
|
||||
let shouldLoadCaptcha = false;
|
||||
|
||||
onMount(() => {
|
||||
setTimeout(() => {
|
||||
shouldLoadCaptcha = true;
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
|
|
@ -86,7 +94,13 @@
|
|||
autocomplete="new-password"
|
||||
/>
|
||||
<div class="h-[78px]">
|
||||
<HCaptcha on:success={captchaComplete} theme="dark" sitekey={PUBLIC_SITE_KEY} />
|
||||
{#if shouldLoadCaptcha}
|
||||
<HCaptcha
|
||||
on:success={captchaComplete}
|
||||
theme="dark"
|
||||
sitekey={PUBLIC_SITE_KEY}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
<button {disabled} type="submit" on:click={signUp} class="cta-button mt-2"
|
||||
>Sign up</button
|
||||
|
|
|
|||
1
src/types/api.d.ts
vendored
1
src/types/api.d.ts
vendored
|
|
@ -37,6 +37,7 @@ export type GetUserResponse = GetUserResponseSuccess | GenericFailureResponse;
|
|||
export interface LoginRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
captchaToken: string;
|
||||
}
|
||||
|
||||
export interface LoginResponseSuccess {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue