feat: add NFT usernames and bot verification (#22)
Implements collectible usernames, official verification workflows, and third-party bot verification after maintainer protocol and migration review. The composite activity/moderation rating remains an admin-only read model; Telegram Stars Rating wire fields stay unset pending a dedicated official-semantics implementation. Reviewed-Head: 2796345775ea0f908fb7734601e5e1dee4b653b9 Original-Head: fa082b892fd5180c9c9bc53c81c21cf5d250a75b Co-authored-by: Egor Egorov <business.egor.sg@gmail.com>
This commit is contained in:
parent
b0fd3976f1
commit
fff8de783a
169 changed files with 55769 additions and 282 deletions
|
|
@ -1,12 +1,16 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { api, APIError } from "./api";
|
||||
import { api } from "./api";
|
||||
import { BootScreen, Shell } from "./components/Layout";
|
||||
import { LoginPage } from "./pages/LoginPage";
|
||||
import { PermissionsProvider } from "./permissions";
|
||||
import { Routes } from "./pages/Routes";
|
||||
import { currentRoute, type RouteState } from "./routing";
|
||||
import type { AdminSession } from "./types";
|
||||
|
||||
export function App() {
|
||||
const [actor, setActor] = useState<string | null | undefined>(undefined);
|
||||
// One GET /api/session at boot carries both the actor and the permission set the
|
||||
// signed session was issued with.
|
||||
const [session, setSession] = useState<AdminSession | null | undefined>(undefined);
|
||||
const [route, setRoute] = useState<RouteState>(() => currentRoute());
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -17,14 +21,10 @@ export function App() {
|
|||
|
||||
useEffect(() => {
|
||||
api.session()
|
||||
.then((session) => setActor(session.actor))
|
||||
.catch((error) => {
|
||||
if (error instanceof APIError && error.status === 401) {
|
||||
setActor(null);
|
||||
return;
|
||||
}
|
||||
setActor(null);
|
||||
});
|
||||
.then((next) => setSession(next))
|
||||
// A 401 and an unreachable backend both end at the login screen; there is
|
||||
// nothing the panel can render without a session.
|
||||
.catch(() => setSession(null));
|
||||
}, []);
|
||||
|
||||
const navigate = (href: string) => {
|
||||
|
|
@ -32,17 +32,19 @@ export function App() {
|
|||
setRoute(currentRoute());
|
||||
};
|
||||
|
||||
if (actor === undefined) {
|
||||
if (session === undefined) {
|
||||
return <BootScreen />;
|
||||
}
|
||||
|
||||
if (actor === null) {
|
||||
return <LoginPage onLogin={setActor} />;
|
||||
if (session === null) {
|
||||
return <LoginPage onLogin={setSession} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Shell actor={actor} route={route} navigate={navigate} onLogout={() => setActor(null)}>
|
||||
<Routes route={route} navigate={navigate} />
|
||||
</Shell>
|
||||
<PermissionsProvider permissions={session.permissions ?? []}>
|
||||
<Shell actor={session.actor} route={route} navigate={navigate} onLogout={() => setSession(null)}>
|
||||
<Routes route={route} navigate={navigate} />
|
||||
</Shell>
|
||||
</PermissionsProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue