revert 44ff9f39: pass access token through API to enforce rank

This commit is contained in:
Hazelnoot 2025-06-22 14:54:08 -04:00
parent d7a629e178
commit 7f547a8c10
166 changed files with 377 additions and 472 deletions

View file

@ -16,7 +16,7 @@ import { ChatEntityService } from '@/core/entities/ChatEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { PushNotificationService } from '@/core/PushNotificationService.js';
import { bindThis } from '@/decorators.js';
import type { ChatApprovalsRepository, ChatMessagesRepository, ChatRoomInvitationsRepository, ChatRoomMembershipsRepository, ChatRoomsRepository, MiAccessToken, MiChatMessage, MiChatRoom, MiChatRoomMembership, MiDriveFile, MiUser, MutingsRepository, UsersRepository } from '@/models/_.js';
import type { ChatApprovalsRepository, ChatMessagesRepository, ChatRoomInvitationsRepository, ChatRoomMembershipsRepository, ChatRoomsRepository, MiChatMessage, MiChatRoom, MiChatRoomMembership, MiDriveFile, MiUser, MutingsRepository, UsersRepository } from '@/models/_.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { QueryService } from '@/core/QueryService.js';
import { RoleService } from '@/core/RoleService.js';
@ -342,11 +342,11 @@ export class ChatService {
}
@bindThis
public async hasPermissionToViewRoomTimeline(meId: MiUser['id'], room: MiChatRoom, token?: MiAccessToken | null) {
public async hasPermissionToViewRoomTimeline(meId: MiUser['id'], room: MiChatRoom) {
if (await this.isRoomMember(room, meId)) {
return true;
} else {
const iAmModerator = await this.roleService.isModerator({ id: meId }, token);
const iAmModerator = await this.roleService.isModerator({ id: meId });
if (iAmModerator) {
return true;
}
@ -563,12 +563,12 @@ export class ChatService {
}
@bindThis
public async hasPermissionToDeleteRoom(meId: MiUser['id'], room: MiChatRoom, token?: MiAccessToken | null) {
public async hasPermissionToDeleteRoom(meId: MiUser['id'], room: MiChatRoom) {
if (room.ownerId === meId) {
return true;
}
const iAmModerator = await this.roleService.isModerator({ id: meId }, token);
const iAmModerator = await this.roleService.isModerator({ id: meId });
if (iAmModerator) {
return true;
}

View file

@ -10,7 +10,7 @@ import type { MiUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js';
import type { MiMeta } from '@/models/Meta.js';
import { Packed } from '@/misc/json-schema.js';
import type { MiAccessToken, NotesRepository } from '@/models/_.js';
import type { NotesRepository } from '@/models/_.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { UtilityService } from '@/core/UtilityService.js';
@ -28,7 +28,6 @@ type TimelineOptions = {
limit: number,
allowPartial: boolean,
me?: { id: MiUser['id'] } | undefined | null,
token?: MiAccessToken | null,
useDbFallback: boolean,
redisTimelines: FanoutTimelineName[],
noteFilter?: (note: MiNote) => boolean,
@ -65,7 +64,7 @@ export class FanoutTimelineEndpointService {
@bindThis
async timeline(ps: TimelineOptions): Promise<Packed<'Note'>[]> {
return await this.noteEntityService.packMany(await this.getMiNotes(ps), ps.me, ps.token);
return await this.noteEntityService.packMany(await this.getMiNotes(ps), ps.me);
}
@bindThis

View file

@ -650,7 +650,7 @@ export class NoteCreateService implements OnApplicationShutdown {
if (this.userEntityService.isLocalUser(user)) this.activeUsersChart.write(user);
// Pack the note
const noteObj = await this.noteEntityService.pack(note, null, null, { skipHide: true, withReactionAndUserPairCache: true });
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
this.globalEventService.publishNotesStream(noteObj);
@ -856,7 +856,7 @@ export class NoteCreateService implements OnApplicationShutdown {
continue;
}
const detailPackedNote = await this.noteEntityService.pack(note, u, null, {
const detailPackedNote = await this.noteEntityService.pack(note, u, {
detail: true,
});

View file

@ -618,7 +618,7 @@ export class NoteEditService implements OnApplicationShutdown {
if (this.userEntityService.isLocalUser(user)) this.activeUsersChart.write(user);
// Pack the note
const noteObj = await this.noteEntityService.pack(note, null, null, { skipHide: true, withReactionAndUserPairCache: true });
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
this.globalEventService.publishNoteStream(note.id, 'updated', {
cw: note.cw,
text: note.text ?? '',

View file

@ -177,7 +177,7 @@ export class NotificationService implements OnApplicationShutdown {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
} while (true);
const packed = await this.notificationEntityService.pack(notification, notifieeId, undefined, {});
const packed = await this.notificationEntityService.pack(notification, notifieeId, {});
if (packed == null) return null;

View file

@ -8,7 +8,6 @@ import * as Redis from 'ioredis';
import { In } from 'typeorm';
import { ModuleRef } from '@nestjs/core';
import type {
MiAccessToken,
MiMeta,
MiRole,
MiRoleAssignment,
@ -513,16 +512,14 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
}
@bindThis
public async isModerator(user: { id: MiUser['id'] } | null, token?: MiAccessToken | null): Promise<boolean> {
public async isModerator(user: { id: MiUser['id'] } | null): Promise<boolean> {
if (user == null) return false;
if (token?.rank != null && token.rank !== 'admin' && token.rank !== 'mod') return false;
return (this.meta.rootUserId === user.id) || (await this.getUserRoles(user.id)).some(r => r.isModerator || r.isAdministrator);
}
@bindThis
public async isAdministrator(user: { id: MiUser['id'] } | null, token?: MiAccessToken | null): Promise<boolean> {
public async isAdministrator(user: { id: MiUser['id'] } | null): Promise<boolean> {
if (user == null) return false;
if (token?.rank != null && token.rank !== 'admin') return false;
return (this.meta.rootUserId === user.id) || (await this.getUserRoles(user.id)).some(r => r.isAdministrator);
}

View file

@ -6,7 +6,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { Brackets, SelectQueryBuilder } from 'typeorm';
import { DI } from '@/di-symbols.js';
import { type FollowingsRepository, MiAccessToken, MiUser, type MutingsRepository, type UserProfilesRepository, type UsersRepository } from '@/models/_.js';
import { type FollowingsRepository, MiUser, type MutingsRepository, type UserProfilesRepository, type UsersRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
import type { Config } from '@/config.js';
@ -63,7 +63,6 @@ export class UserSearchService {
* @param params .
* @param opts .
* @param me . .
* @param token
* @see {@link UserSearchService#buildSearchUserQueries}
* @see {@link UserSearchService#buildSearchUserNoLoginQueries}
*/
@ -79,7 +78,6 @@ export class UserSearchService {
detail?: boolean,
},
me?: MiUser | null,
token?: MiAccessToken | null,
): Promise<Packed<'User'>[]> {
const queries = me ? this.buildSearchUserQueries(me, params) : this.buildSearchUserNoLoginQueries(params);
@ -102,7 +100,7 @@ export class UserSearchService {
return this.userEntityService.packMany<'UserLite' | 'UserDetailed'>(
[...resultSet].slice(0, limit),
me,
{ schema: opts?.detail ? 'UserDetailed' : 'UserLite', token },
{ schema: opts?.detail ? 'UserDetailed' : 'UserLite' },
);
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { AbuseUserReportsRepository, InstancesRepository, MiAccessToken, MiInstance, MiUser } from '@/models/_.js';
import type { AbuseUserReportsRepository, InstancesRepository, MiInstance, MiUser } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
import { bindThis } from '@/decorators.js';
@ -39,7 +39,6 @@ export class AbuseUserReportEntityService {
packedAssignee?: Packed<'UserDetailedNotMe'>,
},
me?: MiUser | null,
token?: MiAccessToken | null,
) {
const report = typeof src === 'object' ? src : await this.abuseUserReportsRepository.findOneByOrFail({ id: src });
@ -54,24 +53,21 @@ export class AbuseUserReportEntityService {
assigneeId: report.assigneeId,
reporter: hint?.packedReporter ?? this.userEntityService.pack(report.reporter ?? report.reporterId, me, {
schema: 'UserDetailedNotMe',
token,
}),
targetUser: hint?.packedTargetUser ?? this.userEntityService.pack(report.targetUser ?? report.targetUserId, me, {
schema: 'UserDetailedNotMe',
token,
}),
// return hint, or pack by relation, or fetch and pack by id, or null
targetInstance: hint?.packedTargetInstance ?? (
report.targetUserInstance
? this.instanceEntityService.pack(report.targetUserInstance, me, token)
? this.instanceEntityService.pack(report.targetUserInstance, me)
: report.targetUserHost
? this.instancesRepository.findOneBy({ host: report.targetUserHost }).then(instance => instance
? this.instanceEntityService.pack(instance, me, token)
? this.instanceEntityService.pack(instance, me)
: null)
: null),
assignee: report.assigneeId ? hint?.packedAssignee ?? this.userEntityService.pack(report.assignee ?? report.assigneeId, me, {
schema: 'UserDetailedNotMe',
token,
}) : null,
forwarded: report.forwarded,
resolvedAs: report.resolvedAs,
@ -83,7 +79,6 @@ export class AbuseUserReportEntityService {
public async packMany(
reports: MiAbuseUserReport[],
me?: MiUser | null,
token?: MiAccessToken | null,
) {
const _reporters = reports.map(({ reporter, reporterId }) => reporter ?? reporterId);
const _targetUsers = reports.map(({ targetUser, targetUserId }) => targetUser ?? targetUserId);
@ -91,12 +86,12 @@ export class AbuseUserReportEntityService {
const _userMap = await this.userEntityService.packMany(
[..._reporters, ..._targetUsers, ..._assignees],
me,
{ schema: 'UserDetailedNotMe', token },
{ schema: 'UserDetailedNotMe' },
).then(users => new Map(users.map(u => [u.id, u])));
const _targetInstances = reports
.map(({ targetUserInstance, targetUserHost }) => targetUserInstance ?? targetUserHost)
.filter((i): i is MiInstance | string => i != null);
const _instanceMap = await this.instanceEntityService.packMany(await this.instanceEntityService.fetchInstancesByHost(_targetInstances), me, token)
const _instanceMap = await this.instanceEntityService.packMany(await this.instanceEntityService.fetchInstancesByHost(_targetInstances), me)
.then(instances => new Map(instances.map(i => [i.host, i])));
return Promise.all(
reports.map(report => {
@ -104,7 +99,7 @@ export class AbuseUserReportEntityService {
const packedTargetUser = _userMap.get(report.targetUserId);
const packedTargetInstance = report.targetUserHost ? _instanceMap.get(report.targetUserHost) : undefined;
const packedAssignee = report.assigneeId != null ? _userMap.get(report.assigneeId) : undefined;
return this.pack(report, { packedReporter, packedTargetUser, packedAssignee, packedTargetInstance }, me, token);
return this.pack(report, { packedReporter, packedTargetUser, packedAssignee, packedTargetInstance }, me);
}),
);
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { BlockingsRepository, MiAccessToken } from '@/models/_.js';
import type { BlockingsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { MiBlocking } from '@/models/Blocking.js';
@ -29,7 +29,6 @@ export class BlockingEntityService {
public async pack(
src: MiBlocking['id'] | MiBlocking,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hint?: {
blockee?: Packed<'UserDetailedNotMe'>,
},
@ -42,7 +41,6 @@ export class BlockingEntityService {
blockeeId: blocking.blockeeId,
blockee: hint?.blockee ?? this.userEntityService.pack(blocking.blockeeId, me, {
schema: 'UserDetailedNotMe',
token,
}),
});
}
@ -51,11 +49,10 @@ export class BlockingEntityService {
public async packMany(
blockings: MiBlocking[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
const _blockees = blockings.map(({ blockee, blockeeId }) => blockee ?? blockeeId);
const _userMap = await this.userEntityService.packMany(_blockees, me, { schema: 'UserDetailedNotMe', token })
const _userMap = await this.userEntityService.packMany(_blockees, me, { schema: 'UserDetailedNotMe' })
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(blockings.map(blocking => this.pack(blocking, me, token, { blockee: _userMap.get(blocking.blockeeId) })));
return Promise.all(blockings.map(blocking => this.pack(blocking, me, { blockee: _userMap.get(blocking.blockeeId) })));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, MiAccessToken, NotesRepository } from '@/models/_.js';
import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, NotesRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
import type { MiUser } from '@/models/User.js';
@ -44,7 +44,6 @@ export class ChannelEntityService {
public async pack(
src: MiChannel['id'] | MiChannel,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
detailed?: boolean,
): Promise<Packed<'Channel'>> {
const channel = typeof src === 'object' ? src : await this.channelsRepository.findOneByOrFail({ id: src });
@ -95,7 +94,7 @@ export class ChannelEntityService {
} : {}),
...(detailed ? {
pinnedNotes: (await this.noteEntityService.packMany(pinnedNotes, me, token)).sort((a, b) => channel.pinnedNoteIds.indexOf(a.id) - channel.pinnedNoteIds.indexOf(b.id)),
pinnedNotes: (await this.noteEntityService.packMany(pinnedNotes, me)).sort((a, b) => channel.pinnedNoteIds.indexOf(a.id) - channel.pinnedNoteIds.indexOf(b.id)),
} : {}),
};
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { ClipNotesRepository, ClipFavoritesRepository, ClipsRepository, MiUser, MiAccessToken } from '@/models/_.js';
import type { ClipNotesRepository, ClipFavoritesRepository, ClipsRepository, MiUser } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
@ -35,7 +35,6 @@ export class ClipEntityService {
public async pack(
src: MiClip['id'] | MiClip,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hint?: {
packedUser?: Packed<'UserLite'>
},
@ -48,7 +47,7 @@ export class ClipEntityService {
createdAt: this.idService.parse(clip.id).date.toISOString(),
lastClippedAt: clip.lastClippedAt ? clip.lastClippedAt.toISOString() : null,
userId: clip.userId,
user: hint?.packedUser ?? this.userEntityService.pack(clip.user ?? clip.userId, me, { token }),
user: hint?.packedUser ?? this.userEntityService.pack(clip.user ?? clip.userId),
name: clip.name,
description: clip.description,
isPublic: clip.isPublic,
@ -62,12 +61,11 @@ export class ClipEntityService {
public async packMany(
clips: MiClip[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const _users = clips.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { token })
const _userMap = await this.userEntityService.packMany(_users, me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(clips.map(clip => this.pack(clip, me, token, { packedUser: _userMap.get(clip.userId) })));
return Promise.all(clips.map(clip => this.pack(clip, me, { packedUser: _userMap.get(clip.userId) })));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { FlashLikesRepository, FlashsRepository, MiAccessToken } from '@/models/_.js';
import type { FlashLikesRepository, FlashsRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import type { MiUser } from '@/models/User.js';
import type { MiFlash } from '@/models/Flash.js';
@ -29,7 +29,6 @@ export class FlashEntityService {
public async pack(
src: MiFlash['id'] | MiFlash,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hint?: {
packedUser?: Packed<'UserLite'>,
likedFlashIds?: MiFlash['id'][],
@ -39,7 +38,7 @@ export class FlashEntityService {
const flash = typeof src === 'object' ? src : await this.flashsRepository.findOneByOrFail({ id: src });
// { schema: 'UserDetailed' } すると無限ループするので注意
const user = hint?.packedUser ?? await this.userEntityService.pack(flash.user ?? flash.userId, me, { token });
const user = hint?.packedUser ?? await this.userEntityService.pack(flash.user ?? flash.userId, me);
let isLiked = undefined;
if (meId) {
@ -67,10 +66,9 @@ export class FlashEntityService {
public async packMany(
flashes: MiFlash[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const _users = flashes.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { token })
const _userMap = await this.userEntityService.packMany(_users, me)
.then(users => new Map(users.map(u => [u.id, u])));
const _likedFlashIds = me
? await this.flashLikesRepository.createQueryBuilder('flashLike')
@ -80,7 +78,7 @@ export class FlashEntityService {
.then(likes => [...new Set(likes.map(like => like.flashLike_flashId))])
: [];
return Promise.all(
flashes.map(flash => this.pack(flash, me, token, {
flashes.map(flash => this.pack(flash, me, {
packedUser: _userMap.get(flash.userId),
likedFlashIds: _likedFlashIds,
})),

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { FlashLikesRepository, MiAccessToken } from '@/models/_.js';
import type { FlashLikesRepository } from '@/models/_.js';
import type { } from '@/models/Blocking.js';
import type { MiUser } from '@/models/User.js';
import type { MiFlashLike } from '@/models/FlashLike.js';
@ -26,13 +26,12 @@ export class FlashLikeEntityService {
public async pack(
src: MiFlashLike['id'] | MiFlashLike,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const like = typeof src === 'object' ? src : await this.flashLikesRepository.findOneByOrFail({ id: src });
return {
id: like.id,
flash: await this.flashEntityService.pack(like.flash ?? like.flashId, me, token),
flash: await this.flashEntityService.pack(like.flash ?? like.flashId, me),
};
}
@ -40,9 +39,8 @@ export class FlashLikeEntityService {
public packMany(
likes: any[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
return Promise.all(likes.map(x => this.pack(x, me, token)));
return Promise.all(likes.map(x => this.pack(x, me)));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { FollowRequestsRepository, MiAccessToken } from '@/models/_.js';
import type { FollowRequestsRepository } from '@/models/_.js';
import type { } from '@/models/Blocking.js';
import type { MiUser } from '@/models/User.js';
import type { MiFollowRequest } from '@/models/FollowRequest.js';
@ -27,7 +27,6 @@ export class FollowRequestEntityService {
public async pack(
src: MiFollowRequest['id'] | MiFollowRequest,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hint?: {
packedFollower?: Packed<'UserLite'>,
packedFollowee?: Packed<'UserLite'>,
@ -37,8 +36,8 @@ export class FollowRequestEntityService {
return {
id: request.id,
follower: hint?.packedFollower ?? await this.userEntityService.pack(request.followerId, me, { token }),
followee: hint?.packedFollowee ?? await this.userEntityService.pack(request.followeeId, me, { token }),
follower: hint?.packedFollower ?? await this.userEntityService.pack(request.followerId, me),
followee: hint?.packedFollowee ?? await this.userEntityService.pack(request.followeeId, me),
};
}
@ -46,17 +45,16 @@ export class FollowRequestEntityService {
public async packMany(
requests: MiFollowRequest[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const _followers = requests.map(({ follower, followerId }) => follower ?? followerId);
const _followees = requests.map(({ followee, followeeId }) => followee ?? followeeId);
const _userMap = await this.userEntityService.packMany([..._followers, ..._followees], me, { token })
const _userMap = await this.userEntityService.packMany([..._followers, ..._followees], me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(
requests.map(req => {
const packedFollower = _userMap.get(req.followerId);
const packedFollowee = _userMap.get(req.followeeId);
return this.pack(req, me, token, { packedFollower, packedFollowee });
return this.pack(req, me, { packedFollower, packedFollowee });
}),
);
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { FollowingsRepository, MiAccessToken } from '@/models/_.js';
import type { FollowingsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import { MiBlocking } from '@/models/Blocking.js';
@ -76,23 +76,23 @@ export class FollowingEntityService {
}
@bindThis
public async getFollowing(me: MiLocalUser, token: MiAccessToken | null | undefined, params: FollowsQueryParams) {
return await this.getFollows(me, token, params, 'following.followerHost = :host');
public async getFollowing(me: MiLocalUser, params: FollowsQueryParams) {
return await this.getFollows(me, params, 'following.followerHost = :host');
}
@bindThis
public async getFollowers(me: MiLocalUser, token: MiAccessToken | null | undefined, params: FollowsQueryParams) {
return await this.getFollows(me, token, params, 'following.followeeHost = :host');
public async getFollowers(me: MiLocalUser, params: FollowsQueryParams) {
return await this.getFollows(me, params, 'following.followeeHost = :host');
}
private async getFollows(me: MiLocalUser, token: MiAccessToken | null | undefined, params: FollowsQueryParams, condition: string) {
private async getFollows(me: MiLocalUser, params: FollowsQueryParams, condition: string) {
const builder = this.followingsRepository.createQueryBuilder('following');
const query = this.queryService
.makePaginationQuery(builder, params.sinceId, params.untilId)
.andWhere(condition, { host: params.host })
.limit(params.limit);
if (!await this.roleService.isModerator(me, token)) {
if (!await this.roleService.isModerator(me)) {
query.setParameter('me', me.id);
// Make sure that the followee doesn't block us, if their profile will be included.
@ -119,14 +119,13 @@ export class FollowingEntityService {
}
const followings = await query.getMany();
return await this.packMany(followings, me, token, { populateFollowee: params.includeFollowee, populateFollower: params.includeFollower });
return await this.packMany(followings, me, { populateFollowee: params.includeFollowee, populateFollower: params.includeFollower });
}
@bindThis
public async pack(
src: MiFollowing['id'] | MiFollowing,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
opts?: {
populateFollowee?: boolean;
populateFollower?: boolean;
@ -147,11 +146,9 @@ export class FollowingEntityService {
followerId: following.followerId,
followee: opts.populateFollowee ? hint?.packedFollowee ?? this.userEntityService.pack(following.followee ?? following.followeeId, me, {
schema: 'UserDetailedNotMe',
token,
}) : undefined,
follower: opts.populateFollower ? hint?.packedFollower ?? this.userEntityService.pack(following.follower ?? following.followerId, me, {
schema: 'UserDetailedNotMe',
token,
}) : undefined,
});
}
@ -160,7 +157,6 @@ export class FollowingEntityService {
public async packMany(
followings: MiFollowing[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
opts?: {
populateFollowee?: boolean;
populateFollower?: boolean;
@ -168,13 +164,13 @@ export class FollowingEntityService {
) {
const _followees = opts?.populateFollowee ? followings.map(({ followee, followeeId }) => followee ?? followeeId) : [];
const _followers = opts?.populateFollower ? followings.map(({ follower, followerId }) => follower ?? followerId) : [];
const _userMap = await this.userEntityService.packMany([..._followees, ..._followers], me, { schema: 'UserDetailedNotMe', token })
const _userMap = await this.userEntityService.packMany([..._followees, ..._followers], me, { schema: 'UserDetailedNotMe' })
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(
followings.map(following => {
const packedFollowee = opts?.populateFollowee ? _userMap.get(following.followeeId) : undefined;
const packedFollower = opts?.populateFollower ? _userMap.get(following.followerId) : undefined;
return this.pack(following, me, token, opts, { packedFollowee, packedFollower });
return this.pack(following, me, opts, { packedFollowee, packedFollower });
}),
);
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { GalleryLikesRepository, MiAccessToken } from '@/models/_.js';
import type { GalleryLikesRepository } from '@/models/_.js';
import type { } from '@/models/Blocking.js';
import type { MiGalleryLike } from '@/models/GalleryLike.js';
import { bindThis } from '@/decorators.js';
@ -25,13 +25,12 @@ export class GalleryLikeEntityService {
public async pack(
src: MiGalleryLike['id'] | MiGalleryLike,
me?: any,
token?: MiAccessToken | null,
) {
const like = typeof src === 'object' ? src : await this.galleryLikesRepository.findOneByOrFail({ id: src });
return {
id: like.id,
post: await this.galleryPostEntityService.pack(like.post ?? like.postId, me, token),
post: await this.galleryPostEntityService.pack(like.post ?? like.postId, me),
};
}
@ -39,9 +38,8 @@ export class GalleryLikeEntityService {
public packMany(
likes: any[],
me: any,
token?: MiAccessToken | null,
) {
return Promise.all(likes.map(x => this.pack(x, me, token)));
return Promise.all(likes.map(x => this.pack(x, me)));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { GalleryLikesRepository, GalleryPostsRepository, MiAccessToken } from '@/models/_.js';
import type { GalleryLikesRepository, GalleryPostsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
@ -35,7 +35,6 @@ export class GalleryPostEntityService {
public async pack(
src: MiGalleryPost['id'] | MiGalleryPost,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hint?: {
packedUser?: Packed<'UserLite'>
},
@ -48,7 +47,7 @@ export class GalleryPostEntityService {
createdAt: this.idService.parse(post.id).date.toISOString(),
updatedAt: post.updatedAt.toISOString(),
userId: post.userId,
user: hint?.packedUser ?? this.userEntityService.pack(post.user ?? post.userId, me, { token }),
user: hint?.packedUser ?? this.userEntityService.pack(post.user ?? post.userId, me),
title: post.title,
description: post.description,
fileIds: post.fileIds,
@ -65,12 +64,11 @@ export class GalleryPostEntityService {
public async packMany(
posts: MiGalleryPost[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const _users = posts.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { token })
const _userMap = await this.userEntityService.packMany(_users, me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(posts.map(post => this.pack(post, me, token, { packedUser: _userMap.get(post.userId) })));
return Promise.all(posts.map(post => this.pack(post, me, { packedUser: _userMap.get(post.userId) })));
}
}

View file

@ -12,7 +12,7 @@ import { UtilityService } from '@/core/UtilityService.js';
import { RoleService } from '@/core/RoleService.js';
import { MiUser } from '@/models/User.js';
import { DI } from '@/di-symbols.js';
import type { InstancesRepository, MiAccessToken, MiMeta } from '@/models/_.js';
import type { InstancesRepository, MiMeta } from '@/models/_.js';
@Injectable()
export class InstanceEntityService {
@ -33,9 +33,8 @@ export class InstanceEntityService {
public async pack(
instance: MiInstance,
me?: { id: MiUser['id']; } | null | undefined,
token?: MiAccessToken | null,
): Promise<Packed<'FederationInstance'>> {
const iAmModerator = me ? await this.roleService.isModerator(me as MiUser, token) : false;
const iAmModerator = me ? await this.roleService.isModerator(me as MiUser) : false;
const softwareSuspended = this.utilityService.isDeliverSuspendedSoftware(instance);
return {
@ -76,9 +75,8 @@ export class InstanceEntityService {
public packMany(
instances: MiInstance[],
me?: { id: MiUser['id']; } | null | undefined,
token?: MiAccessToken | null,
) {
return Promise.all(instances.map(x => this.pack(x, me, token)));
return Promise.all(instances.map(x => this.pack(x, me)));
}
@bindThis

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, RegistrationTicketsRepository } from '@/models/_.js';
import type { RegistrationTicketsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { MiUser } from '@/models/User.js';
@ -29,7 +29,6 @@ export class InviteCodeEntityService {
public async pack(
src: MiRegistrationTicket['id'] | MiRegistrationTicket,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hints?: {
packedCreatedBy?: Packed<'UserLite'>,
packedUsedBy?: Packed<'UserLite'>,
@ -47,8 +46,8 @@ export class InviteCodeEntityService {
code: target.code,
expiresAt: target.expiresAt ? target.expiresAt.toISOString() : null,
createdAt: this.idService.parse(target.id).date.toISOString(),
createdBy: target.createdBy ? hints?.packedCreatedBy ?? await this.userEntityService.pack(target.createdBy, me, { token }) : null,
usedBy: target.usedBy ? hints?.packedUsedBy ?? await this.userEntityService.pack(target.usedBy, me, { token }) : null,
createdBy: target.createdBy ? hints?.packedCreatedBy ?? await this.userEntityService.pack(target.createdBy, me) : null,
usedBy: target.usedBy ? hints?.packedUsedBy ?? await this.userEntityService.pack(target.usedBy, me) : null,
usedAt: target.usedAt ? target.usedAt.toISOString() : null,
used: !!target.usedAt,
});
@ -58,17 +57,16 @@ export class InviteCodeEntityService {
public async packMany(
tickets: MiRegistrationTicket[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
const _createdBys = tickets.map(({ createdBy, createdById }) => createdBy ?? createdById).filter(x => x != null);
const _usedBys = tickets.map(({ usedBy, usedById }) => usedBy ?? usedById).filter(x => x != null);
const _userMap = await this.userEntityService.packMany([..._createdBys, ..._usedBys], me, { token })
const _userMap = await this.userEntityService.packMany([..._createdBys, ..._usedBys], me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(
tickets.map(ticket => {
const packedCreatedBy = ticket.createdById != null ? _userMap.get(ticket.createdById) : undefined;
const packedUsedBy = ticket.usedById != null ? _userMap.get(ticket.usedById) : undefined;
return this.pack(ticket, me, token, { packedCreatedBy, packedUsedBy });
return this.pack(ticket, me, { packedCreatedBy, packedUsedBy });
}),
);
}

View file

@ -5,14 +5,13 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, ModerationLogsRepository } from '@/models/_.js';
import type { ModerationLogsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { } from '@/models/Blocking.js';
import { MiModerationLog } from '@/models/ModerationLog.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
import type { Packed } from '@/misc/json-schema.js';
import type { MiLocalUser } from '@/models/User.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
@ -29,8 +28,6 @@ export class ModerationLogEntityService {
@bindThis
public async pack(
src: MiModerationLog['id'] | MiModerationLog,
me?: MiLocalUser,
token?: MiAccessToken | null,
hint?: {
packedUser?: Packed<'UserDetailedNotMe'>,
},
@ -43,9 +40,8 @@ export class ModerationLogEntityService {
type: log.type,
info: log.info,
userId: log.userId,
user: hint?.packedUser ?? this.userEntityService.pack(log.user ?? log.userId, me, {
user: hint?.packedUser ?? this.userEntityService.pack(log.user ?? log.userId, null, {
schema: 'UserDetailedNotMe',
token,
}),
});
}
@ -53,13 +49,11 @@ export class ModerationLogEntityService {
@bindThis
public async packMany(
reports: MiModerationLog[],
me?: MiLocalUser,
token?: MiAccessToken | null,
) {
const _users = reports.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailedNotMe', token })
const _userMap = await this.userEntityService.packMany(_users, null, { schema: 'UserDetailedNotMe' })
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(reports.map(report => this.pack(report, me, token, { packedUser: _userMap.get(report.userId) })));
return Promise.all(reports.map(report => this.pack(report, { packedUser: _userMap.get(report.userId) })));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, MutingsRepository } from '@/models/_.js';
import type { MutingsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
@ -30,7 +30,6 @@ export class MutingEntityService {
public async pack(
src: MiMuting['id'] | MiMuting,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hints?: {
packedMutee?: Packed<'UserDetailedNotMe'>,
},
@ -44,7 +43,6 @@ export class MutingEntityService {
muteeId: muting.muteeId,
mutee: hints?.packedMutee ?? this.userEntityService.pack(muting.muteeId, me, {
schema: 'UserDetailedNotMe',
token,
}),
});
}
@ -53,12 +51,11 @@ export class MutingEntityService {
public async packMany(
mutings: MiMuting[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
const _mutees = mutings.map(({ mutee, muteeId }) => mutee ?? muteeId);
const _userMap = await this.userEntityService.packMany(_mutees, me, { schema: 'UserDetailedNotMe', token })
const _userMap = await this.userEntityService.packMany(_mutees, me, { schema: 'UserDetailedNotMe' })
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(mutings.map(muting => this.pack(muting, me, token, { packedMutee: _userMap.get(muting.muteeId) })));
return Promise.all(mutings.map(muting => this.pack(muting, me, { packedMutee: _userMap.get(muting.muteeId) })));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, NoteFavoritesRepository } from '@/models/_.js';
import type { NoteFavoritesRepository } from '@/models/_.js';
import type { } from '@/models/Blocking.js';
import type { MiUser } from '@/models/User.js';
import type { MiNoteFavorite } from '@/models/NoteFavorite.js';
@ -28,7 +28,6 @@ export class NoteFavoriteEntityService {
public async pack(
src: MiNoteFavorite['id'] | MiNoteFavorite,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const favorite = typeof src === 'object' ? src : await this.noteFavoritesRepository.findOneByOrFail({ id: src });
@ -36,7 +35,7 @@ export class NoteFavoriteEntityService {
id: favorite.id,
createdAt: this.idService.parse(favorite.id).date.toISOString(),
noteId: favorite.noteId,
note: await this.noteEntityService.pack(favorite.note ?? favorite.noteId, me, token),
note: await this.noteEntityService.pack(favorite.note ?? favorite.noteId, me),
};
}
@ -44,8 +43,7 @@ export class NoteFavoriteEntityService {
public packMany(
favorites: any[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
return Promise.all(favorites.map(x => this.pack(x, me, token)));
return Promise.all(favorites.map(x => this.pack(x, me)));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, NoteReactionsRepository } from '@/models/_.js';
import type { NoteReactionsRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
@ -49,7 +49,6 @@ export class NoteReactionEntityService implements OnModuleInit {
public async pack(
src: MiNoteReaction['id'] | MiNoteReaction,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
options?: {
withNote: boolean;
},
@ -66,10 +65,10 @@ export class NoteReactionEntityService implements OnModuleInit {
return {
id: reaction.id,
createdAt: this.idService.parse(reaction.id).date.toISOString(),
user: hints?.packedUser ?? await this.userEntityService.pack(reaction.user ?? reaction.userId, me, { token }),
user: hints?.packedUser ?? await this.userEntityService.pack(reaction.user ?? reaction.userId, me),
type: this.reactionService.convertLegacyReaction(reaction.reaction),
...(opts.withNote ? {
note: await this.noteEntityService.pack(reaction.note ?? reaction.noteId, me, token),
note: await this.noteEntityService.pack(reaction.note ?? reaction.noteId, me),
} : {}),
};
}
@ -78,7 +77,6 @@ export class NoteReactionEntityService implements OnModuleInit {
public async packMany(
reactions: MiNoteReaction[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
options?: {
withNote: boolean;
},
@ -87,8 +85,8 @@ export class NoteReactionEntityService implements OnModuleInit {
withNote: false,
}, options);
const _users = reactions.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { token })
const _userMap = await this.userEntityService.packMany(_users, me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(reactions.map(reaction => this.pack(reaction, me, token, opts, { packedUser: _userMap.get(reaction.userId) })));
return Promise.all(reactions.map(reaction => this.pack(reaction, me, opts, { packedUser: _userMap.get(reaction.userId) })));
}
}

View file

@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { In, EntityNotFoundError } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { FollowRequestsRepository, NotesRepository, MiUser, UsersRepository, MiAccessToken, AccessTokensRepository } from '@/models/_.js';
import type { FollowRequestsRepository, NotesRepository, MiUser, UsersRepository, AccessTokensRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { MiGroupedNotification, MiNotification } from '@/models/Notification.js';
import type { MiNote } from '@/models/Note.js';
@ -69,7 +69,6 @@ export class NotificationEntityService implements OnModuleInit {
async #packInternal <T extends MiNotification | MiGroupedNotification> (
src: T,
meId: MiUser['id'],
token: MiAccessToken | null | undefined,
options: {
checkValidNotifier?: boolean;
},
@ -86,7 +85,7 @@ export class NotificationEntityService implements OnModuleInit {
const noteIfNeed = needsNote ? (
hint?.packedNotes != null
? hint.packedNotes.get(notification.noteId)
: undefOnMissing(this.noteEntityService.pack(notification.noteId, { id: meId }, token, {
: undefOnMissing(this.noteEntityService.pack(notification.noteId, { id: meId }, {
detail: true,
}))
) : undefined;
@ -97,7 +96,7 @@ export class NotificationEntityService implements OnModuleInit {
const userIfNeed = needsUser ? (
hint?.packedUsers != null
? hint.packedUsers.get(notification.notifierId)
: undefOnMissing(this.userEntityService.pack(notification.notifierId, { id: meId }, { token }))
: undefOnMissing(this.userEntityService.pack(notification.notifierId, { id: meId }))
) : undefined;
// if the user has been deleted, don't show this notification
if (needsUser && !userIfNeed) return null;
@ -107,7 +106,7 @@ export class NotificationEntityService implements OnModuleInit {
const reactions = (await Promise.all(notification.reactions.map(async reaction => {
const user = hint?.packedUsers != null
? hint.packedUsers.get(reaction.userId)!
: await undefOnMissing(this.userEntityService.pack(reaction.userId, { id: meId }, { token }));
: await undefOnMissing(this.userEntityService.pack(reaction.userId, { id: meId }));
return {
user,
reaction: reaction.reaction,
@ -132,7 +131,7 @@ export class NotificationEntityService implements OnModuleInit {
return packedUser;
}
return undefOnMissing(this.userEntityService.pack(userId, { id: meId }, { token }));
return undefOnMissing(this.userEntityService.pack(userId, { id: meId }));
}))).filter(x => x != null);
// if all users have been deleted, don't show this notification
if (users.length === 0) {
@ -213,7 +212,6 @@ export class NotificationEntityService implements OnModuleInit {
async #packManyInternal <T extends MiNotification | MiGroupedNotification> (
notifications: T[],
meId: MiUser['id'],
token?: MiAccessToken | null,
): Promise<T[]> {
if (notifications.length === 0) return [];
@ -226,7 +224,7 @@ export class NotificationEntityService implements OnModuleInit {
where: { id: In(noteIds) },
relations: ['user', 'reply', 'reply.user', 'renote', 'renote.user'],
}) : [];
const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, token, {
const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, {
detail: true,
});
const packedNotes = new Map(packedNotesArray.map(p => [p.id, p]));
@ -242,7 +240,7 @@ export class NotificationEntityService implements OnModuleInit {
const users = userIds.length > 0 ? await this.usersRepository.find({
where: { id: In(userIds) },
}) : [];
const packedUsersArray = await this.userEntityService.packMany(users, { id: meId }, { token });
const packedUsersArray = await this.userEntityService.packMany(users, { id: meId });
const packedUsers = new Map(packedUsersArray.map(p => [p.id, p]));
// 既に解決されたフォローリクエストの通知を除外
@ -258,7 +256,6 @@ export class NotificationEntityService implements OnModuleInit {
return this.pack(
x,
meId,
token,
{ checkValidNotifier: false },
{ packedNotes, packedUsers },
);
@ -271,7 +268,6 @@ export class NotificationEntityService implements OnModuleInit {
public async pack(
src: MiNotification | MiGroupedNotification,
meId: MiUser['id'],
token: MiAccessToken | null | undefined,
options: {
checkValidNotifier?: boolean;
@ -281,25 +277,23 @@ export class NotificationEntityService implements OnModuleInit {
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
},
): Promise<Packed<'Notification'> | null> {
return await this.#packInternal(src, meId, token, options, hint);
return await this.#packInternal(src, meId, options, hint);
}
@bindThis
public async packMany(
notifications: MiNotification[],
meId: MiUser['id'],
token?: MiAccessToken | null,
): Promise<MiNotification[]> {
return await this.#packManyInternal(notifications, meId, token);
return await this.#packManyInternal(notifications, meId);
}
@bindThis
public async packGroupedMany(
notifications: MiGroupedNotification[],
meId: MiUser['id'],
token?: MiAccessToken | null,
): Promise<MiGroupedNotification[]> {
return await this.#packManyInternal(notifications, meId, token);
return await this.#packManyInternal(notifications, meId);
}
/**

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { DriveFilesRepository, PagesRepository, PageLikesRepository, MiAccessToken } from '@/models/_.js';
import type { DriveFilesRepository, PagesRepository, PageLikesRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
@ -39,7 +39,6 @@ export class PageEntityService {
public async pack(
src: MiPage['id'] | MiPage,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hint?: {
packedUser?: Packed<'UserLite'>
},
@ -94,7 +93,7 @@ export class PageEntityService {
createdAt: this.idService.parse(page.id).date.toISOString(),
updatedAt: page.updatedAt.toISOString(),
userId: page.userId,
user: hint?.packedUser ?? this.userEntityService.pack(page.user ?? page.userId, me, { token }), // { schema: 'UserDetailed' } すると無限ループするので注意
user: hint?.packedUser ?? this.userEntityService.pack(page.user ?? page.userId, me), // { schema: 'UserDetailed' } すると無限ループするので注意
content: page.content,
variables: page.variables,
title: page.title,
@ -116,12 +115,11 @@ export class PageEntityService {
public async packMany(
pages: MiPage[],
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const _users = pages.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { token })
const _userMap = await this.userEntityService.packMany(_users, me)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(pages.map(page => this.pack(page, me, token, { packedUser: _userMap.get(page.userId) })));
return Promise.all(pages.map(page => this.pack(page, me, { packedUser: _userMap.get(page.userId) })));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, PageLikesRepository } from '@/models/_.js';
import type { PageLikesRepository } from '@/models/_.js';
import type { } from '@/models/Blocking.js';
import type { MiUser } from '@/models/User.js';
import type { MiPageLike } from '@/models/PageLike.js';
@ -26,13 +26,12 @@ export class PageLikeEntityService {
public async pack(
src: MiPageLike['id'] | MiPageLike,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
) {
const like = typeof src === 'object' ? src : await this.pageLikesRepository.findOneByOrFail({ id: src });
return {
id: like.id,
page: await this.pageEntityService.pack(like.page ?? like.pageId, me, token),
page: await this.pageEntityService.pack(like.page ?? like.pageId, me),
};
}
@ -40,9 +39,8 @@ export class PageLikeEntityService {
public packMany(
likes: any[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
return Promise.all(likes.map(x => this.pack(x, me, token)));
return Promise.all(likes.map(x => this.pack(x, me)));
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, RenoteMutingsRepository } from '@/models/_.js';
import type { RenoteMutingsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
@ -30,7 +30,6 @@ export class RenoteMutingEntityService {
public async pack(
src: MiRenoteMuting['id'] | MiRenoteMuting,
me?: { id: MiUser['id'] } | null | undefined,
token?: MiAccessToken | null,
hints?: {
packedMutee?: Packed<'UserDetailedNotMe'>
},
@ -43,7 +42,6 @@ export class RenoteMutingEntityService {
muteeId: muting.muteeId,
mutee: hints?.packedMutee ?? this.userEntityService.pack(muting.muteeId, me, {
schema: 'UserDetailedNotMe',
token,
}),
});
}
@ -52,12 +50,11 @@ export class RenoteMutingEntityService {
public async packMany(
mutings: MiRenoteMuting[],
me: { id: MiUser['id'] },
token?: MiAccessToken | null,
) {
const _users = mutings.map(({ mutee, muteeId }) => mutee ?? muteeId);
const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailedNotMe', token })
const _userMap = await this.userEntityService.packMany(_users, me, { schema: 'UserDetailedNotMe' })
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(mutings.map(muting => this.pack(muting, me, token, { packedMutee: _userMap.get(muting.muteeId) })));
return Promise.all(mutings.map(muting => this.pack(muting, me, { packedMutee: _userMap.get(muting.muteeId) })));
}
}

View file

@ -481,8 +481,8 @@ export class UserEntityService implements OnModuleInit {
const isDetailed = opts.schema !== 'UserLite';
const meId = me ? me.id : null;
const isMe = meId === user.id;
const iAmModerator = opts.iAmModerator ?? (me ? await this.roleService.isModerator(me as MiUser, opts.token) : false);
const iAmAdmin = opts.iAmAdmin ?? (me ? await this.roleService.isAdministrator(user, opts.token) : false);
const iAmModerator = opts.iAmModerator ?? (me ? await this.roleService.isModerator(me as MiUser) : false);
const iAmAdmin = opts.iAmAdmin ?? (me ? await this.roleService.isAdministrator(user) : false);
const profile = isDetailed
? (opts.userProfile ?? user.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id }))
@ -629,11 +629,11 @@ export class UserEntityService implements OnModuleInit {
fields: profile!.fields,
verifiedLinks: profile!.verifiedLinks,
pinnedNoteIds: pins.map(pin => pin.noteId),
pinnedNotes: this.noteEntityService.packMany(pins.map(pin => pin.note!), me, opts.token, {
pinnedNotes: this.noteEntityService.packMany(pins.map(pin => pin.note!), me, {
detail: true,
}),
pinnedPageId: profile!.pinnedPageId,
pinnedPage: profile!.pinnedPageId ? this.pageEntityService.pack(profile!.pinnedPageId, me, opts.token) : null,
pinnedPage: profile!.pinnedPageId ? this.pageEntityService.pack(profile!.pinnedPageId, me) : null,
publicReactions: this.isLocalUser(user) ? profile!.publicReactions : false, // https://github.com/misskey-dev/misskey/issues/12964
followersVisibility: profile!.followersVisibility,
followingVisibility: profile!.followingVisibility,
@ -744,15 +744,12 @@ export class UserEntityService implements OnModuleInit {
return await awaitAll(packed);
}
// TODO pass token
public async packMany<S extends 'MeDetailed' | 'UserDetailedNotMe' | 'UserDetailed' | 'UserLite' = 'UserLite'>(
users: (MiUser['id'] | MiUser)[],
me?: { id: MiUser['id'] } | null | undefined,
options?: {
schema?: S,
includeSecrets?: boolean,
token?: MiAccessToken | null,
},
): Promise<Packed<S>[]> {
if (users.length === 0) return [];
@ -775,9 +772,8 @@ export class UserEntityService implements OnModuleInit {
const _userIds = _users.map(u => u.id);
// Sync with ApiCallService
const roles = me ? await this.roleService.getUserRoles(me.id) : [];
const iAmAdmin = roles.some(r => r.isAdministrator) && (options?.token?.rank == null || options?.token.rank === 'admin');
const iAmModerator = roles.some(r => r.isAdministrator || r.isModerator) && (options?.token?.rank == null || options?.token.rank === 'admin' || options?.token.rank === 'mod');
const iAmAdmin = me ? await this.roleService.isAdministrator(me) : false;
const iAmModerator = me ? await this.roleService.isModerator(me) : false;
const meId = me ? me.id : null;
const isDetailed = options && options.schema !== 'UserLite';

View file

@ -5,13 +5,12 @@
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { MiAccessToken, MiUserListMembership, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js';
import type { MiUserListMembership, UserListMembershipsRepository, UserListsRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import type { } from '@/models/Blocking.js';
import type { MiUserList } from '@/models/UserList.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
import type { MiLocalUser } from '@/models/User.js';
import { UserEntityService } from './UserEntityService.js';
@Injectable()
@ -50,17 +49,15 @@ export class UserListEntityService {
@bindThis
public async packMembershipsMany(
memberships: MiUserListMembership[],
me?: MiLocalUser | null,
token?: MiAccessToken | null,
) {
const _users = memberships.map(({ user, userId }) => user ?? userId);
const _userMap = await this.userEntityService.packMany(_users, me, { token })
const _userMap = await this.userEntityService.packMany(_users)
.then(users => new Map(users.map(u => [u.id, u])));
return Promise.all(memberships.map(async x => ({
id: x.id,
createdAt: this.idService.parse(x.id).date.toISOString(),
userId: x.userId,
user: _userMap.get(x.userId) ?? await this.userEntityService.pack(x.userId, me, { token }),
user: _userMap.get(x.userId) ?? await this.userEntityService.pack(x.userId),
withReplies: x.withReplies,
})));
}