UNPKG

@atproto/ozone

Version:

Backend service for moderating the Bluesky network.

269 lines 9.51 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppContext = void 0; const node_assert_1 = __importDefault(require("node:assert")); const plc = __importStar(require("@did-plc/lib")); const api_1 = require("@atproto/api"); const crypto_1 = require("@atproto/crypto"); const identity_1 = require("@atproto/identity"); const xrpc_server_1 = require("@atproto/xrpc-server"); const auth_verifier_1 = require("./auth-verifier"); const background_1 = require("./background"); const template_1 = require("./communication-service/template"); const daemon_1 = require("./daemon"); const blob_diverter_1 = require("./daemon/blob-diverter"); const db_1 = require("./db"); const mod_service_1 = require("./mod-service"); const service_1 = require("./safelink/service"); const sequencer_1 = require("./sequencer/sequencer"); const service_2 = require("./set/service"); const service_3 = require("./setting/service"); const team_1 = require("./team"); const util_1 = require("./util"); const issuer_1 = require("./verification/issuer"); const service_4 = require("./verification/service"); class AppContext { constructor(opts, secrets) { Object.defineProperty(this, "opts", { enumerable: true, configurable: true, writable: true, value: opts }); Object.defineProperty(this, "secrets", { enumerable: true, configurable: true, writable: true, value: secrets }); } static async fromConfig(cfg, secrets, overrides) { const db = new db_1.Database({ url: cfg.db.postgresUrl, schema: cfg.db.postgresSchema, poolSize: cfg.db.poolSize, poolMaxUses: cfg.db.poolMaxUses, poolIdleTimeoutMs: cfg.db.poolIdleTimeoutMs, }); const signingKey = await crypto_1.Secp256k1Keypair.import(secrets.signingKeyHex); const signingKeyId = await (0, util_1.getSigningKeyId)(db, signingKey.did()); const appviewAgent = new api_1.AtpAgent({ service: cfg.appview.url }); const pdsAgent = cfg.pds ? new api_1.AtpAgent({ service: cfg.pds.url }) : undefined; const chatAgent = cfg.chat ? new api_1.AtpAgent({ service: cfg.chat.url }) : undefined; const didCache = new identity_1.MemoryCache(cfg.identity.cacheStaleTTL, cfg.identity.cacheMaxTTL); const idResolver = new identity_1.IdResolver({ plcUrl: cfg.identity.plcUrl, didCache, }); const createAuthHeaders = (aud, lxm) => (0, xrpc_server_1.createServiceAuthHeaders)({ iss: `${cfg.service.did}#atproto_labeler`, aud, lxm, keypair: signingKey, }); const backgroundQueue = new background_1.BackgroundQueue(db); const blobDiverter = cfg.blobDivert ? new blob_diverter_1.BlobDiverter(db, { idResolver, serviceConfig: cfg.blobDivert, }) : undefined; const eventPusher = new daemon_1.EventPusher(db, createAuthHeaders, { appview: cfg.appview.pushEvents ? cfg.appview : undefined, pds: cfg.pds ?? undefined, }); const modService = mod_service_1.ModerationService.creator(signingKey, signingKeyId, cfg, backgroundQueue, idResolver, eventPusher, appviewAgent, createAuthHeaders, overrides?.imgInvalidator); const communicationTemplateService = template_1.CommunicationTemplateService.creator(); const safelinkRuleService = service_1.SafelinkRuleService.creator(); const teamService = team_1.TeamService.creator(appviewAgent, cfg.appview.did, createAuthHeaders); const setService = service_2.SetService.creator(); const settingService = service_3.SettingService.creator(); const verificationService = service_4.VerificationService.creator(); const verificationIssuer = issuer_1.VerificationIssuer.creator(); const sequencer = new sequencer_1.Sequencer(modService(db)); const authVerifier = new auth_verifier_1.AuthVerifier(idResolver, { serviceDid: cfg.service.did, adminPassword: secrets.adminPassword, teamService: teamService(db), }); return new AppContext({ db, cfg, modService, communicationTemplateService, safelinkRuleService, teamService, setService, settingService, appviewAgent, pdsAgent, chatAgent, signingKey, signingKeyId, didCache, idResolver, backgroundQueue, sequencer, authVerifier, blobDiverter, verificationService, verificationIssuer, ...(overrides ?? {}), }, secrets); } assignPort(port) { (0, node_assert_1.default)(!this.cfg.service.port || this.cfg.service.port === port, 'Conflicting port in config'); this.opts.cfg.service.port = port; } get db() { return this.opts.db; } get cfg() { return this.opts.cfg; } get modService() { return this.opts.modService; } get blobDiverter() { return this.opts.blobDiverter; } get communicationTemplateService() { return this.opts.communicationTemplateService; } get safelinkRuleService() { return this.opts.safelinkRuleService; } get teamService() { return this.opts.teamService; } get setService() { return this.opts.setService; } get settingService() { return this.opts.settingService; } get verificationService() { return this.opts.verificationService; } get verificationIssuer() { return this.opts.verificationIssuer; } get appviewAgent() { return this.opts.appviewAgent; } get pdsAgent() { return this.opts.pdsAgent; } get chatAgent() { return this.opts.chatAgent; } get signingKey() { return this.opts.signingKey; } get signingKeyId() { return this.opts.signingKeyId; } get plcClient() { return new plc.Client(this.cfg.identity.plcUrl); } get didCache() { return this.opts.didCache; } get idResolver() { return this.opts.idResolver; } get backgroundQueue() { return this.opts.backgroundQueue; } get sequencer() { return this.opts.sequencer; } get authVerifier() { return this.opts.authVerifier; } async serviceAuthHeaders(aud, lxm) { const iss = `${this.cfg.service.did}#atproto_labeler`; return (0, xrpc_server_1.createServiceAuthHeaders)({ iss, aud, lxm, keypair: this.signingKey, }); } async pdsAuth(lxm) { if (!this.cfg.pds) { return undefined; } return this.serviceAuthHeaders(this.cfg.pds.did, lxm); } async appviewAuth(lxm) { return this.serviceAuthHeaders(this.cfg.appview.did, lxm); } async chatAuth(lxm) { if (!this.cfg.chat) { throw new Error('No chat service configured'); } return this.serviceAuthHeaders(this.cfg.chat.did, lxm); } devOverride(overrides) { this.opts = { ...this.opts, ...overrides, }; } reqLabelers(req) { const val = req.header(util_1.LABELER_HEADER_NAME); let parsed; try { parsed = (0, util_1.parseLabelerHeader)(val, this.cfg.service.did); } catch (err) { parsed = null; } if (!parsed) return (0, util_1.defaultLabelerHeader)([]); return parsed; } } exports.AppContext = AppContext; //# sourceMappingURL=context.js.map