1
0
Fork 0
mirror of https://github.com/kou029w/quot.git synced 2025-01-31 14:28:06 +00:00

Compare commits

..

3 commits

Author SHA1 Message Date
787f97dcd7 redo and undo 2022-09-07 00:47:55 +09:00
cc9097d3a3 update dependencies 2022-09-06 23:52:06 +09:00
70006ba31c fixed dev api server 2022-09-06 23:43:35 +09:00
7 changed files with 673 additions and 206 deletions

View file

@ -7,7 +7,9 @@ interface Config {
apiEndpoint: string; apiEndpoint: string;
viewsDir: string; viewsDir: string;
rootUrl: URL; rootUrl: URL;
openid: { openid:
| false
| {
issuer: string; issuer: string;
client: { client: {
client_id: string; client_id: string;
@ -15,7 +17,7 @@ interface Config {
}; };
request: HttpOptions; request: HttpOptions;
}; };
key: KeyObject; key: false | KeyObject;
} }
export type { Config }; export type { Config };
@ -31,16 +33,18 @@ function defaultConfig(): Config {
apiUrl: new URL(process.env.QUOT_API_URL ?? "http://127.0.0.1:3000"), apiUrl: new URL(process.env.QUOT_API_URL ?? "http://127.0.0.1:3000"),
apiEndpoint: process.env.QUOT_API_ENDPOINT ?? "/api", apiEndpoint: process.env.QUOT_API_ENDPOINT ?? "/api",
viewsDir: "views", viewsDir: "views",
openid: { openid: Boolean(process.env.QUOT_OPENID_ISSUER) && {
issuer: process.env.QUOT_OPENID_ISSUER ?? "", issuer: process.env.QUOT_OPENID_ISSUER!,
client: { client: {
client_id: process.env.QUOT_OPENID_CLIENT_ID ?? "", client_id: process.env.QUOT_OPENID_CLIENT_ID!,
client_secret: process.env.QUOT_OPENID_CLIENT_SECRET ?? "", client_secret: process.env.QUOT_OPENID_CLIENT_SECRET!,
}, },
request: { timeout: 5_000 }, request: { timeout: 5_000 },
}, },
key: crypto.createPrivateKey({ key:
key: JSON.parse(process.env.QUOT_JWK ?? "{}"), Boolean(process.env.QUOT_JWK) &&
crypto.createPrivateKey({
key: JSON.parse(process.env.QUOT_JWK!),
format: "jwk", format: "jwk",
}), }),
}; };

View file

