Added option to disable captcha

This commit is contained in:
WardPearce
2026-02-17 20:28:42 +13:00
parent b10b5c2a24
commit 3f112ada56
6 changed files with 34 additions and 21 deletions
+6
View File
@@ -12,6 +12,9 @@ invidious_companion:
public_url: "http://companion.example.com/companion"
```
### Proof-of-work Captcha
Will only work while using HTTPS. If in HTTP set `PUBLIC_CAPTCHA_DISABLED` to `true`
### Docker Compose
```yaml
@@ -42,6 +45,9 @@ services:
# Allow anyone to register
PUBLIC_REGISTRATION_ALLOWED: "false"
# Disable POW Captcha
PUBLIC_CAPTCHA_DISABLED: "false"
# Allow any domain in proxy
# This shouldn't be used unless you KNOW what your doing
# requires VITE_REGISTRATION_ALLOWED to be false
+3
View File
@@ -1,8 +1,11 @@
import { error } from '@sveltejs/kit';
import { verifySolution } from 'altcha-lib';
import { getSequelize } from './database';
import { isOwnBackend } from '$lib/shared';
export async function verifyCaptcha(payload: string, key: string, maxUses: number = -1) {
if (isOwnBackend()?.captchaDisabled) return;
const passedCaptcha = await verifySolution(payload, key, true);
if (!passedCaptcha) {
throw error(400, 'Unsupported payload');
+3 -1
View File
@@ -6,6 +6,7 @@ export type IsOwnBackend = {
requireAuth: boolean;
registrationAllowed: boolean;
allowAnyProxy: boolean;
captchaDisabled: boolean;
};
export function isOwnBackend(): IsOwnBackend | null {
@@ -16,6 +17,7 @@ export function isOwnBackend(): IsOwnBackend | null {
internalAuth: env.PUBLIC_INTERNAL_AUTH !== 'false',
requireAuth: env.PUBLIC_REQUIRE_AUTH !== 'false',
registrationAllowed: env.PUBLIC_REGISTRATION_ALLOWED === 'true',
allowAnyProxy: env.PUBLIC_DANGEROUS_ALLOW_ANY_PROXY === 'true'
allowAnyProxy: env.PUBLIC_DANGEROUS_ALLOW_ANY_PROXY === 'true',
captchaDisabled: env.PUBLIC_CAPTCHA_DISABLED === 'true'
};
}
@@ -81,22 +81,24 @@
{/if}
</div>
<article
class="surface-container-highest no-padding"
style="width: 100%;height: fit-content;"
>
<altcha-widget
challengeurl="/api/captcha"
hidelogo
hidefooter
onstatechange={(ev) => {
const { payload, state } = ev.detail;
if (state === 'verified' && payload) {
captchaPayload = payload;
}
}}
></altcha-widget>
</article>
{#if !isOwnBackend()?.captchaDisabled}
<article
class="surface-container-highest no-padding"
style="width: 100%;height: fit-content;"
>
<altcha-widget
challengeurl="/api/captcha"
hidelogo
hidefooter
onstatechange={(ev) => {
const { payload, state } = ev.detail;
if (state === 'verified' && payload) {
captchaPayload = payload;
}
}}
></altcha-widget>
</article>
{/if}
<nav class="right-align">
<button
@@ -16,7 +16,7 @@ const zUserCreate = z.object({
cipher: z.string().max(255),
nonce: z.string().max(255)
}),
captchaPayload: z.string()
captchaPayload: z.string().optional()
});
export async function POST({ request, cookies, locals }) {
@@ -28,7 +28,7 @@ export async function POST({ request, cookies, locals }) {
if (!userToCreate.success) throw error(400);
await verifyCaptcha(userToCreate.data.captchaPayload, locals.captchaKey, 1);
await verifyCaptcha(userToCreate.data.captchaPayload ?? '', locals.captchaKey, 1);
const createdUser = await createUser({
username: userToCreate.data.username,
@@ -8,7 +8,7 @@ import { verifyCaptcha } from '$lib/server/captcha';
const zUserLogin = z.object({
username: z.string(),
passwordHash: z.string(),
captchaPayload: z.string()
captchaPayload: z.string().optional()
});
export async function POST({ request, cookies, locals }) {
@@ -20,7 +20,7 @@ export async function POST({ request, cookies, locals }) {
if (!userLogin.success) throw error(401);
await verifyCaptcha(userLogin.data.captchaPayload, locals.captchaKey, 1);
await verifyCaptcha(userLogin.data.captchaPayload ?? '', locals.captchaKey, 1);
const userModel = await authenticateUser(userLogin.data.username, userLogin.data.passwordHash);