Commit 728ac1d5 authored by Grant's avatar Grant
Browse files

Merge branch '12-custom-activitypub-server-builtin' into 'main'

Custom ActivityPub server builtin

See merge request !2
parents 661fe3a7 5f9a0de8
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
FROM node:20-alpine AS base
FROM node:23-alpine AS base
RUN apk add --no-cache openssl

FROM base as dev_dep
FROM base AS dev_dep
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app

@@ -12,7 +13,7 @@ COPY --chown=node:node frontend/package*.json ./frontend/
USER node
RUN npm install --include=dev

FROM base as dep
FROM base AS dep
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app

@@ -28,7 +29,7 @@ RUN npm install --omit=dev
# === BUILDER ===
#

FROM base as build
FROM base AS build
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app

@@ -49,7 +50,7 @@ RUN npm -w backend run build
# === RUNNER ===
#

FROM base as run
FROM base AS run
WORKDIR /home/node/app
COPY --from=dep /home/node/app/ ./
COPY package*.json docker-start.sh ./
@@ -72,9 +73,9 @@ RUN npx -w backend prisma generate

# set runtime env variables

ENV PORT 3000
ENV NODE_ENV production
ENV SERVE_FRONTEND /home/node/app/frontend
ENV PORT=3000
ENV NODE_ENV=production
ENV SERVE_FRONTEND=/home/node/app/frontend

EXPOSE 3000
ENTRYPOINT [ "/bin/sh" ]
+8 −1
Original line number Diff line number Diff line
@@ -6,14 +6,21 @@
  "private": true,
  "type": "module",
  "dependencies": {
    "@fedify/express": "^0.2.0",
    "@fedify/fedify": "^1.5.1",
    "@fedify/redis": "^0.4.0",
    "@js-temporal/polyfill": "^0.5.1",
    "@logtape/logtape": "^0.9.1",
    "@prisma/client": "^5.13.0",
    "@tsconfig/recommended": "^1.0.6",
    "body-parser": "^1.20.2",
    "cookie-parser": "^1.4.6",
    "cors": "^2.8.5",
    "cron": "^4.3.0",
    "express": "^4.19.2",
    "express-session": "^1.18.0",
    "oidc-provider": "^8.4.6",
    "ioredis": "^5.6.1",
    "oidc-provider": "^8.8.1",
    "openid-client": "^5.6.5"
  },
  "devDependencies": {
+25 −0
Original line number Diff line number Diff line
/*
  Warnings:

  - You are about to drop the column `mode` on the `AuthSession` table. All the data in the column will be lost.
  - A unique constraint covering the columns `[objectId]` on the table `AuthSession` will be added. If there are existing duplicate values, this will fail.
  - The required column `objectId` was added to the `AuthSession` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required.

*/
-- AlterTable
ALTER TABLE "AuthSession" DROP COLUMN "mode",
ADD COLUMN     "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN     "expiresAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN     "objectId" TEXT NOT NULL;

-- CreateTable
CREATE TABLE "FediverseKeyPair" (
    "id" TEXT NOT NULL,
    "keyType" TEXT NOT NULL,
    "value" TEXT NOT NULL,

    CONSTRAINT "FediverseKeyPair_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "AuthSession_objectId_key" ON "AuthSession"("objectId");
+10 −1
Original line number Diff line number Diff line
@@ -28,7 +28,16 @@ model OidcModel {

model AuthSession {
  id            String @id @default(uuid())
  objectId      String @unique @default(uuid()) // fediverse object id
  one_time_code String
  mode          String // RECV_CODE | SEND_CODE -- is the service receiving or sending
  user_sub      String

  createdAt DateTime @default(now())
  expiresAt DateTime @default(now())
}

model FediverseKeyPair {
  id      String @id @default(uuid())
  keyType String
  value   String
}
+86 −0
Original line number Diff line number Diff line
import { AuthSession as DBAuthSession } from "@prisma/client";
import { prisma } from "../lib/prisma.js";

export class AuthSession {
  static generateCode(): string {
    return "."
      .repeat(5)
      .split("")
      .map(() => Math.floor(Math.random() * 10))
      .join("");
  }
  static async create(handle: `${string}@${string}`): Promise<AuthSession> {
    // day in seconds
    const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24);

    const session = await prisma.authSession.create({
      data: {
        one_time_code: this.generateCode(),
        user_sub: handle,
        expiresAt,
      },
    });

    return new AuthSession(session);
  }
  static async getExpired() {
    const sessions = await prisma.authSession.findMany({
      where: {
        expiresAt: {
          lte: new Date(),
        },
      },
    });
    return sessions.map((d) => new AuthSession(d));
  }
  static async getActive(
    handle: `${string}@${string}`
  ): Promise<AuthSession | null> {
    const session = await prisma.authSession.findFirst({
      where: {
        user_sub: handle,
        expiresAt: {
          gt: new Date(),
        },
      },
    });

    if (!session) return null;

    return new AuthSession(session);
  }

  private _id: string;
  private _user_sub: `${string}@${string}`;
  private _createdAt: Date;
  private _expiresAt: Date;
  private _code: string;

  private constructor(session: DBAuthSession) {
    this._id = session.id;
    this._user_sub = session.user_sub as any;
    this._createdAt = session.createdAt;
    this._expiresAt = session.expiresAt;
    this._code = session.one_time_code;
  }

  get id() {
    return this._id;
  }

  get user_sub() {
    return this._user_sub;
  }

  get createdAt() {
    return this._createdAt;
  }

  get expiresAt() {
    return this._expiresAt;
  }

  get code() {
    return this._code;
  }
}
Loading