feat: add invite code system for closed alpha registration
This commit is contained in:
@@ -244,10 +244,10 @@ und `twitter:title/description` dynamisch bei jedem Sprachwechsel (i18n-Keys `me
|
||||
## Checkliste vor Alpha-Start
|
||||
|
||||
- [ ] Directus: Collection `invite_codes` anlegen (Schema siehe oben)
|
||||
- [ ] PHP: `invite/validate.php` deployen auf `pow.kashilo.com`
|
||||
- [x] PHP: `invite/validate.php` deployen auf `pow.kashilo.com`
|
||||
- [ ] PHP: `config.php` → `LISTING_FEE` auf 0.01 setzen
|
||||
- [ ] PHP: `config.php` → `REQUIRE_INVITE_CODE = true`
|
||||
- [ ] Frontend: Invite-Code-Feld in `auth-modal.js` einbauen
|
||||
- [x] PHP: `config.php` → `REQUIRE_INVITE_CODE = true`
|
||||
- [x] Frontend: Invite-Code-Feld in `auth-modal.js` einbauen
|
||||
- [x] Frontend: Meta-Description i18n-Keys in alle 7 Sprachen
|
||||
- [x] Frontend: Impressum-Seite (Entwurf, alle 7 Sprachen, Platzhalter für Adressdaten)
|
||||
- [x] Frontend: Datenschutz, AGB, Über uns — alle 7 Sprachen
|
||||
|
||||
@@ -11,3 +11,5 @@ define('LISTING_FEE', ['EUR' => 1, 'USD' => 1, 'CHF' => 1, 'GBP' => 1, 'JPY' =>
|
||||
|
||||
define('DIRECTUS_URL', getenv('DIRECTUS_URL') ?: 'https://api.kashilo.com');
|
||||
define('DIRECTUS_TOKEN', getenv('DIRECTUS_TOKEN') ?: 'CHANGE_ME');
|
||||
|
||||
define('REQUIRE_INVITE_CODE', (bool)(getenv('REQUIRE_INVITE_CODE') ?: true));
|
||||
|
||||
@@ -36,6 +36,9 @@ switch ($uri) {
|
||||
case '/btcpay/webhook':
|
||||
require __DIR__ . '/btcpay-webhook.php';
|
||||
break;
|
||||
case '/invite/validate':
|
||||
require __DIR__ . '/invite-validate.php';
|
||||
break;
|
||||
default:
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Not found']);
|
||||
|
||||
64
docs/pow-server/invite-validate.php
Normal file
64
docs/pow-server/invite-validate.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
require __DIR__ . '/config.php';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!REQUIRE_INVITE_CODE) {
|
||||
echo json_encode(['valid' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$code = trim($input['code'] ?? '');
|
||||
|
||||
if (!$code) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['valid' => false, 'error' => 'Missing invite code']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$url = DIRECTUS_URL . '/items/invite_codes?filter[code][_eq]=' . urlencode($code)
|
||||
. '&filter[status][_eq]=active&limit=1';
|
||||
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'header' => "Authorization: Bearer " . DIRECTUS_TOKEN . "\r\n",
|
||||
'ignore_errors' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
$response = file_get_contents($url, false, $context);
|
||||
$data = json_decode($response, true);
|
||||
$invite = $data['data'][0] ?? null;
|
||||
|
||||
if (!$invite) {
|
||||
echo json_encode(['valid' => false, 'error' => 'invalid_code']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($invite['max_uses'] > 0 && $invite['used_count'] >= $invite['max_uses']) {
|
||||
echo json_encode(['valid' => false, 'error' => 'code_redeemed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($invite['expires_at'] && strtotime($invite['expires_at']) < time()) {
|
||||
echo json_encode(['valid' => false, 'error' => 'code_expired']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$updateUrl = DIRECTUS_URL . '/items/invite_codes/' . $invite['id'];
|
||||
$updateContext = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'PATCH',
|
||||
'header' => "Content-Type: application/json\r\nAuthorization: Bearer " . DIRECTUS_TOKEN . "\r\n",
|
||||
'content' => json_encode(['used_count' => $invite['used_count'] + 1]),
|
||||
'ignore_errors' => true,
|
||||
],
|
||||
]);
|
||||
file_get_contents($updateUrl, false, $updateContext);
|
||||
|
||||
echo json_encode(['valid' => true]);
|
||||
Reference in New Issue
Block a user