diff --git a/package.json b/package.json index 40557a772..dba9a0dd3 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ }, "devDependencies": { "admin": "workspace:./admin", - "docs": "workspace:./doc" + "docs": "workspace:./doc", + "ui": "workspace:./ui" }, "engines": { "node": ">=18.18.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 656d59201..0cc9bd4bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,6 +18,9 @@ importers: docs: specifier: workspace:./doc version: link:doc + ui: + specifier: workspace:./ui + version: link:ui admin: devDependencies: @@ -348,6 +351,15 @@ importers: specifier: ^5.4.3 version: 5.4.3 + ui: + devDependencies: + typescript: + specifier: ^5.2.2 + version: 5.4.3 + vite: + specifier: ^5.2.0 + version: 5.2.3 + packages: /@aashutoshrathi/word-wrap@1.2.6: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 53cf76272..9ebd5c672 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,3 +3,4 @@ packages: - admin - bin - doc + - ui diff --git a/src/node/security/OAuth2Provider.ts b/src/node/security/OAuth2Provider.ts index fd50c9e87..b5afbb5cb 100644 --- a/src/node/security/OAuth2Provider.ts +++ b/src/node/security/OAuth2Provider.ts @@ -27,7 +27,6 @@ const configuration: Configuration = { ], scopes: ['openid', 'profile', 'email'], findAccount: async (ctx, id) => { - console.log("Finding account", id) return { accountId: id, claims: () => ({ @@ -71,7 +70,6 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp const {login, password} = (await formid.parse(req))[0] const {prompt, jti, session, params, grantId} = await oidc.interactionDetails(req, res); - console.log("Session is", session) switch (prompt.name) { case 'login': { @@ -131,8 +129,7 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp } await next(); } catch (err) { - console.log(err) - return next(err); + return res.writeHead(500).end(err.message); } }) @@ -143,10 +140,8 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp uid, prompt, params, session, } = await oidc.interactionDetails(req, res); - console.log("Params are", params) params["state"] = uid - console.log("Prompt is", prompt) switch (prompt.name) { case 'login': { res.redirect(format({ @@ -156,7 +151,6 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp break } case 'consent': { - console.log("Consent") res.redirect(format({ pathname: '/views/consent', query: params as ParsedUrlQuery @@ -180,22 +174,7 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp res.sendFile(path.join(settings.root,'src','static', 'oidc','consent.html')); }) - args.app.get('/interaction/:uid/confirm', async (req, res) => { - const {uid, prompt, params} = await oidc.interactionDetails(req, res); - console.log('interaction', uid, prompt, params); - res.render('interaction', { - uid, - prompt, - params, - title: 'Authorize', - client: await oidc.Client.find(params.client_id!), - }); - }) - - args.app.get('/interaction/:uid', async (req, res) => { - return res.sendFile(path.join(settings.root,'src','static', 'oidc','login.html')); - }) - + /* oidc.on('authorization.error', (ctx, error) => { console.log('authorization.error', error); }) @@ -211,7 +190,7 @@ export const expressCreateServer = async (hookName: string, args: ArgsExpressTyp }) oidc.on('revocation.error', (ctx, error) => { console.log('revocation.error', error); - }) + })*/ args.app.use("/oidc", oidc.callback()); //cb(); } diff --git a/src/node/security/OIDCAdapter.ts b/src/node/security/OIDCAdapter.ts index d71d98112..219f9edf6 100644 --- a/src/node/security/OIDCAdapter.ts +++ b/src/node/security/OIDCAdapter.ts @@ -68,7 +68,6 @@ class MemoryAdapter implements Adapter{ find(id: string): Promise { const foundSession = storage.get(this.key(id)) as AdapterPayload; - console.log("find", id, foundSession); if (storage.has(this.key(id))){ return Promise.resolve(storage.get(this.key(id)) as AdapterPayload); } @@ -76,7 +75,6 @@ class MemoryAdapter implements Adapter{ } findByUserCode(userCode: string) { - console.log("findByUserCode", userCode); const id = storage.get(userCodeKeyFor(userCode)) as string; return this.find(id); } @@ -99,14 +97,11 @@ class MemoryAdapter implements Adapter{ } findByUid(uid: string): Promise { - console.log("findByUid", uid); for(const [_, value] of storage.entries()){ if(typeof value ==="object" && "uid" in value && value.uid === uid){ - console.log("found", value); return Promise.resolve(value); } } - console.log("not found"); return Promise.resolve(undefined); } diff --git a/src/static/oidc/login.html b/src/static/oidc/login.html index edc26fce8..ef9a7ddb2 100644 --- a/src/static/oidc/login.html +++ b/src/static/oidc/login.html @@ -26,17 +26,14 @@ body: JSON.stringify(data), }).then(response => { if (response.ok) { - return response.json(); - } - throw new Error('Network response was not ok.'); - }).then(data => { - if (data.status === 'success') { - window.location.href = data.redirect; + if (response.redirected) { + window.location.href = response.url; + } } else { document.getElementById('error').innerText = "Error signing in"; } }).catch(error => { - console.error('There has been a problem with your fetch operation:', error); + document.getElementById('error').innerText = "Error signing in"+error; }); }); } diff --git a/ui/.gitignore b/ui/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/ui/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/ui/consent.html b/ui/consent.html new file mode 100644 index 000000000..d687f6b77 --- /dev/null +++ b/ui/consent.html @@ -0,0 +1,13 @@ + + + + + + + Vite + TS + + +
+ + + diff --git a/ui/login.html b/ui/login.html new file mode 100644 index 000000000..44a933506 --- /dev/null +++ b/ui/login.html @@ -0,0 +1,13 @@ + + + + + + + Vite + TS + + +
+ + + diff --git a/ui/package.json b/ui/package.json new file mode 100644 index 000000000..fb5cab322 --- /dev/null +++ b/ui/package.json @@ -0,0 +1,15 @@ +{ + "name": "ui", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.2.2", + "vite": "^5.2.0" + } +} diff --git a/ui/public/vite.svg b/ui/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/ui/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/consent.ts b/ui/src/consent.ts new file mode 100644 index 000000000..e69de29bb diff --git a/ui/src/main.ts b/ui/src/main.ts new file mode 100644 index 000000000..4d2f2a286 --- /dev/null +++ b/ui/src/main.ts @@ -0,0 +1,3 @@ +import './style.css' + + diff --git a/ui/src/style.css b/ui/src/style.css new file mode 100644 index 000000000..f9c735024 --- /dev/null +++ b/ui/src/style.css @@ -0,0 +1,96 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.vanilla:hover { + filter: drop-shadow(0 0 2em #3178c6aa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/ui/src/typescript.svg b/ui/src/typescript.svg new file mode 100644 index 000000000..d91c910cc --- /dev/null +++ b/ui/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui/src/vite-env.d.ts b/ui/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/ui/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/ui/tsconfig.json b/ui/tsconfig.json new file mode 100644 index 000000000..75abdef26 --- /dev/null +++ b/ui/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/ui/vite.config.ts b/ui/vite.config.ts new file mode 100644 index 000000000..4fafe1389 --- /dev/null +++ b/ui/vite.config.ts @@ -0,0 +1,14 @@ +// vite.config.js +import { resolve } from 'path' +import { defineConfig } from 'vite' + +export default defineConfig({ + build: { + rollupOptions: { + input: { + main: resolve(__dirname, 'index.html'), + nested: resolve(__dirname, 'nested/index.html'), + }, + }, + }, +})