diff --git a/centralUserBackend/cartero/root.cartero b/centralUserBackend/cartero/root.cartero new file mode 100644 --- /dev/null +++ b/centralUserBackend/cartero/root.cartero @@ -0,0 +1,3 @@ +version = 1 +url = "https://localhost" +method = "GET" diff --git a/centralUserBackend/package.json b/centralUserBackend/package.json --- a/centralUserBackend/package.json +++ b/centralUserBackend/package.json @@ -1,12 +1,20 @@ { "name": "centraluserbackend", - "module": "src/index.ts", + "module": "./src/index.ts", + "main": "./src/index.ts", "type": "module", "private": true, + "scripts": { + "dev": "bun --watch ." + }, + "dependencies": { + "@atproto/jwk-jose": "^0.1.11", + "@atproto/oauth-client-node": "^0.3.17" + }, "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5" } -} +} \ No newline at end of file diff --git a/centralUserBackend/src/index.ts b/centralUserBackend/src/index.ts --- a/centralUserBackend/src/index.ts +++ b/centralUserBackend/src/index.ts @@ -1,9 +1,38 @@ const server = Bun.serve({ + port: 3000, routes: { + "/": { + GET(request) { + return new Response("Hello from the HarmonyChat Central User Backend!") + } + }, "/auth/new": { - // create a new session, returns a session token - POST(request) { - return Response.json({ no: true }) + // create a new session, returns a login redirection url + async POST(request) { + try { + const { handle } = await (request.json() as Promise); + + if (!handle || typeof handle !== "string") { + return Response.json( + { error: "Handle is required" }, + { status: 400 } + ); + } + + const client = await getOAuthClient(); + + // Resolves handle, finds their auth server, returns authorization URL + const authUrl = await client.authorize(handle, { + scope: SCOPE, + }); + + return Response.json({ redirectUrl: authUrl.toString() }); + } catch (error) { + return Response.json( + { error: error instanceof Error ? error.message : "Login failed" }, + { status: 500 } + ); + } } }, "/auth/logout": { @@ -76,3 +105,5 @@ } }, } }) + +console.log(`HarmonyChat Central User Backend listening on port ${server.port}`) diff --git a/centralUserBackend/src/session.ts b/centralUserBackend/src/session.ts --- a/centralUserBackend/src/session.ts +++ b/centralUserBackend/src/session.ts @@ -1,4 +1,13 @@ -const activeSessions = new Map(); +// user id -> did:harmony:[32x randchar] - -// user id -> did:harmony:[32x randchar] +// GCI Sessions +// sessionToken -> domain +const activeGCISessions = new Map(); +// Frontend Sessions +// sessionToken -> domain +const activeFrontendSessions = new Map(); +// User Sessions +// sessionToken -> did +const activeUserSessions = new Map(); +// PDS Sessions +const activePDSSessions = new Map(); diff --git a/centralUserBackend/tsconfig.json b/centralUserBackend/tsconfig.json --- a/centralUserBackend/tsconfig.json +++ b/centralUserBackend/tsconfig.json @@ -1,30 +1,31 @@ { "compilerOptions": { // Environment setup & latest features - "lib": ["ESNext"], + "lib": [ + "ESNext" + ], "target": "ESNext", - "module": "Preserve", + "module": "esnext", "moduleDetection": "force", "jsx": "react-jsx", "allowJs": true, - "types": ["bun"], - + "types": [ + "bun" + ], // Bundler mode "moduleResolution": "bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "noEmit": true, - // Best practices "strict": true, "skipLibCheck": true, "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, "noImplicitOverride": true, - // Some stricter flags (disabled by default) "noUnusedLocals": false, "noUnusedParameters": false, "noPropertyAccessFromIndexSignature": false } -} +} \ No newline at end of file diff --git a/frontend/pnpm-workspace.yaml b/frontend/pnpm-workspace.yaml deleted file mode 100644 --- a/frontend/pnpm-workspace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -allowBuilds: - '@parcel/watcher': true - core-js: true - esbuild: true diff --git a/frontend/src/lib/authentication.ts b/frontend/src/lib/authentication.ts --- a/frontend/src/lib/authentication.ts +++ b/frontend/src/lib/authentication.ts @@ -40,7 +40,7 @@ client = new NodeOAuthClient({ clientMetadata: buildAtprotoLoopbackClientMetadata({ scope: SCOPE, - redirect_uris: [`${process.env.PUBLIC_URL || "http://127.0.0.1:5173"}/oauth/callback`], + redirect_uris: [`${process.env.PUBLIC_URL || "http://127.0.0.1"}/oauth/callback`], }), stateStore: { diff --git a/frontend/src/routes/oauth/callback.tsx b/frontend/src/routes/oauth/callback.tsx --- a/frontend/src/routes/oauth/callback.tsx +++ b/frontend/src/routes/oauth/callback.tsx @@ -44,4 +44,4 @@ return Response.redirect(new URL("/oauth/error/login_failed", PUBLIC_URL)); } } -const PUBLIC_URL = process.env.PUBLIC_URL || "http://127.0.0.1:5173"; +const PUBLIC_URL = process.env.PUBLIC_URL || "http://127.0.0.1"; diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "version": "1.0.0", "description": "Community-based AT protocol chat application", "main": "index.js", "scripts": { - "dev-frontend": "pnpm --dir ./frontend run dev" + "dev-frontend": "pnpm --dir ./frontend run dev", + "dev-cub": "pnpm --dir ./centralUserBackend run dev" }, "keywords": [], "author": "", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -209,6 +209,12 @@ .: {} centralUserBackend: dependencies: + '@atproto/jwk-jose': + specifier: ^0.1.11 + version: 0.1.11 + '@atproto/oauth-client-node': + specifier: ^0.3.17 + version: 0.3.17 typescript: specifier: ^5 version: 5.9.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,6 +2,6 @@ packages: - centralUserBackend - frontend allowBuilds: - '@parcel/watcher': set this to true or false - core-js: set this to true or false - esbuild: set this to true or false + '@parcel/watcher': true + core-js: true + esbuild: true