fix lib
This commit is contained in:
parent
fef9da2ab0
commit
46d5d1d777
|
|
@ -1,4 +1,4 @@
|
|||
import { ServerContext, SessionContext } from "./server-route";
|
||||
import type { ServerContext, SessionContext } from "lib/session/type";
|
||||
|
||||
export const sessionContext = <T>(sf: any) => {
|
||||
return sf as unknown as SessionContext<T>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { _post } from "lib/utils/post";
|
||||
import { addRoute, createRouter, findRoute } from "rou3";
|
||||
import { ServerContext, SessionContext } from "./session/type";
|
||||
import { ServerContext, SessionContext } from "../session/type";
|
||||
|
||||
type RouteFn = (...arg: any[]) => Promise<any>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
import { newClientRouter } from "../server-route";
|
||||
import { sessionRouter } from "./router/session-router";
|
||||
import { sessionClientStore } from "./store/client-store";
|
||||
import { ClientSession } from "./type";
|
||||
|
||||
export const newClientSession = <T>(arg?: {
|
||||
on: Partial<{
|
||||
messageReceived: (session: ClientSession<T>) => Promise<void>;
|
||||
afterLogin: (session: ClientSession<T>) => Promise<void>;
|
||||
afterLogout: (session: ClientSession<T>) => Promise<void>;
|
||||
afterRecheck: (session: ClientSession<T>) => Promise<void>;
|
||||
}>;
|
||||
}) => {
|
||||
const store = sessionClientStore<T>();
|
||||
const client = newClientRouter(sessionRouter);
|
||||
|
||||
const session: ClientSession<T> = {
|
||||
status: "checking",
|
||||
current: null,
|
||||
async connect() {
|
||||
const url = new URL(location.href);
|
||||
url.protocol = "wss:";
|
||||
const ws = new WebSocket(url);
|
||||
|
||||
ws.onopen = () => {
|
||||
ws.send("ok");
|
||||
};
|
||||
ws.onmessage = (m) => {
|
||||
console.log(m);
|
||||
};
|
||||
// const current = await store.load();
|
||||
// if (!current) {
|
||||
// this.status = "guest";
|
||||
// } else {
|
||||
// this.status = await client.check(current.uid, current.sid);
|
||||
// }
|
||||
return { status: this.status };
|
||||
},
|
||||
async login(arg: {
|
||||
method: "user-pass";
|
||||
username: string;
|
||||
password: string;
|
||||
}) {},
|
||||
async logout() {},
|
||||
};
|
||||
|
||||
session.connect();
|
||||
return session;
|
||||
};
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/// <reference types="bun-types" />
|
||||
|
||||
import { useServerRouter } from "../server-route";
|
||||
import { sessionRouter } from "./router/session-router";
|
||||
import { newSessionStore } from "./store/session-store";
|
||||
import { ServerContext } from "./type";
|
||||
|
||||
type SessionServerHandler = {
|
||||
cleanup: () => Promise<void>;
|
||||
handle: (arg: ServerContext) => Promise<Response>;
|
||||
};
|
||||
|
||||
export const createSessionServer = <T>(arg: {
|
||||
encrypt?: boolean;
|
||||
server_router?: ReturnType<typeof useServerRouter>;
|
||||
site_id?: string;
|
||||
}): SessionServerHandler => {
|
||||
const session_store = newSessionStore<T>(arg.site_id);
|
||||
|
||||
const session_router = useServerRouter(sessionRouter);
|
||||
|
||||
const server_handler: SessionServerHandler = {
|
||||
async cleanup() {},
|
||||
async handle(server_arg) {
|
||||
const { req, handle, url } = server_arg;
|
||||
|
||||
const route_arg = {
|
||||
...server_arg,
|
||||
session: {
|
||||
...session_store,
|
||||
current: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
if (url.pathname.startsWith("/_session/")) {
|
||||
const res = await session_router.handle(route_arg);
|
||||
if (res) return res;
|
||||
}
|
||||
|
||||
if (arg.server_router) {
|
||||
const res = await arg.server_router.handle(route_arg);
|
||||
if (res) return res;
|
||||
}
|
||||
|
||||
return handle(req);
|
||||
},
|
||||
};
|
||||
|
||||
return server_handler;
|
||||
};
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
import { ConsoleLogWriter } from "drizzle-orm";
|
||||
import { newClientRouter } from "../server/server-route";
|
||||
import { sessionRouter } from "./router/session-router";
|
||||
import { sessionClientStore } from "./store/client-store";
|
||||
import { ClientSession, SessionAuth, SessionData } from "./type";
|
||||
|
||||
export const newClientSession = <T>(arg?: {
|
||||
on?: Partial<{
|
||||
messageReceived: (session: ClientSession<T>) => Promise<void>;
|
||||
afterLogin: (session: ClientSession<T>) => Promise<void>;
|
||||
afterLogout: (session: ClientSession<T>) => Promise<void>;
|
||||
afterInit: (session: ClientSession<T>) => Promise<void>;
|
||||
}>;
|
||||
}) => {
|
||||
const store = sessionClientStore<T>();
|
||||
const client = newClientRouter(sessionRouter);
|
||||
|
||||
const login_promise = { resolve: null as any, reject: null as any };
|
||||
const logout_promise = { resolve: null as any, reject: null as any };
|
||||
|
||||
const session: ClientSession<T> = {
|
||||
status: "checking",
|
||||
wsid: "",
|
||||
current: null,
|
||||
connected: false,
|
||||
get connectURL() {
|
||||
const url = new URL(location.href);
|
||||
url.protocol = "wss:";
|
||||
url.hash = "";
|
||||
return url;
|
||||
},
|
||||
connect(auth?: SessionAuth) {
|
||||
return new Promise<void>(async (done, reject) => {
|
||||
const current = this.current;
|
||||
if (current || auth) {
|
||||
if (this.ws) {
|
||||
await wsReady(this.ws);
|
||||
}
|
||||
|
||||
const ws = new WebSocket(this.connectURL);
|
||||
this.ws = ws;
|
||||
ws.onclose = () => {
|
||||
session.connected = false;
|
||||
console.log(this.status);
|
||||
if (this.status === "logout") {
|
||||
store.clear();
|
||||
this.current = null;
|
||||
if (arg?.on?.afterLogout) {
|
||||
arg.on.afterLogout(session);
|
||||
}
|
||||
logout_promise.resolve();
|
||||
logout_promise.resolve = null;
|
||||
logout_promise.reject = null;
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
console.warn("Reconnecting Session WS...");
|
||||
this.connect();
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
ws.onopen = () => {
|
||||
if (session.current) {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
uid: session.current.uid,
|
||||
sid: session.current.sid,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
if (auth) {
|
||||
ws.send(JSON.stringify(auth));
|
||||
} else {
|
||||
if (ws.readyState === ws.OPEN) {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
ws.onmessage = async (m) => {
|
||||
if (!session.connected) {
|
||||
try {
|
||||
const parsed = JSON.parse(m.data) as
|
||||
| {
|
||||
status: "ok";
|
||||
wsid: string;
|
||||
session: SessionData<T>;
|
||||
}
|
||||
| { status: "failed" };
|
||||
|
||||
if (parsed.status === "ok") {
|
||||
session.wsid = parsed.wsid;
|
||||
session.current = parsed.session;
|
||||
if (login_promise.resolve) {
|
||||
session.connected = true;
|
||||
login_promise.resolve(session.current);
|
||||
await store.save(session.current);
|
||||
}
|
||||
} else {
|
||||
if (login_promise.reject) login_promise.reject();
|
||||
}
|
||||
login_promise.resolve = null;
|
||||
login_promise.reject = null;
|
||||
if (arg?.on?.afterLogin) {
|
||||
arg.on.afterLogin(session);
|
||||
}
|
||||
done();
|
||||
|
||||
return;
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
|
||||
if (ws.readyState === ws.OPEN) {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
const current = await store.load();
|
||||
if (!current) {
|
||||
this.status = "guest";
|
||||
} else {
|
||||
this.current = current;
|
||||
this.status = await client.check(current.uid, current.sid);
|
||||
if (this.status !== "active") {
|
||||
await store.clear();
|
||||
this.current = null;
|
||||
} else {
|
||||
await this.connect();
|
||||
}
|
||||
}
|
||||
if (arg?.on?.afterInit) {
|
||||
arg.on.afterInit(session);
|
||||
}
|
||||
|
||||
return { status: this.status };
|
||||
},
|
||||
login(auth: SessionAuth) {
|
||||
return new Promise<SessionData<T>>(async (resolve, reject) => {
|
||||
if (isEditor) {
|
||||
resolve({} as any);
|
||||
return;
|
||||
}
|
||||
|
||||
login_promise.resolve = resolve;
|
||||
login_promise.reject = reject;
|
||||
if (this.status === "checking") {
|
||||
await new Promise<void>((done) => {
|
||||
const ival = setInterval(() => {
|
||||
if (this.status !== "checking") {
|
||||
clearInterval(ival);
|
||||
done();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.status === "guest") {
|
||||
this.connect(auth);
|
||||
} else {
|
||||
console.error(
|
||||
`\
|
||||
Session login failed, current status is: ${this.status}.
|
||||
Login is prevented, please logout first before re-login!`
|
||||
);
|
||||
if (this.current) {
|
||||
resolve(this.current);
|
||||
} else {
|
||||
if (auth) {
|
||||
this.connect(auth);
|
||||
} else {
|
||||
reject("Current session not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
logout() {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
if (isEditor) {
|
||||
resolve({} as any);
|
||||
return;
|
||||
}
|
||||
|
||||
logout_promise.resolve = resolve;
|
||||
logout_promise.reject = reject;
|
||||
if (this.status === "active" && this.ws) {
|
||||
await wsReady(this.ws);
|
||||
this.status = "logout";
|
||||
|
||||
this.ws.send(JSON.stringify({ action: "logout" }));
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
if (!isEditor) {
|
||||
session.init();
|
||||
}
|
||||
return session;
|
||||
};
|
||||
|
||||
const wsReady = async (ws: WebSocket) => {
|
||||
if (ws) {
|
||||
if (ws.readyState === ws.OPEN) return;
|
||||
else {
|
||||
ws.close();
|
||||
await new Promise<void>((done) => {
|
||||
const ival = setInterval(() => {
|
||||
if (ws.readyState === ws.CLOSED) {
|
||||
clearInterval(ival);
|
||||
done();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -4,8 +4,15 @@ import { ClientSessionStatus } from "../type";
|
|||
|
||||
export default async function (this: any, uid: string, sid: string) {
|
||||
const ctx = sessionContext<EsensiSession>(this);
|
||||
|
||||
let result = "invalid" as ClientSessionStatus;
|
||||
const session = ctx.session.findFirst({ uid, sid });
|
||||
if (session) {
|
||||
if (!session.expired_at || session.expired_at > Date.now()) {
|
||||
result = "active";
|
||||
} else {
|
||||
result = "expired";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
/// <reference types="bun-types" />
|
||||
|
||||
import { ServerWebSocket } from "bun";
|
||||
import { useServerRouter } from "../server/server-route";
|
||||
import { sessionRouter } from "./router/session-router";
|
||||
import { newSessionStore } from "./store/session-store";
|
||||
import {
|
||||
ServerContext,
|
||||
SessionAuth,
|
||||
SessionStore,
|
||||
SingleSession,
|
||||
} from "./type";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { ConsoleLogWriter } from "drizzle-orm";
|
||||
|
||||
type WS = ServerWebSocket<{ url: string }>;
|
||||
type SessionServerHandler = {
|
||||
cleanup: () => Promise<void>;
|
||||
handle: (arg: ServerContext) => Promise<Response>;
|
||||
ws: {
|
||||
sids: Record<string, WS[]>;
|
||||
index: Record<string, WS>;
|
||||
conns: Map<WS, { sid: string; uid: string; wsid: string }>;
|
||||
init: () => PrasiServer["ws"];
|
||||
};
|
||||
};
|
||||
|
||||
export const initSessionServer = <T>(
|
||||
server: PrasiServer,
|
||||
arg: {
|
||||
encrypt?: boolean;
|
||||
router?: ReturnType<typeof useServerRouter>;
|
||||
login: (
|
||||
session: SessionStore<T>,
|
||||
arg: SessionAuth
|
||||
) => Promise<SingleSession<T> | false>;
|
||||
}
|
||||
) => {
|
||||
try {
|
||||
const session_store = newSessionStore<T>(server.site_id);
|
||||
const session_router = useServerRouter(sessionRouter);
|
||||
const server_handler: SessionServerHandler = {
|
||||
async cleanup() {},
|
||||
ws: {
|
||||
sids: {},
|
||||
index: {},
|
||||
conns: new Map(),
|
||||
init() {
|
||||
return {
|
||||
async message(ws, message) {
|
||||
const sids = server_handler.ws.sids;
|
||||
const conns = server_handler.ws.conns;
|
||||
const index = server_handler.ws.index;
|
||||
const conn = conns.get(ws);
|
||||
if (conn) {
|
||||
try {
|
||||
if (typeof message === "string") {
|
||||
const parsed = JSON.parse(message) as { action: "logout" };
|
||||
|
||||
if (parsed.action === "logout") {
|
||||
const sid = `${conn.uid}-${conn.sid}`;
|
||||
|
||||
if (!sids[sid]) {
|
||||
sids[sid] = [];
|
||||
}
|
||||
sids[sid].forEach((e) => {
|
||||
conns.delete(e);
|
||||
e.close();
|
||||
});
|
||||
|
||||
session_store.update(
|
||||
{ sid: conn.sid, uid: conn.uid },
|
||||
{
|
||||
active: false,
|
||||
wsid: [],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
} else {
|
||||
try {
|
||||
if (typeof message === "string") {
|
||||
const activateSession = (result: SingleSession<T>) => {
|
||||
try {
|
||||
const wsid = createId();
|
||||
conns.set(ws, {
|
||||
wsid,
|
||||
uid: result.uid,
|
||||
sid: result.sid,
|
||||
});
|
||||
|
||||
index[wsid] = ws;
|
||||
const sid = `${result.uid}-${result.sid}`;
|
||||
|
||||
if (!sids[sid]) {
|
||||
sids[sid] = [];
|
||||
}
|
||||
|
||||
sids[sid].push(ws);
|
||||
|
||||
const wsids = Object.values(sids[sid]).map(
|
||||
(e) => server_handler.ws.conns.get(e)?.sid || ""
|
||||
);
|
||||
|
||||
session_store.update(
|
||||
{ sid: result.sid, uid: result.uid },
|
||||
{
|
||||
wsid: wsids,
|
||||
}
|
||||
);
|
||||
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
status: "ok",
|
||||
wsid,
|
||||
session: result,
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const parsed = JSON.parse(message) as
|
||||
| {
|
||||
method: undefined;
|
||||
uid: string;
|
||||
sid: string;
|
||||
}
|
||||
| SessionAuth;
|
||||
|
||||
if (parsed) {
|
||||
if (parsed.method) {
|
||||
if (parsed.method === "user-pass") {
|
||||
const result = await arg.login(session_store, parsed);
|
||||
if (result) {
|
||||
activateSession(result);
|
||||
} else {
|
||||
ws.send(JSON.stringify({ status: "failed" }));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const result = session_store.findFirst({
|
||||
uid: parsed.uid,
|
||||
sid: parsed.sid,
|
||||
});
|
||||
|
||||
if (result) {
|
||||
if (
|
||||
result.active &&
|
||||
(!result.expired_at ||
|
||||
(result.expired_at &&
|
||||
result.expired_at > Date.now()))
|
||||
) {
|
||||
activateSession(result);
|
||||
} else {
|
||||
session_store.update(
|
||||
{
|
||||
uid: parsed.uid,
|
||||
sid: parsed.sid,
|
||||
},
|
||||
{ active: false }
|
||||
);
|
||||
|
||||
ws.send(JSON.stringify({ status: "expired" }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
close(ws, code, reason) {
|
||||
const result = server_handler.ws.conns.get(ws);
|
||||
|
||||
if (result) {
|
||||
const sid = `${result.uid}-${result.sid}`;
|
||||
if (server_handler.ws.sids[sid]) {
|
||||
server_handler.ws.sids[sid] = server_handler.ws.sids[
|
||||
sid
|
||||
].filter((e) => e !== ws);
|
||||
|
||||
session_store.update(
|
||||
{ sid: result.sid },
|
||||
{
|
||||
wsid: Object.values(server_handler.ws.sids[sid]).map(
|
||||
(e) => server_handler.ws.conns.get(e)?.sid || ""
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
delete server_handler.ws.index[result.wsid];
|
||||
server_handler.ws.conns.delete(ws);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
async handle(server_arg) {
|
||||
const { req, handle, url } = server_arg;
|
||||
|
||||
const route_arg = {
|
||||
...server_arg,
|
||||
session: {
|
||||
...session_store,
|
||||
current: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
if (url.pathname.startsWith("/_session/")) {
|
||||
const res = await session_router.handle(route_arg);
|
||||
if (res) return res;
|
||||
}
|
||||
|
||||
if (arg.router) {
|
||||
const res = await arg.router.handle(route_arg);
|
||||
if (res) return res;
|
||||
}
|
||||
|
||||
return handle(req);
|
||||
},
|
||||
};
|
||||
|
||||
server.ws = server_handler.ws.init();
|
||||
server.session = server_handler;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
|
@ -12,4 +12,14 @@ export const sessionClientStore = <T>() => ({
|
|||
}
|
||||
return null;
|
||||
},
|
||||
async save(arg: SessionData<T>): Promise<void> {
|
||||
if (w._prasi?.site_id) {
|
||||
localStorage.setItem(`sid-${w._prasi?.site_id}`, JSON.stringify(arg));
|
||||
}
|
||||
},
|
||||
async clear(): Promise<void> {
|
||||
if (w._prasi?.site_id) {
|
||||
localStorage.removeItem(`sid-${w._prasi?.site_id}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -14,6 +14,7 @@ export const session = sqliteTable(
|
|||
),
|
||||
active: integer("active", { mode: "boolean" }),
|
||||
data: text("data", { mode: "json" }).notNull(),
|
||||
wsid: text("wsid", { mode: "json" }).default([]),
|
||||
expired_at: integer("expired_at", { mode: "timestamp_ms" }),
|
||||
},
|
||||
(table) => {
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
/// <reference types="bun-types" />
|
||||
import Database from "bun:sqlite";
|
||||
import { and, eq, sql } from "drizzle-orm";
|
||||
import { and, ConsoleLogWriter, eq, sql } from "drizzle-orm";
|
||||
import { BunSQLiteDatabase, drizzle } from "drizzle-orm/bun-sqlite";
|
||||
import { mkdirSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { dir } from "../../utils/dir";
|
||||
import { dir } from "../../server/utils/dir";
|
||||
import { SessionData, SessionStore, SingleSession } from "../type";
|
||||
import { session } from "./schema";
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ CREATE TABLE IF NOT EXISTS session (
|
|||
created_at integer NOT NULL DEFAULT current_timestamp,
|
||||
active integer,
|
||||
data text NOT NULL,
|
||||
wsid text default \`[]\`,
|
||||
expired_at integer
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS expired_at_idx ON session (expired_at);
|
||||
|
|
@ -68,6 +69,7 @@ CREATE INDEX IF NOT EXISTS expired_at_idx ON session (expired_at);
|
|||
|
||||
return {
|
||||
create(data) {
|
||||
try {
|
||||
return createSingleStore(
|
||||
db.session
|
||||
.insert(session)
|
||||
|
|
@ -82,8 +84,29 @@ CREATE INDEX IF NOT EXISTS expired_at_idx ON session (expired_at);
|
|||
.returning()
|
||||
.get()
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Session Create Error:\n", e);
|
||||
}
|
||||
},
|
||||
update(where, data) {
|
||||
try {
|
||||
db.session
|
||||
.update(session)
|
||||
.set(data)
|
||||
.where(
|
||||
and(
|
||||
...Object.entries(where || {}).map(([k, v]) => {
|
||||
return eq(k as any, v);
|
||||
})
|
||||
)
|
||||
)
|
||||
.get();
|
||||
} catch (e) {
|
||||
console.error("Session Update Error:\n", e);
|
||||
}
|
||||
},
|
||||
findFirst(arg) {
|
||||
try {
|
||||
return createSingleStore(
|
||||
db.session
|
||||
.select()
|
||||
|
|
@ -97,8 +120,12 @@ CREATE INDEX IF NOT EXISTS expired_at_idx ON session (expired_at);
|
|||
)
|
||||
.get()
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Session FindFirst Error:\n", e);
|
||||
}
|
||||
},
|
||||
findMany(arg) {
|
||||
try {
|
||||
return db.session
|
||||
.select()
|
||||
.from(session)
|
||||
|
|
@ -111,6 +138,9 @@ CREATE INDEX IF NOT EXISTS expired_at_idx ON session (expired_at);
|
|||
)
|
||||
.all()
|
||||
.map((e) => createSingleStore(e));
|
||||
} catch (e) {
|
||||
console.error("Session FindMany Error:\n", e);
|
||||
}
|
||||
},
|
||||
} as SessionStore<T>;
|
||||
};
|
||||
|
|
@ -32,6 +32,10 @@ export type SessionStore<T> = {
|
|||
data?: T;
|
||||
expired_at?: number;
|
||||
}) => SingleSession<T>;
|
||||
update: (
|
||||
where: Partial<FilterSessionArg>,
|
||||
data: { active?: boolean; wsid?: string[] }
|
||||
) => SingleSession<T>[];
|
||||
findMany: (arg?: Partial<FilterSessionArg>) => SingleSession<T>[];
|
||||
findFirst: (arg?: Partial<FilterSessionArg>) => null | SingleSession<T>;
|
||||
};
|
||||
|
|
@ -40,16 +44,22 @@ export type ServerSession<T> = SessionStore<T> & {
|
|||
current?: SingleSession<T>;
|
||||
};
|
||||
|
||||
export type ClientSessionStatus = "checking" | "guest" | "expired" | "active";
|
||||
export type ClientSessionStatus =
|
||||
| "checking"
|
||||
| "guest"
|
||||
| "expired"
|
||||
| "active"
|
||||
| "logout";
|
||||
export type ClientSession<T> = {
|
||||
status: ClientSessionStatus;
|
||||
current: null | SessionData<T>;
|
||||
connect(): Promise<{ status: ClientSessionStatus }>;
|
||||
login(arg: {
|
||||
method: "user-pass";
|
||||
username: string;
|
||||
password: string;
|
||||
}): Promise<void>;
|
||||
wsid: string;
|
||||
connectURL: URL;
|
||||
ws?: WebSocket;
|
||||
init(): Promise<{ status: ClientSessionStatus }>;
|
||||
connect(auth?: SessionAuth): Promise<void>;
|
||||
connected: boolean;
|
||||
login(auth: SessionAuth): Promise<SessionData<T>>;
|
||||
logout(): Promise<void>;
|
||||
};
|
||||
|
||||
|
|
@ -66,3 +76,9 @@ export type ServerContext = {
|
|||
pathname: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type SessionAuth = {
|
||||
method: "user-pass";
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
import { SessionData } from "lib/server/session/server-session";
|
||||
|
||||
const w = window as unknown as {
|
||||
_prasi_session: any;
|
||||
_prasi: { site_id: string };
|
||||
};
|
||||
|
||||
type SessionResponse<T> =
|
||||
| { active: false; reason: string }
|
||||
| { active: true; data: T; token: string };
|
||||
|
||||
export const sessionClient = async <T extends SessionData<any>>(arg: {
|
||||
editorSampleData: T;
|
||||
auth: {
|
||||
mode: "user-pass";
|
||||
};
|
||||
on?: Partial<{
|
||||
active: (arg: { token: string; data: T }) => any;
|
||||
expired: () => any;
|
||||
logout: () => any;
|
||||
broadcast: (arg: { data: any }) => any;
|
||||
}>;
|
||||
}): Promise<Session<T>> => {
|
||||
const session: Session<T> = {
|
||||
active: false,
|
||||
id_site: isEditor ? "" : w._prasi.site_id,
|
||||
async login() {},
|
||||
async logout() {},
|
||||
token: "",
|
||||
data: {} as T,
|
||||
};
|
||||
if (isEditor) {
|
||||
session.active = true;
|
||||
session.data = arg.editorSampleData;
|
||||
return session;
|
||||
}
|
||||
if (w._prasi_session) return w._prasi_session as Session<T>;
|
||||
|
||||
const s = localStorage.getItem(`prss-${session.id_site}`);
|
||||
if (!s) {
|
||||
session.active = false;
|
||||
} else {
|
||||
let url = siteurl("/_session");
|
||||
if (
|
||||
location.hostname === "prasi.avolut.com" ||
|
||||
location.host === "localhost:4550"
|
||||
) {
|
||||
const newurl = new URL(location.href);
|
||||
newurl.pathname = `/_proxy/${url}`;
|
||||
url = newurl.toString();
|
||||
}
|
||||
|
||||
const prss = await fetch(url, { method: "POST", body: s });
|
||||
try {
|
||||
const resp = (await prss.json()) as SessionResponse<T>;
|
||||
if (resp) {
|
||||
if (resp.active) {
|
||||
session.data = resp.data;
|
||||
session.active = true;
|
||||
session.token = resp.token;
|
||||
} else {
|
||||
console.warn("Session inactive, reason:" + resp.reason);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Failed to activate session");
|
||||
}
|
||||
}
|
||||
|
||||
return session;
|
||||
};
|
||||
|
||||
export type Session<T extends SessionData<any>> = {
|
||||
active: boolean;
|
||||
id_site: string;
|
||||
login: (arg: { username: string; password: string }) => Promise<void>;
|
||||
logout: () => Promise<void>;
|
||||
token: string;
|
||||
data: T;
|
||||
};
|
||||
Loading…
Reference in New Issue