@ -3,9 +3,21 @@ import { SignJWT } from "jose";
import type { FastifyInstance } from "fastify"; import type { FastifyInstance } from "fastify";
async function login(fastify: FastifyInstance) { async function login(fastify: FastifyInstance) {
custom.setHttpOptionsDefaults(fastify.config.openid.request); const key = fastify.config.key;
const issuer = await Issuer.discover(fastify.config.openid.issuer); if (!key) {
const client = new issuer.Client(fastify.config.openid.client); fastify.log.warn("The key is required to use login endpoint.");
return;
}
const openid = fastify.config.openid;
if (!openid) {
fastify.log.warn(
"The openid parameters is required to use login endpoint."
);
return;
}
custom.setHttpOptionsDefaults(openid.request);
const issuer = await Issuer.discover(openid.issuer);
const client = new issuer.Client(openid.client);
fastify.get("/login", async (request, reply) => { fastify.get("/login", async (request, reply) => {
const params = client.callbackParams(request.raw); const params = client.callbackParams(request.raw);
@ -22,7 +34,7 @@ async function login(fastify: FastifyInstance) {
.setProtectedHeader({ typ: "JWT", alg: "RS256" }) .setProtectedHeader({ typ: "JWT", alg: "RS256" })
.setExpirationTime("30days") .setExpirationTime("30days")
.setSubject(userUrl.href) .setSubject(userUrl.href)
.sign(fastify.config.key); .sign(key);
const url = new URL(fastify.config.rootUrl); const url = new URL(fastify.config.rootUrl);
url.hash = new URLSearchParams({ jwt }).toString(); url.hash = new URLSearchParams({ jwt }).toString();
return reply.redirect(url.href); return reply.redirect(url.href);

796
app/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -13,18 +13,19 @@
"dependencies": { "dependencies": {
"@exampledev/new.css": "^1.1.3", "@exampledev/new.css": "^1.1.3",
"@fastify/http-proxy": "^8.2.2", "@fastify/http-proxy": "^8.2.2",
"@lexical/plain-text": "^0.3.11", "@lexical/history": "^0.4.1",
"esbuild": "^0.15.5", "@lexical/plain-text": "^0.4.1",
"esbuild": "^0.15.7",
"esbuild-register": "^3.3.3", "esbuild-register": "^3.3.3",
"fastify": "^4.5.3", "fastify": "^4.5.3",
"jose": "^4.9.2", "jose": "^4.9.2",
"lexical": "^0.3.11", "lexical": "^0.4.1",
"openid-client": "^5.1.9", "openid-client": "^5.1.9",
"solid-js": "^1.4.8" "solid-js": "^1.5.4"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node18-strictest-esm": "^1.0.0", "@tsconfig/node18-strictest-esm": "^1.0.1",
"@types/node": "^18.7.8", "@types/node": "^18.7.15",
"typescript": "^4.7.4" "typescript": "^4.8.2"
} }
} }

View file

@ -5,6 +5,7 @@ import {
$getRoot, $getRoot,
createEditor, createEditor,
} from "lexical"; } from "lexical";
import { registerHistory, createEmptyHistoryState } from "@lexical/history";
import { registerPlainText } from "@lexical/plain-text"; import { registerPlainText } from "@lexical/plain-text";
import { onCleanup, onMount } from "solid-js"; import { onCleanup, onMount } from "solid-js";
import type Pages from "../../protocol/pages"; import type Pages from "../../protocol/pages";
@ -34,6 +35,7 @@ export default (props: {
root.append(paragraphNode); root.append(paragraphNode);
}; };
onCleanup(registerPlainText(editor, initialEditorState)); onCleanup(registerPlainText(editor, initialEditorState));
onCleanup(registerHistory(editor, createEmptyHistoryState(), 333));
onMount(() => { onMount(() => {
onCleanup( onCleanup(
editor.registerTextContentListener((text) => { editor.registerTextContentListener((text) => {

View file

@ -11,13 +11,12 @@ async function updatePage(
content: Pages.RequestContentPage content: Pages.RequestContentPage
): Promise<boolean> { ): Promise<boolean> {
const jwt = window.localStorage.getItem("jwt"); const jwt = window.localStorage.getItem("jwt");
if (!jwt) return false;
const res = await fetch( const res = await fetch(
`${import.meta.env.QUOT_API_ENDPOINT}/pages?id=eq.${id}`, `${import.meta.env.QUOT_API_ENDPOINT}/pages?id=eq.${id}`,
{ {
method: "PUT", method: "PUT",
headers: { headers: {
authorization: `Bearer ${jwt}`, ...(jwt ? { authorization: `Bearer ${jwt}` } : {}),
"content-type": "application/json", "content-type": "application/json",
}, },
body: JSON.stringify(content), body: JSON.stringify(content),
@ -28,12 +27,11 @@ async function updatePage(
async function deletePage(id: number): Promise<boolean> { async function deletePage(id: number): Promise<boolean> {
const jwt = window.localStorage.getItem("jwt"); const jwt = window.localStorage.getItem("jwt");
if (!jwt) return false;
const res = await fetch( const res = await fetch(
`${import.meta.env.QUOT_API_ENDPOINT}/pages?id=eq.${id}`, `${import.meta.env.QUOT_API_ENDPOINT}/pages?id=eq.${id}`,
{ {
method: "DELETE", method: "DELETE",
headers: { authorization: `Bearer ${jwt}` }, headers: jwt ? { authorization: `Bearer ${jwt}` } : {},
} }
); );
return res.ok; return res.ok;

View file

@ -22,8 +22,8 @@ services:
restart: unless-stopped restart: unless-stopped
ports: ["3000:3000"] ports: ["3000:3000"]
environment: environment:
QUOT_JWK: ${QUOT_JWK:?} # https://mkjwk.org
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@/postgres?host=/var/run/postgresql DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@/postgres?host=/var/run/postgresql
PGRST_DB_ANON_ROLE: postgres
volumes: volumes:
- postgres_socket:/var/run/postgresql - postgres_socket:/var/run/postgresql
depends_on: depends_on: