From 45d005fa1aa51bf50fc0b882280e6af61860a04a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Thu, 28 Sep 2023 22:58:01 +0200 Subject: [PATCH] [mastodon-client] POST /follow_requests/:id/authorize, POST /follow_requests/:id/reject --- .../server/api/mastodon/endpoints/account.ts | 36 +++++++++++-------- .../src/server/api/mastodon/helpers/user.ts | 28 +++++++++++---- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts index bb61bbc79..badcbcf75 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/account.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts @@ -527,14 +527,18 @@ export function apiAccountMastodon(router: Router): void { router.post<{ Params: { id: string } }>( "/v1/follow_requests/:id/authorize", async (ctx) => { - const BASE_URL = `${ctx.protocol}://${ctx.hostname}`; - const accessTokens = ctx.headers.authorization; - const client = getClient(BASE_URL, accessTokens); try { - const data = await client.acceptFollowRequest( - convertId(ctx.params.id, IdType.IceshrimpId), - ); - ctx.body = convertRelationship(data.data); + const auth = await authenticate(ctx.headers.authorization, null); + const user = auth[0] ?? null; + + if (!user) { + ctx.status = 401; + return; + } + + const target = await UserHelpers.getUserCached(convertId(ctx.params.id, IdType.IceshrimpId)); + const result = await UserHelpers.acceptFollowRequest(target, user); + ctx.body = convertRelationship(result); } catch (e: any) { console.error(e); console.error(e.response.data); @@ -546,14 +550,18 @@ export function apiAccountMastodon(router: Router): void { router.post<{ Params: { id: string } }>( "/v1/follow_requests/:id/reject", async (ctx) => { - const BASE_URL = `${ctx.protocol}://${ctx.hostname}`; - const accessTokens = ctx.headers.authorization; - const client = getClient(BASE_URL, accessTokens); try { - const data = await client.rejectFollowRequest( - convertId(ctx.params.id, IdType.IceshrimpId), - ); - ctx.body = convertRelationship(data.data); + const auth = await authenticate(ctx.headers.authorization, null); + const user = auth[0] ?? null; + + if (!user) { + ctx.status = 401; + return; + } + + const target = await UserHelpers.getUserCached(convertId(ctx.params.id, IdType.IceshrimpId)); + const result = await UserHelpers.rejectFollowRequest(target, user); + ctx.body = convertRelationship(result); } catch (e: any) { console.error(e); console.error(e.response.data); diff --git a/packages/backend/src/server/api/mastodon/helpers/user.ts b/packages/backend/src/server/api/mastodon/helpers/user.ts index f40ec5837..d7afd9020 100644 --- a/packages/backend/src/server/api/mastodon/helpers/user.ts +++ b/packages/backend/src/server/api/mastodon/helpers/user.ts @@ -31,6 +31,8 @@ import { Muting } from "@/models/entities/muting.js"; import { publishUserEvent } from "@/services/stream.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js"; import { convertId, IdType } from "@/misc/convert-id.js"; +import acceptFollowRequest from "@/services/following/requests/accept.js"; +import { rejectFollowRequest } from "@/services/following/reject.js"; export type AccountCache = { locks: AsyncLock; @@ -47,7 +49,7 @@ export type LinkPaginationObject = { type RelationshipType = 'followers' | 'following'; export class UserHelpers { - public static async followUser(target: User, localUser: ILocalUser, reblogs: boolean, notify: boolean) { + public static async followUser(target: User, localUser: ILocalUser, reblogs: boolean, notify: boolean): Promise { //FIXME: implement reblogs & notify params const following = await Followings.exist({where: {followerId: localUser.id, followeeId: target.id}}); const requested = await FollowRequests.exist({where: {followerId: localUser.id, followeeId: target.id}}); @@ -57,7 +59,7 @@ export class UserHelpers { return this.getUserRelationshipTo(target.id, localUser.id); } - public static async unfollowUser(target: User, localUser: ILocalUser) { + public static async unfollowUser(target: User, localUser: ILocalUser): Promise { const following = await Followings.exist({where: {followerId: localUser.id, followeeId: target.id}}); const requested = await FollowRequests.exist({where: {followerId: localUser.id, followeeId: target.id}}); if (following) @@ -68,7 +70,7 @@ export class UserHelpers { return this.getUserRelationshipTo(target.id, localUser.id); } - public static async blockUser(target: User, localUser: ILocalUser) { + public static async blockUser(target: User, localUser: ILocalUser): Promise { const blocked = await Blockings.exist({where: {blockerId: localUser.id, blockeeId: target.id}}); if (!blocked) await createBlocking(localUser, target); @@ -76,7 +78,7 @@ export class UserHelpers { return this.getUserRelationshipTo(target.id, localUser.id); } - public static async unblockUser(target: User, localUser: ILocalUser) { + public static async unblockUser(target: User, localUser: ILocalUser): Promise { const blocked = await Blockings.exist({where: {blockerId: localUser.id, blockeeId: target.id}}); if (blocked) await deleteBlocking(localUser, target); @@ -84,7 +86,7 @@ export class UserHelpers { return this.getUserRelationshipTo(target.id, localUser.id); } - public static async muteUser(target: User, localUser: ILocalUser, notifications: boolean = true, duration: number = 0) { + public static async muteUser(target: User, localUser: ILocalUser, notifications: boolean = true, duration: number = 0): Promise { //FIXME: respect notifications parameter const muted = await Mutings.exist({where: {muterId: localUser.id, muteeId: target.id}}); if (!muted) { @@ -107,7 +109,7 @@ export class UserHelpers { return this.getUserRelationshipTo(target.id, localUser.id); } - public static async unmuteUser(target: User, localUser: ILocalUser) { + public static async unmuteUser(target: User, localUser: ILocalUser): Promise { const muting = await Mutings.findOneBy({muterId: localUser.id, muteeId: target.id}); if (muting) { await Mutings.delete({ @@ -120,6 +122,20 @@ export class UserHelpers { return this.getUserRelationshipTo(target.id, localUser.id); } + public static async acceptFollowRequest(target: User, localUser: ILocalUser): Promise { + const pending = await FollowRequests.exist({where: {followerId: target.id, followeeId: localUser.id}}); + if (pending) + await acceptFollowRequest(localUser, target); + return this.getUserRelationshipTo(target.id, localUser.id); + } + + public static async rejectFollowRequest(target: User, localUser: ILocalUser): Promise { + const pending = await FollowRequests.exist({where: {followerId: target.id, followeeId: localUser.id}}); + if (pending) + await rejectFollowRequest(localUser, target); + return this.getUserRelationshipTo(target.id, localUser.id); + } + public static async getUserMutes(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 40, cache: AccountCache = UserHelpers.getFreshAccountCache()): Promise> { if (limit > 80) limit = 80;