Replace captcha package with own implementation
This commit is contained in:
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Api;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Downloads;
|
use App\Models\Downloads;
|
||||||
use App\Models\Episode;
|
use App\Models\Episode;
|
||||||
use GrantHolle\Altcha\Rules\ValidAltcha;
|
use App\Rules\ValidCaptcha;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class DownloadApiController extends Controller
|
class DownloadApiController extends Controller
|
||||||
@@ -17,7 +17,7 @@ class DownloadApiController extends Controller
|
|||||||
{
|
{
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'episode_id' => ['required'],
|
'episode_id' => ['required'],
|
||||||
'captcha' => ['required', new ValidAltcha],
|
'captcha' => ['required', new ValidCaptcha],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$episode = Episode::where('id', $request->input('episode_id'))
|
$episode = Episode::where('id', $request->input('episode_id'))
|
||||||
|
|||||||
30
app/Http/Controllers/Auth/CaptchaController.php
Normal file
30
app/Http/Controllers/Auth/CaptchaController.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use AltchaOrg\Altcha\Algorithm\Pbkdf2;
|
||||||
|
use AltchaOrg\Altcha\Altcha;
|
||||||
|
use AltchaOrg\Altcha\CreateChallengeOptions;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class CaptchaController extends Controller
|
||||||
|
{
|
||||||
|
public function create(): array
|
||||||
|
{
|
||||||
|
$pbkdf2 = new Pbkdf2;
|
||||||
|
|
||||||
|
$altcha = new Altcha(
|
||||||
|
hmacSignatureSecret: config('captcha.hmac_key'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create challenge
|
||||||
|
$challenge = $altcha->createChallenge(new CreateChallengeOptions(
|
||||||
|
algorithm: $pbkdf2,
|
||||||
|
cost: 5000,
|
||||||
|
counter: random_int(5000, 10000),
|
||||||
|
expiresAt: time() + 600,
|
||||||
|
));
|
||||||
|
|
||||||
|
return get_object_vars($challenge);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ namespace App\Http\Controllers\Auth;
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use GrantHolle\Altcha\Rules\ValidAltcha;
|
use App\Rules\ValidCaptcha;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -25,7 +25,7 @@ class RegisteredUserController extends Controller
|
|||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
|
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
|
||||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||||
'altcha' => ['required', new ValidAltcha],
|
'altcha' => ['required', new ValidCaptcha],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user = User::create([
|
$user = User::create([
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Contact;
|
use App\Models\Contact;
|
||||||
use GrantHolle\Altcha\Rules\ValidAltcha;
|
use App\Rules\ValidCaptcha;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ContactController extends Controller
|
class ContactController extends Controller
|
||||||
@@ -26,7 +26,7 @@ class ContactController extends Controller
|
|||||||
'email' => 'required|max:50',
|
'email' => 'required|max:50',
|
||||||
'message' => 'required|max:1000',
|
'message' => 'required|max:1000',
|
||||||
'subject' => 'required|max:50',
|
'subject' => 'required|max:50',
|
||||||
'altcha' => ['required', new ValidAltcha],
|
'altcha' => ['required', new ValidCaptcha],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$contact = new Contact;
|
$contact = new Contact;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests\Auth;
|
namespace App\Http\Requests\Auth;
|
||||||
|
|
||||||
use GrantHolle\Altcha\Rules\ValidAltcha;
|
use App\Rules\ValidCaptcha;
|
||||||
use Illuminate\Auth\Events\Lockout;
|
use Illuminate\Auth\Events\Lockout;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@@ -30,7 +30,7 @@ class LoginRequest extends FormRequest
|
|||||||
return [
|
return [
|
||||||
'email' => ['required', 'string', 'email'],
|
'email' => ['required', 'string', 'email'],
|
||||||
'password' => ['required', 'string'],
|
'password' => ['required', 'string'],
|
||||||
'altcha' => ['required', new ValidAltcha],
|
'altcha' => ['required', new ValidCaptcha],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
129
app/Rules/ValidCaptcha.php
Normal file
129
app/Rules/ValidCaptcha.php
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Rules;
|
||||||
|
|
||||||
|
use AltchaOrg\Altcha\Algorithm\Pbkdf2;
|
||||||
|
use AltchaOrg\Altcha\Altcha;
|
||||||
|
use AltchaOrg\Altcha\Challenge;
|
||||||
|
use AltchaOrg\Altcha\ChallengeParameters;
|
||||||
|
use AltchaOrg\Altcha\Payload;
|
||||||
|
use AltchaOrg\Altcha\Solution;
|
||||||
|
use AltchaOrg\Altcha\VerifySolutionOptions;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation rule to verify captcha solution.
|
||||||
|
*/
|
||||||
|
class ValidCaptcha implements ValidationRule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Altcha instance.
|
||||||
|
*/
|
||||||
|
protected Altcha $altcha;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pbkdf2 algorithm instance.
|
||||||
|
*/
|
||||||
|
protected Pbkdf2 $pbkdf2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->pbkdf2 = new Pbkdf2;
|
||||||
|
$this->altcha = new Altcha(
|
||||||
|
hmacSignatureSecret: config('captcha.hmac_key'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse payload and return the decoded data as an array.
|
||||||
|
*/
|
||||||
|
private function parsePayload(string $value): ?array
|
||||||
|
{
|
||||||
|
$decoded = base64_decode($value, true);
|
||||||
|
if ($decoded === false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = json_decode($decoded, true);
|
||||||
|
if (! is_array($payload)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if payload has required fields.
|
||||||
|
*/
|
||||||
|
private function verifyFields(array $payload): bool
|
||||||
|
{
|
||||||
|
if (! isset($payload['challenge'], $payload['solution'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_array($payload['challenge']) || ! is_array($payload['solution'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Challenge object from challenge data.
|
||||||
|
*/
|
||||||
|
private function createChallenge(array $challengeData): Challenge
|
||||||
|
{
|
||||||
|
return new Challenge(
|
||||||
|
ChallengeParameters::fromArray($challengeData['parameters'] ?? []),
|
||||||
|
$challengeData['signature'] ?? null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Solution object from solution data.
|
||||||
|
*/
|
||||||
|
private function createSolution(array $solutionData): Solution
|
||||||
|
{
|
||||||
|
return new Solution(
|
||||||
|
counter: (int) ($solutionData['counter'] ?? 0),
|
||||||
|
derivedKey: (string) ($solutionData['derivedKey'] ?? ''),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the validation rule.
|
||||||
|
*
|
||||||
|
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
$payload = $this->parsePayload($value);
|
||||||
|
if (! $payload) {
|
||||||
|
$fail('Invalid captcha.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->verifyFields($payload)) {
|
||||||
|
$fail('Invalid captcha.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$challenge = $this->createChallenge($payload['challenge']);
|
||||||
|
$solution = $this->createSolution($payload['solution']);
|
||||||
|
|
||||||
|
$result = $this->altcha->verifySolution(new VerifySolutionOptions(
|
||||||
|
algorithm: $this->pbkdf2,
|
||||||
|
payload: new Payload($challenge, $solution),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (! $result->verified) {
|
||||||
|
$fail('Invalid captcha.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
"grantholle/laravel-altcha": "^2.1",
|
"altcha-org/altcha": "^2.0",
|
||||||
"guzzlehttp/guzzle": "^7.8.1",
|
"guzzlehttp/guzzle": "^7.8.1",
|
||||||
"hisorange/browser-detect": "^5.0",
|
"hisorange/browser-detect": "^5.0",
|
||||||
"http-interop/http-factory-guzzle": "^1.2",
|
"http-interop/http-factory-guzzle": "^1.2",
|
||||||
|
|||||||
96
composer.lock
generated
96
composer.lock
generated
@@ -4,24 +4,23 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "3400111a6254560d548639295422875c",
|
"content-hash": "a33ae97980a40b1a7c55bec75b10d64f",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "altcha-org/altcha",
|
"name": "altcha-org/altcha",
|
||||||
"version": "v1.3.1",
|
"version": "v2.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/altcha-org/altcha-lib-php.git",
|
"url": "https://github.com/altcha-org/altcha-lib-php.git",
|
||||||
"reference": "9e9e70c864a9db960d071c77c778be0c9ff1a4d0"
|
"reference": "8fc4a698b159824d7c1d729dc08e5c0687b494a9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/altcha-org/altcha-lib-php/zipball/9e9e70c864a9db960d071c77c778be0c9ff1a4d0",
|
"url": "https://api.github.com/repos/altcha-org/altcha-lib-php/zipball/8fc4a698b159824d7c1d729dc08e5c0687b494a9",
|
||||||
"reference": "9e9e70c864a9db960d071c77c778be0c9ff1a4d0",
|
"reference": "8fc4a698b159824d7c1d729dc08e5c0687b494a9",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
|
||||||
"php": ">=8.2"
|
"php": ">=8.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
@@ -29,7 +28,7 @@
|
|||||||
"phpstan/extension-installer": "^1.4",
|
"phpstan/extension-installer": "^1.4",
|
||||||
"phpstan/phpstan": "^2.1",
|
"phpstan/phpstan": "^2.1",
|
||||||
"phpstan/phpstan-phpunit": "^2.0",
|
"phpstan/phpstan-phpunit": "^2.0",
|
||||||
"phpunit/phpunit": "^11.5"
|
"phpunit/phpunit": "^11.5.50"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -47,11 +46,12 @@
|
|||||||
"email": "536331+ovx@users.noreply.github.com"
|
"email": "536331+ovx@users.noreply.github.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"description": "A lightweight PHP library for creating and verifying ALTCHA challenges.",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/altcha-org/altcha-lib-php/issues",
|
"issues": "https://github.com/altcha-org/altcha-lib-php/issues",
|
||||||
"source": "https://github.com/altcha-org/altcha-lib-php/tree/v1.3.1"
|
"source": "https://github.com/altcha-org/altcha-lib-php/tree/v2.0.0"
|
||||||
},
|
},
|
||||||
"time": "2025-12-13T10:03:53+00:00"
|
"time": "2026-04-07T11:35:25+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
@@ -823,82 +823,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-12-27T19:43:20+00:00"
|
"time": "2025-12-27T19:43:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "grantholle/laravel-altcha",
|
|
||||||
"version": "2.1.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/grantholle/laravel-altcha.git",
|
|
||||||
"reference": "c0dcc6d0805e8640d46709e5f8d05c7c65b2687c"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/grantholle/laravel-altcha/zipball/c0dcc6d0805e8640d46709e5f8d05c7c65b2687c",
|
|
||||||
"reference": "c0dcc6d0805e8640d46709e5f8d05c7c65b2687c",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"altcha-org/altcha": "^1.3.1",
|
|
||||||
"illuminate/contracts": "^10.0|^11.0|^12.0",
|
|
||||||
"php": "^8.2",
|
|
||||||
"spatie/laravel-package-tools": "^1.14.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"laravel/pint": "^1.0",
|
|
||||||
"nunomaduro/collision": "^8.1.1||^7.10.0",
|
|
||||||
"orchestra/testbench": "^10.0.0||^9.0.0||^8.22.0",
|
|
||||||
"pestphp/pest": "^3.0||^2.0",
|
|
||||||
"pestphp/pest-plugin-arch": "^3.0||^2.0",
|
|
||||||
"pestphp/pest-plugin-laravel": "^3.0||^2.0",
|
|
||||||
"spatie/laravel-ray": "^1.26"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"aliases": {
|
|
||||||
"Altcha": "GrantHolle\\Altcha\\Facades\\Altcha"
|
|
||||||
},
|
|
||||||
"providers": [
|
|
||||||
"GrantHolle\\Altcha\\AltchaServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"GrantHolle\\Altcha\\": "src/",
|
|
||||||
"GrantHolle\\Altcha\\Database\\Factories\\": "database/factories/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Grant Holle",
|
|
||||||
"email": "hollegrant@gmail.com",
|
|
||||||
"role": "Developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A Laravel server implementation for Altcha.",
|
|
||||||
"homepage": "https://github.com/grantholle/laravel-altcha",
|
|
||||||
"keywords": [
|
|
||||||
"Grant Holle",
|
|
||||||
"laravel",
|
|
||||||
"laravel-altcha"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/grantholle/laravel-altcha/issues",
|
|
||||||
"source": "https://github.com/grantholle/laravel-altcha/tree/2.1.1"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/Grant Holle",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-12-16T03:39:06+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/guzzle",
|
"name": "guzzlehttp/guzzle",
|
||||||
"version": "7.10.0",
|
"version": "7.10.0",
|
||||||
@@ -11584,5 +11508,5 @@
|
|||||||
"php": "^8.2"
|
"php": "^8.2"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
9
config/captcha.php
Normal file
9
config/captcha.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Altcha Captcha System
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
'hmac_key' => env('ALTCHA_HMAC_KEY'),
|
||||||
|
];
|
||||||
39
package-lock.json
generated
39
package-lock.json
generated
@@ -4,12 +4,11 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "hstream",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||||
"@jellyfin/libass-wasm": "^4.1.1",
|
"@jellyfin/libass-wasm": "^4.1.1",
|
||||||
"@yaireo/tagify": "^4.21.2",
|
"@yaireo/tagify": "^4.21.2",
|
||||||
"altcha": "^2.3.0",
|
"altcha": "^3.0.0",
|
||||||
"chart.js": "^4.5.0",
|
"chart.js": "^4.5.0",
|
||||||
"dashjs": "^5.0.0",
|
"dashjs": "^5.0.0",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
@@ -42,12 +41,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@altcha/crypto": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@altcha/crypto/-/crypto-0.0.1.tgz",
|
|
||||||
"integrity": "sha512-qZMdnoD3lAyvfSUMNtC2adRi666Pxdcw9zqfMU5qBOaJWqpN9K+eqQGWqeiKDMqL0SF+EytNG4kR/Pr/99GJ6g==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.27.2",
|
"version": "0.27.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
|
||||||
@@ -1209,30 +1202,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/altcha": {
|
"node_modules/altcha": {
|
||||||
"version": "2.3.0",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/altcha/-/altcha-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/altcha/-/altcha-3.0.4.tgz",
|
||||||
"integrity": "sha512-vl8I0dQvSQB7/Mx09XuWZ1+LdSP7vEda6OLbg9kUQ2ZO2LT7MzgUyLK7Iips+GAV6c0ntVcS1XWOqhEPpwbDhQ==",
|
"integrity": "sha512-TA1N0vnKR7aI/usDN2y3dPDcg9DdsDQKvRuCwApMtw3kJHjxH7NRtt+hSV8NZ01tkfHqXEJOtCYRFr8sxw8Fbg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@altcha/crypto": "^0.0.1"
|
"hash-wasm": "^4.12.0"
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.18.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/altcha/node_modules/@rollup/rollup-linux-x64-gnu": {
|
|
||||||
"version": "4.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz",
|
|
||||||
"integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/any-promise": {
|
"node_modules/any-promise": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||||
@@ -2004,6 +1981,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hash-wasm": {
|
||||||
|
"version": "4.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
|
||||||
|
"integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||||
"@jellyfin/libass-wasm": "^4.1.1",
|
"@jellyfin/libass-wasm": "^4.1.1",
|
||||||
"@yaireo/tagify": "^4.21.2",
|
"@yaireo/tagify": "^4.21.2",
|
||||||
"altcha": "^2.3.0",
|
"altcha": "^3.0.0",
|
||||||
"chart.js": "^4.5.0",
|
"chart.js": "^4.5.0",
|
||||||
"dashjs": "^5.0.0",
|
"dashjs": "^5.0.0",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
|
|||||||
@@ -126,29 +126,5 @@ input:checked~.dot {
|
|||||||
|
|
||||||
/* Captcha */
|
/* Captcha */
|
||||||
:root {
|
:root {
|
||||||
--altcha-border-width: 1px;
|
color-scheme: light dark;
|
||||||
--altcha-border-radius: 0.375rem;
|
|
||||||
--altcha-color-base: #333;
|
|
||||||
--altcha-color-border: #a0a0a0;
|
|
||||||
--altcha-color-text: #fff;
|
|
||||||
--altcha-color-border-focus: currentColor;
|
|
||||||
--altcha-color-error-text: #f23939;
|
|
||||||
--altcha-color-footer-bg: #141414;
|
|
||||||
--altcha-max-width: 260px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.altcha-footer {
|
|
||||||
border-bottom-left-radius: 0.375rem;
|
|
||||||
border-bottom-right-radius: 0.375rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"] {
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-color: #a0a0a0;
|
|
||||||
color: rgb(225,29,72);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:checked {
|
|
||||||
background-color: rgb(225,29,72);
|
|
||||||
box-shadow: 0 0 0 0px #fff, 0 0 0 calc(2px + 0px) rgba(246, 59, 118, 0.5), 0 0 #0000;
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
|
|
||||||
// Captcha
|
// Captcha
|
||||||
import 'altcha';
|
import 'altcha';
|
||||||
|
import "altcha/themes/cupcake.css";
|
||||||
|
|
||||||
// import Alpine from 'alpinejs';
|
// import Alpine from 'alpinejs';
|
||||||
|
|
||||||
|
|||||||
@@ -69,8 +69,8 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block">
|
<div class="block pt-3 w-3/4 mx-auto">
|
||||||
<altcha-widget id="captcha" floating challengeurl="/altcha-challenge"></altcha-widget>
|
<altcha-widget id="captcha" theme="cupcake" challenge="/altcha-challenge"></altcha-widget>
|
||||||
<x-input-error :messages="$errors->get('altcha')" class="mt-2" />
|
<x-input-error :messages="$errors->get('altcha')" class="mt-2" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -132,8 +132,8 @@
|
|||||||
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
|
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block">
|
<div class="block pt-3 w-3/4 mx-auto">
|
||||||
<altcha-widget id="captcha" floating challengeurl="/altcha-challenge"></altcha-widget>
|
<altcha-widget id="captcha" theme="cupcake" challenge="/altcha-challenge"></altcha-widget>
|
||||||
<x-input-error :messages="$errors->get('altcha')" class="mt-2" />
|
<x-input-error :messages="$errors->get('altcha')" class="mt-2" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<x-input-error class="mt-2" :messages="$errors->get('message')" />
|
<x-input-error class="mt-2" :messages="$errors->get('message')" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<altcha-widget id="captcha" floating challengeurl="/altcha-challenge"></altcha-widget>
|
<altcha-widget id="captcha" theme="cupcake" challenge="/altcha-challenge"></altcha-widget>
|
||||||
|
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<x-primary-button>{{ __('Submit') }}</x-primary-button>
|
<x-primary-button>{{ __('Submit') }}</x-primary-button>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
</p>
|
</p>
|
||||||
<p id="message" class="text-red-600">
|
<p id="message" class="text-red-600">
|
||||||
</p>
|
</p>
|
||||||
<div class="flex pt-2">
|
<div class="block pt-2">
|
||||||
<altcha-widget id="altcha" challengeurl="/altcha-challenge"></altcha-widget>
|
<altcha-widget id="altcha" theme="cupcake" challenge="/altcha-challenge"></altcha-widget>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<p class="text-gray-800 dark:text-gray-200 text-sm">
|
<p class="text-gray-800 dark:text-gray-200 text-sm">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\Auth\AuthenticatedSessionController;
|
use App\Http\Controllers\Auth\AuthenticatedSessionController;
|
||||||
|
use App\Http\Controllers\Auth\CaptchaController;
|
||||||
use App\Http\Controllers\Auth\ConfirmablePasswordController;
|
use App\Http\Controllers\Auth\ConfirmablePasswordController;
|
||||||
use App\Http\Controllers\Auth\DiscordAuthController;
|
use App\Http\Controllers\Auth\DiscordAuthController;
|
||||||
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
|
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
|
||||||
@@ -38,6 +39,9 @@ Route::middleware('guest')->group(function () {
|
|||||||
->name('discord.login');
|
->name('discord.login');
|
||||||
|
|
||||||
Route::get('/auth/discord/callback', [DiscordAuthController::class, 'callback']);
|
Route::get('/auth/discord/callback', [DiscordAuthController::class, 'callback']);
|
||||||
|
|
||||||
|
// Captcha
|
||||||
|
Route::get('/altcha-challenge', [CaptchaController::class, 'create']);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::middleware('auth')->group(function () {
|
Route::middleware('auth')->group(function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user