summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-01-31 11:38:20 -0500
committerHazelnoot <acomputerdog@gmail.com>2025-02-08 13:17:50 -0500
commit3550ce27d50f160917b3e68829fd649e3e3f0571 (patch)
tree198886ede1a76df378871999ac4cd1d26851700d /packages/backend/src/server/api
parentfix relationship data for Mastodon API (resolves #714) (diff)
downloadsharkey-3550ce27d50f160917b3e68829fd649e3e3f0571.tar.gz
sharkey-3550ce27d50f160917b3e68829fd649e3e3f0571.tar.bz2
sharkey-3550ce27d50f160917b3e68829fd649e3e3f0571.zip
hide restricted edit history from mastodon api (resolves #811)
Diffstat (limited to 'packages/backend/src/server/api')
-rw-r--r--packages/backend/src/server/api/mastodon/MastodonApiServerService.ts12
-rw-r--r--packages/backend/src/server/api/mastodon/MastodonDataService.ts40
-rw-r--r--packages/backend/src/server/api/mastodon/converters.ts14
-rw-r--r--packages/backend/src/server/api/mastodon/endpoints/status.ts7
4 files changed, 63 insertions, 10 deletions
diff --git a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts
index 18a974c234..40180394d3 100644
--- a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts
+++ b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts
@@ -18,6 +18,7 @@ import { ApiAccountMastodonRoute } from '@/server/api/mastodon/endpoints/account
import { ApiSearchMastodonRoute } from '@/server/api/mastodon/endpoints/search.js';
import { ApiFilterMastodonRoute } from '@/server/api/mastodon/endpoints/filter.js';
import { ApiNotifyMastodonRoute } from '@/server/api/mastodon/endpoints/notifications.js';
+import { AuthenticateService } from '@/server/api/AuthenticateService.js';
import { AuthMastodonRoute } from './endpoints/auth.js';
import { toBoolean } from './timelineArgs.js';
import { convertAnnouncement, convertFilter, convertAttachment, convertFeaturedTag, convertList, MastoConverters } from './converters.js';
@@ -25,9 +26,13 @@ import { getInstance } from './endpoints/meta.js';
import { ApiAuthMastodon, ApiAccountMastodon, ApiFilterMastodon, ApiNotifyMastodon, ApiSearchMastodon, ApiTimelineMastodon, ApiStatusMastodon } from './endpoints.js';
import type { FastifyInstance, FastifyPluginOptions } from 'fastify';
-export function getClient(BASE_URL: string, authorization: string | undefined): MegalodonInterface {
+export function getAccessToken(authorization: string | undefined): string | null {
const accessTokenArr = authorization?.split(' ') ?? [null];
- const accessToken = accessTokenArr[accessTokenArr.length - 1];
+ return accessTokenArr[accessTokenArr.length - 1];
+}
+
+export function getClient(BASE_URL: string, authorization: string | undefined): MegalodonInterface {
+ const accessToken = getAccessToken(authorization);
return megalodon('misskey', BASE_URL, accessToken);
}
@@ -47,6 +52,7 @@ export class MastodonApiServerService {
private readonly driveService: DriveService,
private readonly mastoConverter: MastoConverters,
private readonly logger: MastodonLogger,
+ private readonly authenticateService: AuthenticateService,
) { }
@bindThis
@@ -918,7 +924,7 @@ export class MastodonApiServerService {
//#endregion
//#region Status
- const NoteEndpoint = new ApiStatusMastodon(fastify, this.mastoConverter, this.logger);
+ const NoteEndpoint = new ApiStatusMastodon(fastify, this.mastoConverter, this.logger, this.authenticateService);
// GET Endpoints
NoteEndpoint.getStatus();
diff --git a/packages/backend/src/server/api/mastodon/MastodonDataService.ts b/packages/backend/src/server/api/mastodon/MastodonDataService.ts
new file mode 100644
index 0000000000..782f592ee5
--- /dev/null
+++ b/packages/backend/src/server/api/mastodon/MastodonDataService.ts
@@ -0,0 +1,40 @@
+/*
+ * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { DI } from '@/di-symbols.js';
+import { QueryService } from '@/core/QueryService.js';
+import type { MiNote, NotesRepository } from '@/models/_.js';
+import type { MiLocalUser } from '@/models/User.js';
+
+/**
+ * Utility service for accessing data with Mastodon semantics
+ */
+@Injectable()
+export class MastodonDataService {
+ constructor(
+ @Inject(DI.notesRepository)
+ private readonly notesRepository: NotesRepository,
+
+ @Inject(QueryService)
+ private readonly queryService: QueryService,
+ ) {}
+
+ public async getNote(noteId: string, me?: MiLocalUser | null): Promise<MiNote | null> {
+ // Root query: note + required dependencies
+ const query = this.notesRepository
+ .createQueryBuilder('note')
+ .where('note.id = :noteId', { noteId })
+ .innerJoinAndSelect('note.user', 'user');
+
+ // Restrict visibility
+ this.queryService.generateVisibilityQuery(query, me);
+ if (me) {
+ this.queryService.generateBlockedUserQuery(query, me);
+ }
+
+ return await query.getOne();
+ }
+}
diff --git a/packages/backend/src/server/api/mastodon/converters.ts b/packages/backend/src/server/api/mastodon/converters.ts
index 4aea91b4f2..d7309b5a87 100644
--- a/packages/backend/src/server/api/mastodon/converters.ts
+++ b/packages/backend/src/server/api/mastodon/converters.ts
@@ -10,14 +10,15 @@ import { DI } from '@/di-symbols.js';
import { MfmService } from '@/core/MfmService.js';
import type { Config } from '@/config.js';
import { IMentionedRemoteUsers, MiNote } from '@/models/Note.js';
-import type { MiUser } from '@/models/User.js';
+import type { MiLocalUser, MiUser } from '@/models/User.js';
import type { NoteEditRepository, UserProfilesRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import { IdService } from '@/core/IdService.js';
import type { Packed } from '@/misc/json-schema.js';
-import { GetterService } from '../GetterService.js';
+import { MastodonDataService } from '@/server/api/mastodon/MastodonDataService.js';
+import { GetterService } from '@/server/api/GetterService.js';
// Missing from Megalodon apparently
// https://docs.joinmastodon.org/entities/StatusEdit/
@@ -62,6 +63,7 @@ export class MastoConverters {
private readonly customEmojiService: CustomEmojiService,
private readonly idService: IdService,
private readonly driveFileEntityService: DriveFileEntityService,
+ private readonly mastodonDataService: MastodonDataService,
) {}
private encode(u: MiUser, m: IMentionedRemoteUsers): MastodonEntity.Mention {
@@ -184,9 +186,11 @@ export class MastoConverters {
});
}
- public async getEdits(id: string) {
- const note = await this.getterService.getNote(id);
-
+ public async getEdits(id: string, me?: MiLocalUser | null) {
+ const note = await this.mastodonDataService.getNote(id, me);
+ if (!note) {
+ return [];
+ }
const noteUser = await this.getUser(note.userId).then(async (p) => await this.convertAccount(p));
const edits = await this.noteEditRepository.find({ where: { noteId: note.id }, order: { id: 'ASC' } });
const history: Promise<StatusEdit>[] = [];
diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts
index 1767439c2f..99259d2542 100644
--- a/packages/backend/src/server/api/mastodon/endpoints/status.ts
+++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts
@@ -7,8 +7,9 @@ import querystring, { ParsedUrlQueryInput } from 'querystring';
import { emojiRegexAtStartToEnd } from '@/misc/emoji-regex.js';
import { getErrorData, MastodonLogger } from '@/server/api/mastodon/MastodonLogger.js';
import { parseTimelineArgs, TimelineArgs, toBoolean, toInt } from '@/server/api/mastodon/timelineArgs.js';
+import { AuthenticateService } from '@/server/api/AuthenticateService.js';
import { convertAttachment, convertPoll, MastoConverters } from '../converters.js';
-import { getClient } from '../MastodonApiServerService.js';
+import { getAccessToken, getClient } from '../MastodonApiServerService.js';
import type { Entity } from 'megalodon';
import type { FastifyInstance } from 'fastify';
@@ -22,6 +23,7 @@ export class ApiStatusMastodon {
private readonly fastify: FastifyInstance,
private readonly mastoConverters: MastoConverters,
private readonly logger: MastodonLogger,
+ private readonly authenticateService: AuthenticateService,
) {}
public getStatus() {
@@ -81,7 +83,8 @@ export class ApiStatusMastodon {
this.fastify.get<{ Params: { id?: string } }>('/v1/statuses/:id/history', async (_request, reply) => {
try {
if (!_request.params.id) return reply.code(400).send({ error: 'Missing required parameter "id"' });
- const edits = await this.mastoConverters.getEdits(_request.params.id);
+ const [user] = await this.authenticateService.authenticate(getAccessToken(_request.headers.authorization));
+ const edits = await this.mastoConverters.getEdits(_request.params.id, user);
reply.send(edits);
} catch (e) {
const data = getErrorData(e);