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
}
c.Locals("principal", user)
c.Locals("permissions", user.Permissions.Data())
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.Get("/users/me", auth, aboutMe)
api.Post("/users", doRegister)
api.Put("/auth", startChallenge)

View File

@ -1,11 +1,25 @@
import Navbar from "./shared/Navbar.tsx";
import { readProfiles } from "../stores/userinfo.ts";
import { createSignal, Show } from "solid-js";
export default function RootLayout(props: any) {
return (
<div>
<Navbar />
const [ready, setReady] = createSignal(false);
<main class="h-[calc(100vh-68px)]">{props.children}</main>
</div>
readProfiles().then(() => setReady(true));
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 {
label: string;
@ -57,7 +58,9 @@ export default function Navbar() {
</ul>
</div>
<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>
);

View File

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

View File

@ -1,7 +1,9 @@
import { userinfo } from "../stores/userinfo.ts";
export default function Dashboard() {
return (
<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>
</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",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": ["ES2020", "ES2015", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */