diff --git a/package.json b/package.json index 0a9d22e..9a4b6c2 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "preview": "astro preview", "astro": "astro", "codegen": "graphql-codegen --config gql-codegen.config.ts && prisma generate", - "test": "astro check && eslint . && tsc && vitest" + "test": "astro check && eslint . && tsc && DATABASE_URL=file:./test.db prisma db push && DATABASE_URL=file:./test.db vitest" }, "dependencies": { "@astrojs/node": "^8.3.4", @@ -17,6 +17,7 @@ "@graphql-typed-document-node/core": "^3.2.0", "@js-temporal/polyfill": "^0.4.4", "@observablehq/plot": "^0.6.16", + "@octokit/auth-oauth-app": "^8.1.1", "@octokit/webhooks": "^13.3.0", "@prisma/client": "^5.22.0", "astro": "^4.16.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66d6497..8e84aed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@observablehq/plot': specifier: ^0.6.16 version: 0.6.16 + '@octokit/auth-oauth-app': + specifier: ^8.1.1 + version: 8.1.1 '@octokit/webhooks': specifier: ^13.3.0 version: 13.3.0 diff --git a/prisma/migrations/20241115014420_login/migration.sql b/prisma/migrations/20241115014420_login/migration.sql new file mode 100644 index 0000000..e96fc2e --- /dev/null +++ b/prisma/migrations/20241115014420_login/migration.sql @@ -0,0 +1,17 @@ +-- CreateTable +CREATE TABLE "GithubUser" ( + "id" TEXT NOT NULL PRIMARY KEY, + "username" TEXT NOT NULL, + "accessToken" TEXT, + "refreshToken" TEXT, + "accessTokenExpires" DATETIME, + "refreshTokenExpires" DATETIME +); + +-- CreateTable +CREATE TABLE "Session" ( + "id" TEXT NOT NULL PRIMARY KEY, + "userId" TEXT NOT NULL, + "expires" DATETIME NOT NULL, + CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "GithubUser" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 40f5237..2eb1079 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -116,3 +116,32 @@ model ProposedComment { /// The text of the proposed comment. markdown String } + +/// Logins only support Github oauth login, since this bot is solely for mediating access to Github +/// data. +model GithubUser { + /// The GraphQL node ID of this user. + id String @id + /// Github login name, for display in the UI. + username String + + // Tokens used for acting as this user. E.g. posting comments and updating labels. + accessToken String? + refreshToken String? + /// When the accessToken needs to be refreshed. + accessTokenExpires DateTime? + /// When the user will need to log in again from scratch. + refreshTokenExpires DateTime? + + sessions Session[] +} + +/// One user can have multiple active sessions in different browsers. +model Session { + /// Cryptographically random identifier for storage in a cookie. + id String @id + userId String + user GithubUser @relation(fields: [userId], references: [id], onDelete: Cascade) + + expires DateTime +} diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 50ef698..e5599b8 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,9 +1,15 @@ --- +import { CLIENT_ID } from "astro:env/server"; +import { app } from "../lib/github/auth"; +import type { User } from "../lib/login"; +import { buildUrl } from "../lib/util"; + interface Props { title: string; + user: User | null; } -const { title } = Astro.props; +const { title, user } = Astro.props; --- @@ -17,6 +23,42 @@ const { title } = Astro.props;