Redirect users to landing on (app) routes, game page
This commit is contained in:
parent
d4180e5e4f
commit
05d0364f36
|
|
@ -8,11 +8,16 @@ export async function handle({ event, resolve }) {
|
|||
}
|
||||
|
||||
const cookie = event.cookies.get(COOKIE_NAME);
|
||||
if (!cookie) return await resolve(event);
|
||||
if (!cookie) {
|
||||
if (event.routeId.startsWith("(app)")) return new Response("", { status: 302, headers: { Location: "/landing" } });
|
||||
return await resolve(event);
|
||||
}
|
||||
|
||||
let user = await getUserFromSession(cookie, event.getClientAddress());
|
||||
if (!user) event.cookies.delete(COOKIE_NAME, { secure: !!process.env.PRODUCTION });
|
||||
else
|
||||
let user = await getUserFromSession(cookie, event.request.headers.get("x-forwarded-for") || event.getClientAddress());
|
||||
if (!user) {
|
||||
event.cookies.delete(COOKIE_NAME, { secure: !!process.env.PRODUCTION });
|
||||
if (event.routeId.startsWith("(app)")) return new Response("", { status: 302, headers: { Location: "/landing" } });
|
||||
} else
|
||||
event.locals.user = {
|
||||
_id: user._id,
|
||||
username: user.username,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
<!-- https://github.com/BillBuilt/sveltekit-hcaptcha -->
|
||||
<script>
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import { browser } from "$app/environment";
|
||||
import { HCAPTCHA_SITEKEY } from "$lib/constants";
|
||||
|
||||
let hcaptcha;
|
||||
let hcaptchaWidgetID;
|
||||
|
||||
export let token = null;
|
||||
// forces 1-way binding
|
||||
let captchaToken;
|
||||
$: token = captchaToken;
|
||||
|
||||
export let isValid = false;
|
||||
// forces 1-way binding
|
||||
let captchaValid;
|
||||
$: isValid = captchaValid;
|
||||
|
||||
onMount(() => {
|
||||
setTimeout(function () {
|
||||
if (browser) {
|
||||
hcaptcha = window.hcaptcha;
|
||||
if (hcaptcha.render) {
|
||||
hcaptchaWidgetID = hcaptcha.render("hcaptcha", {
|
||||
sitekey: HCAPTCHA_SITEKEY,
|
||||
size: "normal",
|
||||
callback: onValidCaptcha,
|
||||
"error-callback": onErrorCaptcha,
|
||||
theme: "light"
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (browser) {
|
||||
hcaptcha = null;
|
||||
}
|
||||
});
|
||||
|
||||
function onValidCaptcha(e) {
|
||||
//console.log('verified event', e)
|
||||
captchaToken = e;
|
||||
captchaValid = true;
|
||||
}
|
||||
|
||||
function onErrorCaptcha(e) {
|
||||
//console.log('error event', {error: e.error})
|
||||
captchaToken = null;
|
||||
captchaValid = false;
|
||||
hcaptcha.reset(hcaptchaWidgetID);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<script src="https://js.hcaptcha.com/1/api.js?render=explicit" async defer></script>
|
||||
</svelte:head>
|
||||
|
||||
<div id="hcaptcha" class="h-captcha" />
|
||||
|
|
@ -2,6 +2,7 @@ export const COOKIE_NAME = ".ROWBLOX_SESSION_DO_NOT_SHARE";
|
|||
export const USERNAME_REGEX = /[^A-Za-z0-9\-_ ]/g;
|
||||
export const MIN_USERNAME_LENGTH = 3;
|
||||
export const MAX_USERNAME_LENGTH = 16;
|
||||
export const MIN_PASSWORD_LENGTH = 0;
|
||||
export const MIN_PASSWORD_LENGTH = 3;
|
||||
export const INVITE_KEY_PREFIX = "rowblox-";
|
||||
export const SESSION_EXPIRE = 604800000;
|
||||
export const HCAPTCHA_SITEKEY = "be5c40c1-13db-423c-878e-f3428e9fc841";
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const assets = await db.collection("assets");
|
|||
const invites = await db.collection("invites");
|
||||
const avatars = await db.collection("avatars");
|
||||
const sessions = await db.collection("sessions");
|
||||
const friends = await db.collection("friends");
|
||||
|
||||
async function inc(collection) {
|
||||
await collection.updateOne({ _id: "_inc" }, { $inc: { _inc: 1 } });
|
||||
|
|
@ -50,7 +51,13 @@ export async function createUser(username, password, lastip) {
|
|||
username,
|
||||
password: await hashPassword(password),
|
||||
lastip,
|
||||
currency: 100
|
||||
currency: 100,
|
||||
joinDate: Date.now(),
|
||||
lastOnline: Date.now(),
|
||||
rank: 1,
|
||||
activity: 1,
|
||||
pendingFriendRequests: [],
|
||||
bio: ""
|
||||
};
|
||||
|
||||
const avatar = {
|
||||
|
|
@ -63,7 +70,8 @@ export async function createUser(username, password, lastip) {
|
|||
LeftLegColor: 1,
|
||||
RightLegColor: 1
|
||||
},
|
||||
Assets: {}
|
||||
Wearing: [],
|
||||
Inventory: []
|
||||
};
|
||||
|
||||
await Promise.all([avatars.insertOne(avatar), await users.insertOne(user)]);
|
||||
|
|
@ -104,12 +112,12 @@ export async function deleteSession(session, lastip) {
|
|||
const sessionDocument = await sessions.findOne({ _id: session });
|
||||
if (!sessionDocument) return false;
|
||||
|
||||
const user = await users.findOne({ _id: sessionDocument._id });
|
||||
const user = await users.findOne({ _id: sessionDocument.owner });
|
||||
if (!user) return false;
|
||||
|
||||
await users.updateOne({ _id: user._id }, { $set: { lastip } });
|
||||
|
||||
return await sessions.deleteOne({ session });
|
||||
return await sessions.deleteOne({ _id: session });
|
||||
}
|
||||
|
||||
export async function getUser(query, projection) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
<script>
|
||||
import Alert from "$lib/components/Alert.svelte";
|
||||
import Banner from "$lib/components/AdBanner.svelte";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
/** @type {import('./$types').LayoutData} */
|
||||
export let data;
|
||||
|
||||
async function logout() {
|
||||
const response = await fetch("/logout", { method: "GET" });
|
||||
await goto("/landing");
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="navbar scrolling-background text-lg py-1 text-white">
|
||||
|
|
@ -31,7 +37,7 @@
|
|||
<a class="block px-4 py-0.5 text-gray-700" href="/my/profile">Profile</a>
|
||||
<a class="block px-4 py-0.5 text-gray-700" href="/my/settings">Settings</a>
|
||||
</div>
|
||||
<a class="block px-4 py-0.5 text-red-700" href="/logout">Logout</a>
|
||||
<span class="block px-4 py-0.5 text-red-700 hover:cursor-pointer" on:click={logout}>Logout</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,38 +1,105 @@
|
|||
<script>
|
||||
import UserListed from "$lib/components/UserListed.svelte";
|
||||
export let game;
|
||||
let state = 0;
|
||||
|
||||
function updateState(newState) {
|
||||
state = newState;
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Games - Rowblox</title>
|
||||
<title>{game?.name} - Rowblox</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="mx-auto rounded-lg shadow border border-gray-300 p-4 divide-y">
|
||||
<div class="flex">
|
||||
<img class="float-left h-[22.5rem]" alt="" src="/img/background.png" />
|
||||
<div class="w-full flex flex-col pl-4">
|
||||
<div class="max-w-[22.9rem]">
|
||||
<p class="text-3xl font-bold truncate">{game?.name}</p>
|
||||
<p class="text-zinc-500">By <a class="font-bold text-blue-500" href="/users/{game?.creator?._id}">{game?.creator?.username}</a></p>
|
||||
</div>
|
||||
<span class="flex-grow" />
|
||||
<div class="flex">
|
||||
<a class="flex-auto text-lg text-blue-500 px-4 py-0.5 rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500 mr-0.5 mb-1 text-center" href="/games/{game?.id}/edit">
|
||||
Edit
|
||||
</a>
|
||||
<button class="flex-auto text-lg text-blue-500 px-4 py-0.5 rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500 ml-0.5 mb-1">Host</button>
|
||||
</div>
|
||||
<button class="text-2xl text-blue-500 px-4 py-2 rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500">Play</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accent py-0.5 flex-none shadow-md"></div>
|
||||
<div class="rounded-lg shadow border border-gray-300 p-2 mt-4">
|
||||
<div class="flex flex-row text-xl text-center text-black">
|
||||
<button
|
||||
class="flex-auto {state == 0 && 'font-bold text-black text-opacity-30'}"
|
||||
on:click={() => {
|
||||
updateState(0);
|
||||
}}>About</button
|
||||
>
|
||||
<button
|
||||
class="flex-auto {state == 1 && 'font-bold text-black text-opacity-30'}"
|
||||
on:click={() => {
|
||||
updateState(1);
|
||||
}}>Store</button
|
||||
>
|
||||
<button
|
||||
class="flex-auto {state == 2 && 'font-bold text-black text-opacity-30'}"
|
||||
on:click={() => {
|
||||
updateState(2);
|
||||
}}>Players</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-4 flex-grow">
|
||||
|
||||
<div class="container"><div class="carbon-gradient rounded shadow-lg p-4"><div class="flex mb-4"><img class="w-[38rem] float-left" alt="">
|
||||
<div class="pl-4 w-full flex flex-col place-content-between"><div class="max-w-[22.9rem]"><p class="text-3xl font-bold text-ellipsis overflow-clip">Test Game</p>
|
||||
<p class="text-zinc-500">By <a class="font-bold text-blue-500 hover:text-zinc-300" href="/users/1">Rowblox</a></p></div>
|
||||
<div class="flex flex-col"><div class="w-full flex flex-col mb-4 mx-auto"><div class="flex flex-row place-content-between mb-0.5 px-1"><div class="flex flex-row text-green-200"><i class="fa fa-thumbs-up text-4xl hover:text-green-300" aria-hidden="true"></i>
|
||||
<p class="my-auto text-lg px-2 select-none font-bold">0</p></div>
|
||||
<div class="flex flex-row text-red-200"><p class="my-auto text-lg px-2 select-none font-bold">0</p>
|
||||
<i class="fa fa-thumbs-down text-4xl hover:text-red-300" aria-hidden="true"></i></div></div>
|
||||
<div class="relative"><div class="py-0.5 bg-red-400 rounded-lg absolute left-0 w-full "></div>
|
||||
<div class="py-0.5 bg-green-400 rounded-lg absolute left-0" style="width: 50%;"></div></div></div>
|
||||
<a class=" text-blue-500 accent shadow-lg rounded hover:text-zinc-300 mb-2 p-1 text-center flex-grow ml-1 border-[3px] border-blue-500" href="/games/1/edit">Edit Game</a></div>
|
||||
<button class="text-xl bg-white hover:text-zinc-300 py-3 w-full rounded shadow-lg accent text-blue-500 border-blue-500 border-[3px]">Play</button></div></div></div>
|
||||
<div class="divider-0"></div>
|
||||
<p class="py-2">Test Game</p>
|
||||
<div class="divider-0"></div>
|
||||
<div class="flex flex-row"><div class="m-4 text-center flex-grow"><p class="text-zinc-500 inline-block">Players</p>
|
||||
<p class="">0</p></div>
|
||||
<div class="m-4 text-center flex-grow"><p class="text-zinc-500 inline-block">Visits</p>
|
||||
<p class="">0</p></div>
|
||||
<div class="m-4 text-center flex-grow"><p class="text-zinc-500 inline-block">Created</p>
|
||||
<p class="">10/10/22</p></div>
|
||||
<div class="m-4 text-center flex-grow"><p class="text-zinc-500 inline-block">Updated</p>
|
||||
<p class="">10/10/22</p></div>
|
||||
<div class="m-4 text-center flex-grow"><p class="text-zinc-500 inline-block">Max Players</p>
|
||||
<p class="">All</p></div></div>
|
||||
<div class="divider-0"></div></div>
|
||||
<div class="carbon-gradient rounded shadow-lg p-2 mt-4"><div class="flex flex-row text-xl text-center"><a href="#players" class="flex-auto text-zinc-600">Players</a>
|
||||
<a href="#gamepasses" class="flex-auto hover:cursor-pointer hover:text-zinc-300">Gamepasses</a></div></div>
|
||||
<div class="carbon-gradient rounded shadow-lg p-[0.7rem] mt-2"><p class="p-1.5 text-base">No players connected</p></div></div>
|
||||
{#if state == 0}
|
||||
<div class="rounded-lg shadow border border-gray-300 p-2 mt-4 divide-y">
|
||||
<div class="pb-2">
|
||||
<p class="px-2 py-1 font-bold text-xl">Description</p>
|
||||
<p class="px-2 text-black text-opacity-80">Test Game</p>
|
||||
</div>
|
||||
<div class="flex flex-row pb-2">
|
||||
<div class="mx-4 mt-4 text-center flex-grow">
|
||||
<p class="text-zinc-500 inline-block">Players</p>
|
||||
<p class="">0</p>
|
||||
</div>
|
||||
<div class="mx-4 mt-4 text-center flex-grow">
|
||||
<p class="text-zinc-500 inline-block">Visits</p>
|
||||
<p class="">0</p>
|
||||
</div>
|
||||
<div class="mx-4 mt-4 text-center flex-grow">
|
||||
<p class="text-zinc-500 inline-block">Created</p>
|
||||
<p class="">10/10/22</p>
|
||||
</div>
|
||||
<div class="mx-4 mt-4 text-center flex-grow">
|
||||
<p class="text-zinc-500 inline-block">Updated</p>
|
||||
<p class="">10/10/22</p>
|
||||
</div>
|
||||
<div class="mx-4 mt-4 text-center flex-grow">
|
||||
<p class="text-zinc-500 inline-block">Max Players</p>
|
||||
<p class="">No Limit</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else if state == 1}
|
||||
<div class="rounded-lg shadow border border-gray-300 p-2 mt-4">
|
||||
<p class="px-2 py-1 font-bold text-xl">Gamepasses</p>
|
||||
<p class="px-2 text-black text-opacity-80">This store does not have any gamepasses for sale.</p>
|
||||
</div>
|
||||
{:else if state == 2}
|
||||
<div class="rounded-lg shadow border border-gray-300 p-2 mt-4">
|
||||
<p class="px-2 py-1 font-bold text-xl">Players</p>
|
||||
<p class="px-2 text-black text-opacity-80">This game does not have any players.</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg shadow border border-gray-300 p-2 mt-4">
|
||||
<p class="px-2 py-1 font-bold text-xl mb-1">Players</p>
|
||||
<UserListed />
|
||||
<UserListed />
|
||||
<UserListed />
|
||||
<UserListed />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -14,18 +14,3 @@
|
|||
<button class="px-3 py-1 rounded border-2 border-blue-500 text-blue-500 shadow-lg hover:bg-blue-200">Add Friend</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="shadow-lg w-96 h-96 p-2 rounded-lg border-2 border-gray-300 mt-2 mx-1 inline-block">
|
||||
<div class="font-bold text-bold mt-72 mx-1">
|
||||
<p class="font-bold text-[18px] mx-20">This is my description!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex place-content-between m">
|
||||
<div class="w-full rounded-lg flex shadow border border-gray-300 p-2 mt-2 mr-1">
|
||||
<p class="font-bold text-2xl">Friends</p>
|
||||
</div>
|
||||
<div class="w-full rounded-lg flex shadow border border-gray-300 p-2 mt-2 ml-1">
|
||||
<p class="font-bold text-2xl">Games</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export const actions = {
|
|||
const correctPassword = await compareHash(password, user.password);
|
||||
if (!correctPassword) return invalid(400, { error: "password" });
|
||||
|
||||
cookies.set(COOKIE_NAME, await createSession(user._id, getClientAddress()), { secure: !!process.env.PRODUCTION });
|
||||
cookies.set(COOKIE_NAME, await createSession(user._id, request.headers.get("x-forwarded-for") || getClientAddress()), { secure: !!process.env.PRODUCTION });
|
||||
throw redirect(302, "/");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<img class="mx-auto mb-2" src="/favicon.png" alt="" />
|
||||
<div class="flex flex-col">
|
||||
<input
|
||||
class="rounded-lg w-72 px-4 border-2 {form?.error == 'username' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
class="rounded-lg w-[19rem] px-4 border-2 {form?.error == 'username' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
type="username"
|
||||
name="username"
|
||||
id="username"
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
value={form?.username ?? ""}
|
||||
/>
|
||||
<input
|
||||
class="rounded-lg w-72 px-4 border-2 {form?.error == 'password' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
class="rounded-lg w-[19rem] px-4 border-2 {form?.error == 'password' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
type="password"
|
||||
name="password"
|
||||
id="password"
|
||||
|
|
@ -28,8 +28,8 @@
|
|||
/>
|
||||
</div>
|
||||
{#if form?.message}
|
||||
<p class="rounded w-72 px-4 border-[3px] border-red-500 text-red-500 mx-auto my-1.5 py-1.5 hover:bg-opacity-50 hover:bg-red-500">{form?.message}</p>
|
||||
<p class="rounded w-[19rem] px-4 border-[3px] border-red-500 text-red-500 mx-auto my-1.5 py-1.5 hover:bg-opacity-50 hover:bg-red-500">{form?.message}</p>
|
||||
{/if}
|
||||
<div class="h-captcha" data-sitekey="30000000-ffff-ffff-ffff-000000000003" />
|
||||
<button class="my-1.5 text-xl text-white px-4 py-1.5 w-full rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500">Login</button>
|
||||
<button class="my-1.5 text-xl text-white px-4 py-1.5 w-[19rem] rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500">Login</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { deleteSession } from "$lib/database";
|
|||
import { COOKIE_NAME } from "$lib/constants";
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET({ cookies, getClientAddress }) {
|
||||
export async function GET({ request, cookies, getClientAddress }) {
|
||||
const session = cookies.get(COOKIE_NAME);
|
||||
if (!session)
|
||||
return new Response("", {
|
||||
|
|
@ -11,7 +11,7 @@ export async function GET({ cookies, getClientAddress }) {
|
|||
});
|
||||
|
||||
cookies.delete(COOKIE_NAME, { secure: !!process.env.PRODUCTION });
|
||||
await deleteSession(session, getClientAddress());
|
||||
await deleteSession(session, request.headers.get("x-forwarded-for") || getClientAddress());
|
||||
|
||||
return new Response("", {
|
||||
status: 302,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { invalid, redirect } from "@sveltejs/kit";
|
||||
import { createUser, createSession } from "$lib/database";
|
||||
import { MIN_USERNAME_LENGTH, MAX_USERNAME_LENGTH, USERNAME_REGEX, MIN_PASSWORD_LENGTH, INVITE_KEY_PREFIX, COOKIE_NAME } from "$lib/constants";
|
||||
import { createUser, createSession, getUser } from "$lib/database";
|
||||
import { MIN_USERNAME_LENGTH, MAX_USERNAME_LENGTH, USERNAME_REGEX, MIN_PASSWORD_LENGTH, INVITE_KEY_PREFIX, COOKIE_NAME, HCAPTCHA_SITEKEY } from "$lib/constants";
|
||||
|
||||
/** @type {import('./$types').Actions} */
|
||||
export const actions = {
|
||||
|
|
@ -13,6 +13,7 @@ export const actions = {
|
|||
const password = data.get("password");
|
||||
const confirm_password = data.get("confirm_password");
|
||||
const invite_key = data.get("invite_key");
|
||||
const hcaptcha_response = data.get("h-captcha-response");
|
||||
|
||||
if (username.length < MIN_USERNAME_LENGTH || username.length > MAX_USERNAME_LENGTH || new RegExp(USERNAME_REGEX).test(username))
|
||||
return invalid(400, {
|
||||
|
|
@ -35,8 +36,37 @@ export const actions = {
|
|||
error: "invite_key"
|
||||
});
|
||||
|
||||
const user = await createUser(username, password, getClientAddress());
|
||||
cookies.set(COOKIE_NAME, await createSession(user, getClientAddress()), { secure: !!process.env.PRODUCTION });
|
||||
if (!hcaptcha_response)
|
||||
return invalid(400, {
|
||||
username,
|
||||
invite_key,
|
||||
error: "hcaptcha"
|
||||
});
|
||||
|
||||
const existingUser = await getUser({ username }, { _id: true });
|
||||
if (existingUser)
|
||||
return invalid(400, {
|
||||
username,
|
||||
invite_key,
|
||||
error: "username"
|
||||
});
|
||||
|
||||
const hcaptcha = await fetch("https://hcaptcha.com/siteverify", {
|
||||
method: "POST",
|
||||
body: `response=${hcaptcha_response}&secret=${process.env.HCAPTCHA_SECRET}`,
|
||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
||||
});
|
||||
|
||||
const hcaptchaBody = await hcaptcha.json();
|
||||
if (!hcaptchaBody.success)
|
||||
return invalid(400, {
|
||||
username,
|
||||
invite_key,
|
||||
error: "hcaptcha"
|
||||
});
|
||||
|
||||
const user = await createUser(username, password, request.headers.get("x-forwarded-for") || getClientAddress());
|
||||
cookies.set(COOKIE_NAME, await createSession(user, request.headers.get("x-forwarded-for") || getClientAddress()), { secure: !!process.env.PRODUCTION });
|
||||
throw redirect(302, "/");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<script>
|
||||
import HCaptcha from "../../../lib/components/hCaptcha.svelte";
|
||||
/** @type {import('./$types').ActionData} */ export let form;
|
||||
|
||||
let captchaValid = false;
|
||||
let captchaToken;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Register - Rowblox</title>
|
||||
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
|
||||
</svelte:head>
|
||||
|
||||
<form method="POST" class="max-w-lg mx-auto text-center text-white">
|
||||
<img class="mx-auto mb-2" src="/favicon.png" alt="" />
|
||||
<div class="flex flex-col">
|
||||
<input
|
||||
class="rounded-lg w-72 px-4 border-2 {form?.error == 'username' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
class="rounded-lg w-[19rem] px-4 border-2 {form?.error == 'username' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
required
|
||||
type="username"
|
||||
name="username"
|
||||
|
|
@ -20,7 +23,7 @@
|
|||
value={form?.username ?? ""}
|
||||
/>
|
||||
<input
|
||||
class="rounded-lg w-72 px-4 border-2 {form?.error == 'password' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
class="rounded-lg w-[19rem] px-4 border-2 {form?.error == 'password' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
required
|
||||
type="password"
|
||||
name="password"
|
||||
|
|
@ -28,7 +31,7 @@
|
|||
placeholder="Password"
|
||||
/>
|
||||
<input
|
||||
class="rounded-lg w-72 px-4 border-2 {form?.error == 'password' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
class="rounded-lg w-[19rem] px-4 border-2 {form?.error == 'password' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
required
|
||||
type="password"
|
||||
name="confirm_password"
|
||||
|
|
@ -36,7 +39,7 @@
|
|||
placeholder="Confirm Password"
|
||||
/>
|
||||
<input
|
||||
class="rounded-lg w-72 px-4 border-2 {form?.error == 'invite_key' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto my-0.5 py-2"
|
||||
class="rounded-lg w-[19rem] px-4 border-2 {form?.error == 'invite_key' ? 'border-red-500' : 'border-blue-500'} text-black mx-auto mt-0.5 mb-1.5 py-2"
|
||||
required
|
||||
type="text"
|
||||
name="invite_key"
|
||||
|
|
@ -46,8 +49,10 @@
|
|||
/>
|
||||
</div>
|
||||
{#if form?.message}
|
||||
<p class="rounded w-72 px-4 border-2 border-red-500 text-red-500 bg-red-500 mx-auto my-1.5 py-1.5 bg-opacity-50">{form?.message}</p>
|
||||
<p class="rounded w-[19rem] px-4 border-2 border-red-500 text-red-500 bg-red-500 mx-auto my-1.5 py-1.5 bg-opacity-50">{form?.message}</p>
|
||||
{/if}
|
||||
<div class="h-captcha" data-sitekey="30000000-ffff-ffff-ffff-000000000003" />
|
||||
<button class="my-1.5 text-xl text-white px-4 py-1.5 w-full rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500">Register</button>
|
||||
<div class={form?.error == "hcaptcha" && "border-2 border-red-500"}>
|
||||
<HCaptcha bind:token={captchaToken} bind:isValid={captchaValid} />
|
||||
</div>
|
||||
<button class="my-1.5 text-xl text-white px-4 py-1.5 w-[19rem] rounded shadow-lg border-2 border-blue-500 hover:bg-opacity-50 hover:bg-blue-500">Register</button>
|
||||
</form>
|
||||
|
|
|
|||
Loading…
Reference in New Issue