diff --git a/src/app.ts b/src/app.ts index e8673ed3..a2eda9d0 100644 --- a/src/app.ts +++ b/src/app.ts @@ -36,6 +36,7 @@ import { cors } from 'hono/cors'; import jwt from 'jsonwebtoken'; import jose from 'node-jose'; import { behindProxy } from 'x-forwarded-fetch'; +import { AccountService } from './account/account.service'; import { client } from './db'; import { acceptDispatcher, @@ -611,7 +612,8 @@ app.use(async (ctx, next) => { await next(); }); -const siteService = new SiteService(client); +const accountService = new AccountService(client); +const siteService = new SiteService(client, accountService); // This needs to go before the middleware which loads the site // Because the site doesn't always exist - this is how it's created app.get('/.ghost/activitypub/site', getSiteDataHandler(siteService)); diff --git a/src/site/site.service.integration.test.ts b/src/site/site.service.integration.test.ts index 7a69773c..10eadc2b 100644 --- a/src/site/site.service.integration.test.ts +++ b/src/site/site.service.integration.test.ts @@ -1,12 +1,15 @@ -import { beforeEach, describe, expect, it } from 'vitest'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; import { TABLE_SITES } from '../constants'; import { client as db } from '../db'; +import { AccountService } from '../account/account.service'; +import type { Account } from '../account/types'; import { type Site, SiteService } from './site.service'; describe('SiteService', () => { let service: SiteService; + let accountService: AccountService; let site: Site; beforeEach(async () => { @@ -15,8 +18,9 @@ describe('SiteService', () => { await db(TABLE_SITES).truncate(); await db.raw('SET FOREIGN_KEY_CHECKS = 1'); + accountService = Object.create(AccountService.prototype); // Create the service - service = new SiteService(db); + service = new SiteService(db, accountService); }); it('Can initialise a site multiple times and retrieve it', async () => { @@ -24,12 +28,18 @@ describe('SiteService', () => { expect(existingSite).toBeNull(); + const createInternalAccount = vi + .spyOn(accountService, 'createInternalAccount') + .mockResolvedValue({} as unknown as Account); + const site = await service.initialiseSiteForHost('hostname.tld'); expect(site.host).toBe('hostname.tld'); expect(site.webhook_secret).toBeDefined(); expect(site.id).toBeDefined(); + expect(createInternalAccount.mock.calls).toHaveLength(1); + const siteRows = await db(TABLE_SITES).select('*'); expect(siteRows).toHaveLength(1); diff --git a/src/site/site.service.ts b/src/site/site.service.ts index 6b45b411..86c5fde2 100644 --- a/src/site/site.service.ts +++ b/src/site/site.service.ts @@ -1,5 +1,6 @@ import crypto from 'node:crypto'; import type { Knex } from 'knex'; +import type { AccountService } from '../account/account.service'; export type Site = { id: number; @@ -8,7 +9,10 @@ export type Site = { }; export class SiteService { - constructor(private client: Knex) {} + constructor( + private client: Knex, + private accountService: AccountService, + ) {} private async createSite(host: string): Promise { const rows = await this.client @@ -65,6 +69,11 @@ export class SiteService { throw new Error(`Site initialisation failed for ${host}`); } + const internalAccount = await this.accountService.createInternalAccount( + newSite, + 'index', + ); + return newSite; } }