merge: Reduce log spam (!1004)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1004 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
commit
00c0bdbc94
113 changed files with 909 additions and 626 deletions
|
|
@ -32,6 +32,7 @@ import { getIpHash } from '@/misc/get-ip-hash.js';
|
|||
import { AuthenticateService } from '@/server/api/AuthenticateService.js';
|
||||
import { SkRateLimiterService } from '@/server/SkRateLimiterService.js';
|
||||
import { Keyed, RateLimit, sendRateLimitHeaders } from '@/misc/rate-limit-utils.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
|
|
@ -120,7 +121,7 @@ export class FileServerService {
|
|||
|
||||
@bindThis
|
||||
private async errorHandler(request: FastifyRequest<{ Params?: { [x: string]: any }; Querystring?: { [x: string]: any }; }>, reply: FastifyReply, err?: any) {
|
||||
this.logger.error(`${err}`);
|
||||
this.logger.error(`Unhandled error in file server: ${renderInlineError(err)}`);
|
||||
|
||||
reply.header('Cache-Control', 'max-age=300');
|
||||
|
||||
|
|
@ -353,7 +354,7 @@ export class FileServerService {
|
|||
if (!request.headers['user-agent']) {
|
||||
throw new StatusError('User-Agent is required', 400, 'User-Agent is required');
|
||||
} else if (request.headers['user-agent'].toLowerCase().indexOf('misskey/') !== -1) {
|
||||
throw new StatusError('Refusing to proxy a request from another proxy', 403, 'Proxy is recursive');
|
||||
throw new StatusError(`Refusing to proxy recursive request to ${url} (from user-agent ${request.headers['user-agent']})`, 403, 'Proxy is recursive');
|
||||
}
|
||||
|
||||
// Create temp file
|
||||
|
|
@ -383,7 +384,7 @@ export class FileServerService {
|
|||
) {
|
||||
if (!isConvertibleImage) {
|
||||
// 画像でないなら404でお茶を濁す
|
||||
throw new StatusError('Unexpected mime', 404);
|
||||
throw new StatusError(`Unexpected non-convertible mime: ${file.mime}`, 404, 'Unexpected mime');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -447,7 +448,7 @@ export class FileServerService {
|
|||
} else if (file.mime === 'image/svg+xml') {
|
||||
image = this.imageProcessingService.convertToWebpStream(file.path, 2048, 2048);
|
||||
} else if (!file.mime.startsWith('image/') || !FILE_TYPE_BROWSERSAFE.includes(file.mime)) {
|
||||
throw new StatusError('Rejected type', 403, 'Rejected type');
|
||||
throw new StatusError(`Blocked mime type: ${file.mime}`, 403, 'Blocked mime type');
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
|
|
@ -521,7 +522,7 @@ export class FileServerService {
|
|||
> {
|
||||
if (url.startsWith(`${this.config.url}/files/`)) {
|
||||
const key = url.replace(`${this.config.url}/files/`, '').split('/').shift();
|
||||
if (!key) throw new StatusError('Invalid File Key', 400, 'Invalid File Key');
|
||||
if (!key) throw new StatusError(`Invalid file URL ${url}`, 400, 'Invalid file url');
|
||||
|
||||
return await this.getFileFromKey(key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { genIdenticon } from '@/misc/gen-identicon.js';
|
|||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import { ActivityPubServerService } from './ActivityPubServerService.js';
|
||||
import { NodeinfoServerService } from './NodeinfoServerService.js';
|
||||
import { ApiServerService } from './api/ApiServerService.js';
|
||||
|
|
@ -277,7 +278,7 @@ export class ServerService implements OnApplicationShutdown {
|
|||
this.logger.error(`Port ${this.config.port} is already in use by another process.`);
|
||||
break;
|
||||
default:
|
||||
this.logger.error(err);
|
||||
this.logger.error(`Unhandled error in server: ${renderInlineError(err)}`);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ function createLimitKey(limit: ParsedLimit, actor: string, value: string): strin
|
|||
return `rl_${actor}_${limit.key}_${value}`;
|
||||
}
|
||||
|
||||
class ConflictError extends Error {}
|
||||
export class ConflictError extends Error {}
|
||||
|
||||
interface LimitCounter {
|
||||
timestamp: number;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export class GetterService {
|
|||
const note = await this.notesRepository.findOneBy({ id: noteId });
|
||||
|
||||
if (note == null) {
|
||||
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.');
|
||||
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', `Note ${noteId} does not exist`);
|
||||
}
|
||||
|
||||
return note;
|
||||
|
|
@ -47,7 +47,7 @@ export class GetterService {
|
|||
const note = await this.notesRepository.findOne({ where: { id: noteId }, relations: ['user'] });
|
||||
|
||||
if (note == null) {
|
||||
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.');
|
||||
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', `Note ${noteId} does not exist`);
|
||||
}
|
||||
|
||||
return note;
|
||||
|
|
@ -59,7 +59,7 @@ export class GetterService {
|
|||
@bindThis
|
||||
public async getEdits(noteId: MiNote['id']) {
|
||||
const edits = await this.noteEditRepository.findBy({ noteId: noteId }).catch(() => {
|
||||
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.');
|
||||
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', `Note ${noteId} does not exist`);
|
||||
});
|
||||
|
||||
return edits;
|
||||
|
|
@ -73,7 +73,7 @@ export class GetterService {
|
|||
const user = await this.usersRepository.findOneBy({ id: userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', 'No such user.');
|
||||
throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', `User ${userId} does not exist`);
|
||||
}
|
||||
|
||||
return user as MiLocalUser | MiRemoteUser;
|
||||
|
|
|
|||
|
|
@ -205,37 +205,37 @@ export class SigninApiService {
|
|||
if (process.env.NODE_ENV !== 'test') {
|
||||
if (this.meta.enableHcaptcha && this.meta.hcaptchaSecretKey) {
|
||||
await this.captchaService.verifyHcaptcha(this.meta.hcaptchaSecretKey, body['hcaptcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableMcaptcha && this.meta.mcaptchaSecretKey && this.meta.mcaptchaSitekey && this.meta.mcaptchaInstanceUrl) {
|
||||
await this.captchaService.verifyMcaptcha(this.meta.mcaptchaSecretKey, this.meta.mcaptchaSitekey, this.meta.mcaptchaInstanceUrl, body['m-captcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableFC && this.meta.fcSecretKey) {
|
||||
await this.captchaService.verifyFriendlyCaptcha(this.meta.fcSecretKey, body['frc-captcha-solution']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableRecaptcha && this.meta.recaptchaSecretKey) {
|
||||
await this.captchaService.verifyRecaptcha(this.meta.recaptchaSecretKey, body['g-recaptcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableTurnstile && this.meta.turnstileSecretKey) {
|
||||
await this.captchaService.verifyTurnstile(this.meta.turnstileSecretKey, body['turnstile-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableTestcaptcha) {
|
||||
await this.captchaService.verifyTestcaptcha(body['testcaptcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ export class SigninWithPasskeyApiService {
|
|||
try {
|
||||
authorizedUserId = await this.webAuthnService.verifySignInWithPasskeyAuthentication(context, credential);
|
||||
} catch (err) {
|
||||
this.logger.warn(`Passkey challenge Verify error! : ${err}`);
|
||||
this.logger.warn('Passkey challenge verify error:', err as Error);
|
||||
const errorId = (err as IdentifiableError).id;
|
||||
return error(403, {
|
||||
id: errorId,
|
||||
|
|
|
|||
|
|
@ -83,37 +83,37 @@ export class SignupApiService {
|
|||
if (process.env.NODE_ENV !== 'test') {
|
||||
if (this.meta.enableHcaptcha && this.meta.hcaptchaSecretKey) {
|
||||
await this.captchaService.verifyHcaptcha(this.meta.hcaptchaSecretKey, body['hcaptcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableMcaptcha && this.meta.mcaptchaSecretKey && this.meta.mcaptchaSitekey && this.meta.mcaptchaInstanceUrl) {
|
||||
await this.captchaService.verifyMcaptcha(this.meta.mcaptchaSecretKey, this.meta.mcaptchaSitekey, this.meta.mcaptchaInstanceUrl, body['m-captcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableRecaptcha && this.meta.recaptchaSecretKey) {
|
||||
await this.captchaService.verifyRecaptcha(this.meta.recaptchaSecretKey, body['g-recaptcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableTurnstile && this.meta.turnstileSecretKey) {
|
||||
await this.captchaService.verifyTurnstile(this.meta.turnstileSecretKey, body['turnstile-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableFC && this.meta.fcSecretKey) {
|
||||
await this.captchaService.verifyFriendlyCaptcha(this.meta.fcSecretKey, body['frc-captcha-solution']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.meta.enableTestcaptcha) {
|
||||
await this.captchaService.verifyTestcaptcha(body['testcaptcha-response']).catch(err => {
|
||||
throw new FastifyReplyError(400, err);
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +287,7 @@ export class SignupApiService {
|
|||
token: secret,
|
||||
};
|
||||
} catch (err) {
|
||||
throw new FastifyReplyError(400, typeof err === 'string' ? err : (err as Error).toString());
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -356,7 +356,7 @@ export class SignupApiService {
|
|||
|
||||
return this.signinService.signin(request, reply, account as MiLocalUser);
|
||||
} catch (err) {
|
||||
throw new FastifyReplyError(400, typeof err === 'string' ? err : (err as Error).toString());
|
||||
throw new FastifyReplyError(400, String(err), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,11 +68,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
private readonly moderationLogService: ModerationLogService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
try {
|
||||
if (new URL(ps.inbox).protocol !== 'https:') throw new Error('https only');
|
||||
} catch {
|
||||
throw new ApiError(meta.errors.invalidUrl);
|
||||
}
|
||||
if (!URL.canParse(ps.inbox)) throw new ApiError(meta.errors.invalidUrl);
|
||||
if (new URL(ps.inbox).protocol !== 'https:') throw new ApiError(meta.errors.invalidUrl);
|
||||
|
||||
await this.moderationLogService.log(me, 'addRelay', {
|
||||
inbox: ps.inbox,
|
||||
|
|
|
|||
|
|
@ -173,6 +173,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
case '09d79f9e-64f1-4316-9cfa-e75c4d091574':
|
||||
throw new ApiError(meta.errors.federationNotAllowed);
|
||||
case '72180409-793c-4973-868e-5a118eb5519b':
|
||||
case 'd09dc850-b76c-4f45-875a-7389339d78b8':
|
||||
case 'dc110060-a5f2-461d-808b-39c62702ca64':
|
||||
case '45793ab7-7648-4886-b503-429f8a0d0f73':
|
||||
case '4bf8f36b-4d33-4ac9-ad76-63fa11f354e9':
|
||||
throw new ApiError(meta.errors.responseInvalid);
|
||||
|
||||
// resolveLocal
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
|
|||
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||
import { DriveService } from '@/core/DriveService.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { ApiLoggerService } from '@/server/api/ApiLoggerService.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import { ApiError } from '../../../error.js';
|
||||
import { MiMeta } from '@/models/_.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
|
@ -95,6 +97,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
private driveFileEntityService: DriveFileEntityService,
|
||||
private driveService: DriveService,
|
||||
private readonly apiLoggerService: ApiLoggerService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me, _, file, cleanup, ip, headers) => {
|
||||
// Get 'name' parameter
|
||||
|
|
@ -130,14 +133,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
return await this.driveFileEntityService.pack(driveFile, { self: true });
|
||||
} catch (err) {
|
||||
if (err instanceof Error || typeof err === 'string') {
|
||||
console.error(err);
|
||||
this.apiLoggerService.logger.error(`Error saving drive file: ${renderInlineError(err)}`);
|
||||
}
|
||||
if (err instanceof IdentifiableError) {
|
||||
if (err.id === '282f77bf-5816-4f72-9264-aa14d8261a21') throw new ApiError(meta.errors.inappropriate);
|
||||
if (err.id === 'c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6') throw new ApiError(meta.errors.noFreeSpace);
|
||||
if (err.id === 'f9e4e5f3-4df4-40b5-b400-f236945f7073') throw new ApiError(meta.errors.maxFileSizeExceeded);
|
||||
}
|
||||
throw new ApiError();
|
||||
throw err;
|
||||
} finally {
|
||||
cleanup!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
))).filter(x => x != null);
|
||||
|
||||
if (files.length === 0) {
|
||||
throw new Error();
|
||||
throw new Error('no files specified');
|
||||
}
|
||||
|
||||
const post = await this.galleryPostsRepository.insertOne(new MiGalleryPost({
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
))).filter(x => x != null);
|
||||
|
||||
if (files.length === 0) {
|
||||
throw new Error();
|
||||
throw new Error('no files');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
try {
|
||||
await this.userAuthService.twoFactorAuthenticate(profile, token);
|
||||
} catch (e) {
|
||||
throw new Error('authentication failed');
|
||||
throw new Error('authentication failed', { cause: e });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { ApiLoggerService } from '@/server/api/ApiLoggerService.js';
|
|||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import * as Acct from '@/misc/acct.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { MiMeta } from '@/models/_.js';
|
||||
|
|
@ -105,7 +105,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
const { username, host } = Acct.parse(ps.moveToAccount);
|
||||
// retrieve the destination account
|
||||
let moveTo = await this.remoteUserResolveService.resolveUser(username, host).catch((e) => {
|
||||
this.apiLoggerService.logger.warn(`failed to resolve remote user: ${e}`);
|
||||
this.apiLoggerService.logger.warn(`failed to resolve remote user: ${renderInlineError(e)}`);
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
});
|
||||
const destination = await this.getterService.getUser(moveTo.id) as MiLocalUser | MiRemoteUser;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import { verifyFieldLinks } from '@/misc/verify-field-link.js';
|
|||
import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
|
||||
import { notificationRecieveConfig } from '@/models/json-schema/user.js';
|
||||
import { userUnsignedFetchOptions } from '@/const.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import { ApiLoggerService } from '../../ApiLoggerService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
|
|
@ -516,7 +517,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
// Retrieve the old account
|
||||
const knownAs = await this.remoteUserResolveService.resolveUser(username, host).catch((e) => {
|
||||
this.apiLoggerService.logger.warn(`failed to resolve dstination user: ${e}`);
|
||||
this.apiLoggerService.logger.warn(`failed to resolve destination user: ${renderInlineError(e)}`);
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
});
|
||||
if (knownAs.id === _user.id) throw new ApiError(meta.errors.forbiddenToSetYourself);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import PerUserPvChart from '@/core/chart/charts/per-user-pv.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { renderInlineError } from '@/misc/render-inline-error.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { ApiLoggerService } from '../../ApiLoggerService.js';
|
||||
import type { FindOptionsWhere } from 'typeorm';
|
||||
|
|
@ -131,7 +132,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
// Lookup user
|
||||
if (typeof ps.host === 'string' && typeof ps.username === 'string') {
|
||||
user = await this.remoteUserResolveService.resolveUser(ps.username, ps.host).catch(err => {
|
||||
this.apiLoggerService.logger.warn(`failed to resolve remote user: ${err}`);
|
||||
this.apiLoggerService.logger.warn(`failed to resolve remote user: ${renderInlineError(err)}`);
|
||||
throw new ApiError(meta.errors.failedToResolveRemoteUser);
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue