diff --git a/pkg/server/auth.go b/pkg/server/auth.go
index f938f5d..84d97b7 100644
--- a/pkg/server/auth.go
+++ b/pkg/server/auth.go
@@ -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
diff --git a/pkg/server/profiles_api.go b/pkg/server/profiles_api.go
new file mode 100644
index 0000000..8d82612
--- /dev/null
+++ b/pkg/server/profiles_api.go
@@ -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)
+}
diff --git a/pkg/server/startup.go b/pkg/server/startup.go
index b77063d..559dd91 100644
--- a/pkg/server/startup.go
+++ b/pkg/server/startup.go
@@ -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)
diff --git a/view/src/layouts/RootLayout.tsx b/view/src/layouts/RootLayout.tsx
index b28b6f8..d78be5c 100644
--- a/view/src/layouts/RootLayout.tsx
+++ b/view/src/layouts/RootLayout.tsx
@@ -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 (
-
-
+ const [ready, setReady] = createSignal(false);
- {props.children}
-
+ readProfiles().then(() => setReady(true));
+
+ return (
+
+
+
+
+
+ }>
+
+
+
+ {props.children}
+
+
);
}
\ No newline at end of file
diff --git a/view/src/layouts/shared/Navbar.tsx b/view/src/layouts/shared/Navbar.tsx
index baba66a..3edf5f9 100644
--- a/view/src/layouts/shared/Navbar.tsx
+++ b/view/src/layouts/shared/Navbar.tsx
@@ -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() {
);
diff --git a/view/src/pages/auth/login.tsx b/view/src/pages/auth/login.tsx
index 8ece1bb..8b4db99 100644
--- a/view/src/pages/auth/login.tsx
+++ b/view/src/pages/auth/login.tsx
@@ -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);
diff --git a/view/src/pages/dashboard.tsx b/view/src/pages/dashboard.tsx
index 0fe0ebf..387284b 100644
--- a/view/src/pages/dashboard.tsx
+++ b/view/src/pages/dashboard.tsx
@@ -1,7 +1,9 @@
+import { userinfo } from "../stores/userinfo.ts";
+
export default function Dashboard() {
return (
-
Welcome, undefined
+
Welcome, {userinfo.displayName}
What's a nice day!
)
diff --git a/view/src/stores/userinfo.ts b/view/src/stores/userinfo.ts
new file mode 100644
index 0000000..f5ba90f
--- /dev/null
+++ b/view/src/stores/userinfo.ts
@@ -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 };
\ No newline at end of file
diff --git a/view/tsconfig.json b/view/tsconfig.json
index 3999958..b5ebb60 100644
--- a/view/tsconfig.json
+++ b/view/tsconfig.json
@@ -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 */