diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2025-03-20 20:43:05 -0400 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2025-03-27 19:51:42 -0400 |
| commit | f61d71ac8cda6455238faa976ef221525ab5ed34 (patch) | |
| tree | ae61964b8c9d33e4396be1863d2bbda1f20cd78c /packages/backend/src/server/api/mastodon/MastodonClientService.ts | |
| parent | merge: fix: bubble timeline not being selectable when logged out (!950) (diff) | |
| download | sharkey-f61d71ac8cda6455238faa976ef221525ab5ed34.tar.gz sharkey-f61d71ac8cda6455238faa976ef221525ab5ed34.tar.bz2 sharkey-f61d71ac8cda6455238faa976ef221525ab5ed34.zip | |
refactor mastodon API and preserve remote user agent for requests
Diffstat (limited to 'packages/backend/src/server/api/mastodon/MastodonClientService.ts')
| -rw-r--r-- | packages/backend/src/server/api/mastodon/MastodonClientService.ts | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/packages/backend/src/server/api/mastodon/MastodonClientService.ts b/packages/backend/src/server/api/mastodon/MastodonClientService.ts new file mode 100644 index 0000000000..82f9b7bfa9 --- /dev/null +++ b/packages/backend/src/server/api/mastodon/MastodonClientService.ts @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { megalodon, MegalodonInterface } from 'megalodon'; +import { Injectable } from '@nestjs/common'; +import { MiLocalUser } from '@/models/User.js'; +import { AuthenticateService } from '@/server/api/AuthenticateService.js'; +import type { FastifyRequest } from 'fastify'; + +@Injectable() +export class MastodonClientService { + constructor( + private readonly authenticateService: AuthenticateService, + ) {} + + /** + * Gets the authenticated user and API client for a request. + */ + public async getAuthClient(request: FastifyRequest, accessToken?: string | null): Promise<{ client: MegalodonInterface, me: MiLocalUser | null }> { + const authorization = request.headers.authorization; + accessToken = accessToken !== undefined ? accessToken : getAccessToken(authorization); + + const me = await this.getAuth(request, accessToken); + const client = this.getClient(request, accessToken); + + return { client, me }; + } + + /** + * Gets the authenticated client user for a request. + */ + public async getAuth(request: FastifyRequest, accessToken?: string | null): Promise<MiLocalUser | null> { + const authorization = request.headers.authorization; + accessToken = accessToken !== undefined ? accessToken : getAccessToken(authorization); + const [me] = await this.authenticateService.authenticate(accessToken); + return me; + } + + /** + * Creates an authenticated API client for a request. + */ + public getClient(request: FastifyRequest, accessToken?: string | null): MegalodonInterface { + const authorization = request.headers.authorization; + accessToken = accessToken !== undefined ? accessToken : getAccessToken(authorization); + + // TODO pass agent? + const baseUrl = this.getBaseUrl(request); + const userAgent = request.headers['user-agent']; + return megalodon('misskey', baseUrl, accessToken, userAgent); + } + + /** + * Gets the base URL (origin) of the incoming request + */ + public getBaseUrl(request: FastifyRequest): string { + return `${request.protocol}://${request.host}`; + } +} + +/** + * Extracts the first access token from an authorization header + * Returns null if none were found. + */ +function getAccessToken(authorization: string | undefined): string | null { + const accessTokenArr = authorization?.split(' ') ?? [null]; + return accessTokenArr[accessTokenArr.length - 1]; +} |