✨ Kill Sessions
This commit is contained in:
parent
2a32c8b2f6
commit
e87da59026
@ -55,6 +55,20 @@ func getEvents(c *fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func killSession(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("principal").(models.Account)
|
||||||
|
id, _ := c.ParamsInt("sessionId", 0)
|
||||||
|
|
||||||
|
if err := database.C.Delete(&models.AuthSession{}, &models.AuthSession{
|
||||||
|
BaseModel: models.BaseModel{ID: uint(id)},
|
||||||
|
AccountID: user.ID,
|
||||||
|
}).Error; err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(fiber.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
func doRegister(c *fiber.Ctx) error {
|
func doRegister(c *fiber.Ctx) error {
|
||||||
var data struct {
|
var data struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
@ -26,6 +26,7 @@ func NewServer() {
|
|||||||
{
|
{
|
||||||
api.Get("/users/me", auth, getPrincipal)
|
api.Get("/users/me", auth, getPrincipal)
|
||||||
api.Get("/users/me/events", auth, getEvents)
|
api.Get("/users/me/events", auth, getEvents)
|
||||||
|
api.Delete("/users/me/sessions/:sessionId", auth, killSession)
|
||||||
|
|
||||||
api.Post("/users", doRegister)
|
api.Post("/users", doRegister)
|
||||||
api.Post("/users/me/confirm", doRegisterConfirm)
|
api.Post("/users/me/confirm", doRegisterConfirm)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getAtk, useUserinfo } from "../stores/userinfo.tsx";
|
import { getAtk, readProfiles, useUserinfo } from "../stores/userinfo.tsx";
|
||||||
import { createSignal, For, Show } from "solid-js";
|
import { createSignal, For, Show } from "solid-js";
|
||||||
|
|
||||||
export default function DashboardPage() {
|
export default function DashboardPage() {
|
||||||
@ -20,6 +20,7 @@ export default function DashboardPage() {
|
|||||||
const [eventCount, setEventCount] = createSignal(0);
|
const [eventCount, setEventCount] = createSignal(0);
|
||||||
|
|
||||||
const [error, setError] = createSignal<string | null>(null);
|
const [error, setError] = createSignal<string | null>(null);
|
||||||
|
const [submitting, setSubmitting] = createSignal(false);
|
||||||
|
|
||||||
async function readEvents() {
|
async function readEvents() {
|
||||||
const res = await fetch("/api/users/me/events?take=10", {
|
const res = await fetch("/api/users/me/events?take=10", {
|
||||||
@ -34,6 +35,21 @@ export default function DashboardPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function killSession(item: any) {
|
||||||
|
setSubmitting(true);
|
||||||
|
const res = await fetch(`/api/users/me/sessions/${item.id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: { Authorization: `Bearer ${getAtk()}` }
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
setError(await res.text());
|
||||||
|
} else {
|
||||||
|
await readProfiles();
|
||||||
|
setError(null);
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
|
}
|
||||||
|
|
||||||
readEvents();
|
readEvents();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -160,6 +176,7 @@ export default function DashboardPage() {
|
|||||||
<th>Third Client</th>
|
<th>Third Client</th>
|
||||||
<th>Audiences</th>
|
<th>Audiences</th>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -169,6 +186,16 @@ export default function DashboardPage() {
|
|||||||
<td>{item.client_id ? "Linked" : "Non-linked"}</td>
|
<td>{item.client_id ? "Linked" : "Non-linked"}</td>
|
||||||
<td>{item.audiences?.join(", ")}</td>
|
<td>{item.audiences?.join(", ")}</td>
|
||||||
<td>{new Date(item.created_at).toLocaleString()}</td>
|
<td>{new Date(item.created_at).toLocaleString()}</td>
|
||||||
|
<td class="py-0">
|
||||||
|
<button class="btn btn-sm btn-square btn-error" disabled={submitting()}
|
||||||
|
onClick={() => killSession(item)}>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="h-5 w-5">
|
||||||
|
<path
|
||||||
|
d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208s208-93.31 208-208S370.69 48 256 48zm80 224H176a16 16 0 0 1 0-32h160a16 16 0 0 1 0 32z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
</tr>}
|
</tr>}
|
||||||
</For>
|
</For>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -36,7 +36,7 @@ export async function refreshAtk() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
throw new Error(await res.text());
|
console.error(await res.text())
|
||||||
} else {
|
} else {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
new Cookie().set("access_token", data["access_token"], { path: "/" });
|
new Cookie().set("access_token", data["access_token"], { path: "/" });
|
||||||
@ -48,7 +48,7 @@ function checkLoggedIn(): boolean {
|
|||||||
return new Cookie().get("access_token");
|
return new Cookie().get("access_token");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readProfiles() {
|
export async function readProfiles(recovering = true) {
|
||||||
if (!checkLoggedIn()) return;
|
if (!checkLoggedIn()) return;
|
||||||
|
|
||||||
const res = await fetch("/api/users/me", {
|
const res = await fetch("/api/users/me", {
|
||||||
@ -56,9 +56,14 @@ export async function readProfiles() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
// Auto retry after refresh access token
|
if (recovering) {
|
||||||
await refreshAtk();
|
// Auto retry after refresh access token
|
||||||
return await readProfiles();
|
await refreshAtk();
|
||||||
|
return await readProfiles(false);
|
||||||
|
} else {
|
||||||
|
clearUserinfo();
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
Loading…
Reference in New Issue
Block a user