diff options
| author | Julia <julia@insertdomain.name> | 2025-06-19 21:35:18 +0000 |
|---|---|---|
| committer | Julia <julia@insertdomain.name> | 2025-06-19 21:35:18 +0000 |
| commit | a77c32b17da63d3932b219f74152cce023a30f4a (patch) | |
| tree | d2a05796e942c8f250bbd01369eab0cbe5a14531 /packages/backend/src/server/api/ApiCallService.ts | |
| parent | merge: release 2025.4.2 (!1051) (diff) | |
| parent | Merge branch 'develop' into release/2025.4.3 (diff) | |
| download | sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.tar.gz sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.tar.bz2 sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.zip | |
merge: prepare release 2025.4.3 (!1125)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1125
Approved-by: Marie <github@yuugi.dev>
Approved-by: Julia <julia@insertdomain.name>
Diffstat (limited to 'packages/backend/src/server/api/ApiCallService.ts')
| -rw-r--r-- | packages/backend/src/server/api/ApiCallService.ts | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 0d2dafd556..66d968224a 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -20,12 +20,14 @@ import { RoleService } from '@/core/RoleService.js'; import type { Config } from '@/config.js'; import { sendRateLimitHeaders } from '@/misc/rate-limit-utils.js'; import { SkRateLimiterService } from '@/server/SkRateLimiterService.js'; +import { renderInlineError } from '@/misc/render-inline-error.js'; import { ApiError } from './error.js'; import { ApiLoggerService } from './ApiLoggerService.js'; import { AuthenticateService, AuthenticationError } from './AuthenticateService.js'; import type { FastifyRequest, FastifyReply } from 'fastify'; import type { OnApplicationShutdown } from '@nestjs/common'; import type { IEndpointMeta, IEndpoint } from './endpoints.js'; +import { renderFullError } from '@/misc/render-full-error.js'; const accessDenied = { message: 'Access denied.', @@ -100,26 +102,26 @@ export class ApiCallService implements OnApplicationShutdown { throw err; } else { const errId = randomUUID(); - this.logger.error(`Internal error occurred in ${ep.name}: ${err.message}`, { - ep: ep.name, - ps: data, - e: { - message: err.message, - code: err.name, - stack: err.stack, - id: errId, - }, + const fullError = renderFullError(err); + const message = typeof(fullError) === 'string' + ? `Internal error id=${errId} occurred in ${ep.name}: ${fullError}` + : `Internal error id=${errId} occurred in ${ep.name}:`; + const data = typeof(fullError) === 'object' + ? { e: fullError } + : {}; + this.logger.error(message, { + user: userId ?? '<unauthenticated>', + ...data, }); if (this.config.sentryForBackend) { - Sentry.captureMessage(`Internal error occurred in ${ep.name}: ${err.message}`, { + Sentry.captureMessage(`Internal error occurred in ${ep.name}: ${renderInlineError(err)}`, { level: 'error', user: { id: userId, }, extra: { ep: ep.name, - ps: data, e: { message: err.message, code: err.name, @@ -146,6 +148,10 @@ export class ApiCallService implements OnApplicationShutdown { request: FastifyRequest<{ Body: Record<string, unknown> | undefined, Querystring: Record<string, unknown> }>, reply: FastifyReply, ): void { + // Tell crawlers not to index API endpoints. + // https://developers.google.com/search/docs/crawling-indexing/block-indexing + reply.header('X-Robots-Tag', 'noindex'); + const body = request.method === 'GET' ? request.query : request.body; @@ -344,14 +350,14 @@ export class ApiCallService implements OnApplicationShutdown { } if (ep.meta.requireCredential || ep.meta.requireModerator || ep.meta.requireAdmin) { - if (user == null) { + if (user == null && ep.meta.requireCredential !== 'optional') { throw new ApiError({ message: 'Credential required.', code: 'CREDENTIAL_REQUIRED', id: '1384574d-a912-4b81-8601-c7b1c4085df1', httpStatusCode: 401, }); - } else if (user!.isSuspended) { + } else if (user?.isSuspended) { throw new ApiError({ message: 'Your account has been suspended.', code: 'YOUR_ACCOUNT_SUSPENDED', @@ -372,8 +378,8 @@ export class ApiCallService implements OnApplicationShutdown { } } - if ((ep.meta.requireModerator || ep.meta.requireAdmin) && (this.meta.rootUserId !== user!.id)) { - const myRoles = await this.roleService.getUserRoles(user!.id); + if ((ep.meta.requireModerator || ep.meta.requireAdmin) && (this.meta.rootUserId !== user?.id)) { + const myRoles = user ? await this.roleService.getUserRoles(user) : []; if (ep.meta.requireModerator && !myRoles.some(r => r.isModerator || r.isAdministrator)) { throw new ApiError({ message: 'You are not assigned to a moderator role.', @@ -392,9 +398,9 @@ export class ApiCallService implements OnApplicationShutdown { } } - if (ep.meta.requiredRolePolicy != null && (this.meta.rootUserId !== user!.id)) { - const myRoles = await this.roleService.getUserRoles(user!.id); - const policies = await this.roleService.getUserPolicies(user!.id); + if (ep.meta.requiredRolePolicy != null && (this.meta.rootUserId !== user?.id)) { + const myRoles = user ? await this.roleService.getUserRoles(user) : []; + const policies = await this.roleService.getUserPolicies(user ?? null); if (!policies[ep.meta.requiredRolePolicy] && !myRoles.some(r => r.isAdministrator)) { throw new ApiError({ message: 'You are not assigned to a required role.', @@ -418,7 +424,7 @@ export class ApiCallService implements OnApplicationShutdown { // Cast non JSON input if ((ep.meta.requireFile || request.method === 'GET') && ep.params.properties) { for (const k of Object.keys(ep.params.properties)) { - const param = ep.params.properties![k]; + const param = ep.params.properties[k]; if (['boolean', 'number', 'integer'].includes(param.type ?? '') && typeof data[k] === 'string') { try { data[k] = JSON.parse(data[k]); |