mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-27 07:58:45 -07:00
Import december-2020-12-18 from private repo (scrubbed 2026-05-27)
Targets Rec Room 2020.12.18 client.
Re-import after adding:
- DorkNet.ClientMod/dorknet-clientmod.json.template — config schema
the launcher's manifest-driven patcher renders into UserData/.
- tools/build-patcher-zip.ps1 — produces the dorknet-clientpatch-{key}.zip
Release asset the launcher fetches.
- .github/workflows/release.yml — auto-publishes both Release assets
on v1-december-* tag push.
Scrubbed via maintainer-side scrub-for-public.ps1: same drop rules as
the prior import, plus build-patcher-zip.ps1 added to the tools/
allow-list so it survives the scrub.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { api, ApiError } from '../lib/api';
|
||||
import { notifyAuthChange, setSession } from '../lib/auth';
|
||||
|
||||
interface LoginResponse {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
account_id: number;
|
||||
username: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
export function Login() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const from = (location.state as { from?: { pathname: string } } | null)?.from?.pathname ?? '/';
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const onSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setErr(null);
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await api<LoginResponse>('/login', {
|
||||
method: 'POST',
|
||||
body: { username, password },
|
||||
});
|
||||
setSession(res.access_token, {
|
||||
id: res.account_id,
|
||||
username: res.username,
|
||||
displayName: res.display_name,
|
||||
});
|
||||
notifyAuthChange();
|
||||
navigate(from, { replace: true });
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError) {
|
||||
if (e.body && typeof e.body === 'object' && 'error' in e.body) {
|
||||
const code = (e.body as { error: string }).error;
|
||||
if (code === 'not_admin') setErr('That account is not an admin.');
|
||||
else if (code === 'invalid_credentials') setErr('Invalid username or password.');
|
||||
else setErr(e.message);
|
||||
} else setErr(e.message);
|
||||
} else setErr(String(e));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-full flex items-center justify-center px-4 py-12 bg-gradient-to-br from-ink-950 via-ink-950 to-ink-900">
|
||||
<div className="w-full max-w-sm">
|
||||
<div className="mb-8 flex flex-col items-center gap-2">
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-brand-400 to-brand-600 flex items-center justify-center text-xl font-bold text-white shadow-lg shadow-brand-900/40">D</div>
|
||||
<div className="text-center">
|
||||
<h1 className="text-xl font-semibold tracking-tight text-ink-50">DorkNet Admin</h1>
|
||||
<p className="text-xs text-ink-400">Sign in with an admin account.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={onSubmit} className="card p-6 flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="label" htmlFor="username">Username</label>
|
||||
<input
|
||||
id="username"
|
||||
autoComplete="username"
|
||||
required
|
||||
className="input"
|
||||
value={username}
|
||||
onChange={e => setUsername(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="label" htmlFor="password">Password</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
required
|
||||
className="input"
|
||||
value={password}
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
{err && (
|
||||
<div className="rounded-lg border border-danger/30 bg-danger/10 px-3 py-2 text-xs text-danger">{err}</div>
|
||||
)}
|
||||
<button type="submit" disabled={loading} className="btn-primary mt-1">
|
||||
{loading ? 'Signing in…' : 'Sign in'}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p className="mt-6 text-center text-[11px] text-ink-500">DorkNet private server · admin console</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user