User info

This commit is contained in:
LittleSheep 2024-01-28 00:42:02 +08:00
parent 4f33b9e0f6
commit 9b5500305f
9 changed files with 106 additions and 9 deletions

View File

@ -28,6 +28,7 @@ var auth = keyauth.New(keyauth.Config{
return false, err return false, err
} }
c.Locals("principal", user)
c.Locals("permissions", user.Permissions.Data()) c.Locals("permissions", user.Permissions.Data())
return true, nil return true, nil

View File

@ -0,0 +1,12 @@
package server
import (
"code.smartsheep.studio/hydrogen/passport/pkg/models"
"github.com/gofiber/fiber/v2"
)
func aboutMe(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
return c.JSON(user)
}

View File

@ -21,6 +21,7 @@ func NewServer() {
api := A.Group("/api").Name("API") api := A.Group("/api").Name("API")
{ {
api.Get("/users/me", auth, aboutMe)
api.Post("/users", doRegister) api.Post("/users", doRegister)
api.Put("/auth", startChallenge) api.Put("/auth", startChallenge)

View File

@ -1,11 +1,25 @@
import Navbar from "./shared/Navbar.tsx"; import Navbar from "./shared/Navbar.tsx";
import { readProfiles } from "../stores/userinfo.ts";
import { createSignal, Show } from "solid-js";
export default function RootLayout(props: any) { export default function RootLayout(props: any) {
return ( const [ready, setReady] = createSignal(false);
<div>
<Navbar />
<main class="h-[calc(100vh-68px)]">{props.children}</main> readProfiles().then(() => setReady(true));
</div>
return (
<Show when={ready()} fallback={
<div class="h-screen w-screen flex justify-center items-center">
<div>
<span class="loading loading-lg loading-infinity"></span>
</div>
</div>
}>
<div>
<Navbar />
<main class="h-[calc(100vh-68px)]">{props.children}</main>
</div>
</Show>
); );
} }

View File

@ -1,4 +1,5 @@
import { For } from "solid-js"; import { For, Show } from "solid-js";
import { userinfo } from "../../stores/userinfo.ts";
interface MenuItem { interface MenuItem {
label: string; label: string;
@ -57,7 +58,9 @@ export default function Navbar() {
</ul> </ul>
</div> </div>
<div class="navbar-end pe-5"> <div class="navbar-end pe-5">
<a href="/auth/login" class="btn btn-sm btn-primary">Login</a> <Show when={!userinfo.isLoggedIn}>
<a href="/auth/login" class="btn btn-sm btn-primary">Login</a>
</Show>
</div> </div>
</div> </div>
); );

View File

@ -1,3 +1,4 @@
import { readProfiles } from "../../stores/userinfo.ts";
import { useNavigate } from "@solidjs/router"; import { useNavigate } from "@solidjs/router";
import { createSignal, For, Match, Show, Switch } from "solid-js"; import { createSignal, For, Match, Show, Switch } from "solid-js";
import Cookie from "universal-cookie"; import Cookie from "universal-cookie";
@ -85,6 +86,7 @@ export default function Login() {
const data = await res.json(); const data = await res.json();
if (data["is_finished"]) { if (data["is_finished"]) {
await grantToken(data["session"]["grant_token"]); await grantToken(data["session"]["grant_token"]);
await readProfiles();
navigate("/"); navigate("/");
} else { } else {
setError(null); setError(null);

View File

@ -1,7 +1,9 @@
import { userinfo } from "../stores/userinfo.ts";
export default function Dashboard() { export default function Dashboard() {
return ( return (
<div class="container mx-auto pt-12"> <div class="container mx-auto pt-12">
<h1 class="text-2xl font-bold">Welcome, undefined</h1> <h1 class="text-2xl font-bold">Welcome, {userinfo.displayName}</h1>
<p>What's a nice day!</p> <p>What's a nice day!</p>
</div> </div>
) )

View File

@ -0,0 +1,62 @@
import { createStore } from "solid-js/store";
import Cookie from "universal-cookie";
const [userinfo, setUserinfo] = createStore({
isLoggedIn: false,
displayName: "Citizen",
profiles: null,
meta: null
});
function checkLoggedIn(): boolean {
return new Cookie().get("access_token");
}
export function getAtk(): string {
return new Cookie().get("access_token");
}
export async function refreshAtk() {
const rtk = new Cookie().get("refresh_token");
const res = await fetch("/api/auth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
code: rtk,
grant_type: "refresh_token"
})
});
if (res.status !== 200) {
throw new Error(await res.text());
} else {
const data = await res.json();
new Cookie().set("access_token", data["access_token"], { path: "/" });
new Cookie().set("refresh_token", data["refresh_token"], { path: "/" });
}
}
export async function readProfiles() {
if (!checkLoggedIn()) return;
const res = await fetch("/api/users/me", {
headers: { "Authorization": `Bearer ${getAtk()}` }
});
if (res.status !== 200) {
// Auto retry after refresh access token
await refreshAtk();
return await readProfiles();
}
const data = await res.json();
setUserinfo({
isLoggedIn: true,
displayName: data["nick"],
profiles: null,
meta: data
});
}
export { userinfo };

View File

@ -3,7 +3,7 @@
"target": "ES2020", "target": "ES2020",
"useDefineForClassFields": true, "useDefineForClassFields": true,
"module": "ESNext", "module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"], "lib": ["ES2020", "ES2015", "DOM", "DOM.Iterable"],
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */