From f34f9f6ea583a5455600eea9dbf5ffdf38802d21 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 13 Feb 2023 15:28:07 +0900
Subject: [PATCH] refactor: fix types

---
 packages/backend/src/core/MessagingService.ts |  4 +-
 packages/backend/src/core/PollService.ts      |  5 +-
 packages/backend/src/core/RoleService.ts      |  2 +-
 .../backend/src/core/UserBlockingService.ts   |  4 +-
 packages/backend/src/core/UserCacheService.ts | 24 ++++----
 .../backend/src/core/UserFollowingService.ts  |  4 +-
 .../src/core/activitypub/ApAudienceService.ts | 16 ++---
 .../core/activitypub/ApDbResolverService.ts   | 16 ++---
 .../src/core/activitypub/ApInboxService.ts    | 58 +++++++++----------
 .../core/activitypub/models/ApImageService.ts |  6 +-
 .../activitypub/models/ApMentionService.ts    |  9 ++-
 .../core/activitypub/models/ApNoteService.ts  |  4 +-
 .../activitypub/models/ApPersonService.ts     | 12 ++--
 packages/backend/src/models/entities/User.ts  |  7 +--
 .../queue/processors/InboxProcessorService.ts |  4 +-
 .../backend/src/server/api/ApiCallService.ts  |  4 +-
 .../src/server/api/AuthenticateService.ts     |  4 +-
 .../backend/src/server/api/endpoint-base.ts   |  8 +--
 .../src/server/api/endpoints/ap/show.ts       |  6 +-
 19 files changed, 95 insertions(+), 102 deletions(-)

diff --git a/packages/backend/src/core/MessagingService.ts b/packages/backend/src/core/MessagingService.ts
index 1c36d04d41..0721f63d5e 100644
--- a/packages/backend/src/core/MessagingService.ts
+++ b/packages/backend/src/core/MessagingService.ts
@@ -5,7 +5,7 @@ import type { Config } from '@/config.js';
 import type { DriveFile } from '@/models/entities/DriveFile.js';
 import type { MessagingMessage } from '@/models/entities/MessagingMessage.js';
 import type { Note } from '@/models/entities/Note.js';
-import type { User, CacheableUser, IRemoteUser } from '@/models/entities/User.js';
+import type { User, IRemoteUser } from '@/models/entities/User.js';
 import type { UserGroup } from '@/models/entities/UserGroup.js';
 import { QueueService } from '@/core/QueueService.js';
 import { toArray } from '@/misc/prelude/array.js';
@@ -48,7 +48,7 @@ export class MessagingService {
 	}
 
 	@bindThis
-	public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: CacheableUser | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) {
+	public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: User | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) {
 		const message = {
 			id: this.idService.genId(),
 			createdAt: new Date(),
diff --git a/packages/backend/src/core/PollService.ts b/packages/backend/src/core/PollService.ts
index 018e83f8cd..94adbf2756 100644
--- a/packages/backend/src/core/PollService.ts
+++ b/packages/backend/src/core/PollService.ts
@@ -1,10 +1,9 @@
 import { Inject, Injectable } from '@nestjs/common';
 import { Not } from 'typeorm';
 import { DI } from '@/di-symbols.js';
-import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js';
+import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository, User } from '@/models/index.js';
 import type { Note } from '@/models/entities/Note.js';
 import { RelayService } from '@/core/RelayService.js';
-import type { CacheableUser } from '@/models/entities/User.js';
 import { IdService } from '@/core/IdService.js';
 import { GlobalEventService } from '@/core/GlobalEventService.js';
 import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
@@ -39,7 +38,7 @@ export class PollService {
 	}
 
 	@bindThis
-	public async vote(user: CacheableUser, note: Note, choice: number) {
+	public async vote(user: User, note: Note, choice: number) {
 		const poll = await this.pollsRepository.findOneBy({ noteId: note.id });
 	
 		if (poll == null) throw new Error('poll not found');
diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts
index 9a782780d1..b84d5e7585 100644
--- a/packages/backend/src/core/RoleService.ts
+++ b/packages/backend/src/core/RoleService.ts
@@ -3,7 +3,7 @@ import Redis from 'ioredis';
 import { In } from 'typeorm';
 import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js';
 import { Cache } from '@/misc/cache.js';
-import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js';
+import type { User } from '@/models/entities/User.js';
 import { DI } from '@/di-symbols.js';
 import { bindThis } from '@/decorators.js';
 import { MetaService } from '@/core/MetaService.js';
diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts
index 89de72b9aa..be37bad52e 100644
--- a/packages/backend/src/core/UserBlockingService.ts
+++ b/packages/backend/src/core/UserBlockingService.ts
@@ -2,7 +2,7 @@
 import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
 import Redis from 'ioredis';
 import { IdService } from '@/core/IdService.js';
-import type { CacheableUser, User } from '@/models/entities/User.js';
+import type { User } from '@/models/entities/User.js';
 import type { Blocking } from '@/models/entities/Blocking.js';
 import { QueueService } from '@/core/QueueService.js';
 import { GlobalEventService } from '@/core/GlobalEventService.js';
@@ -236,7 +236,7 @@ export class UserBlockingService implements OnApplicationShutdown {
 	}
 
 	@bindThis
-	public async unblock(blocker: CacheableUser, blockee: CacheableUser) {
+	public async unblock(blocker: User, blockee: User) {
 		const blocking = await this.blockingsRepository.findOneBy({
 			blockerId: blocker.id,
 			blockeeId: blockee.id,
diff --git a/packages/backend/src/core/UserCacheService.ts b/packages/backend/src/core/UserCacheService.ts
index 52cedbd105..5f0a919088 100644
--- a/packages/backend/src/core/UserCacheService.ts
+++ b/packages/backend/src/core/UserCacheService.ts
@@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
 import Redis from 'ioredis';
 import type { UsersRepository } from '@/models/index.js';
 import { Cache } from '@/misc/cache.js';
-import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js';
+import type { ILocalUser, User } from '@/models/entities/User.js';
 import { DI } from '@/di-symbols.js';
 import { UserEntityService } from '@/core/entities/UserEntityService.js';
 import { bindThis } from '@/decorators.js';
@@ -11,10 +11,10 @@ import type { OnApplicationShutdown } from '@nestjs/common';
 
 @Injectable()
 export class UserCacheService implements OnApplicationShutdown {
-	public userByIdCache: Cache<CacheableUser>;
-	public localUserByNativeTokenCache: Cache<CacheableLocalUser | null>;
-	public localUserByIdCache: Cache<CacheableLocalUser>;
-	public uriPersonCache: Cache<CacheableUser | null>;
+	public userByIdCache: Cache<User>;
+	public localUserByNativeTokenCache: Cache<ILocalUser | null>;
+	public localUserByIdCache: Cache<ILocalUser>;
+	public uriPersonCache: Cache<User | null>;
 
 	constructor(
 		@Inject(DI.redisSubscriber)
@@ -27,10 +27,10 @@ export class UserCacheService implements OnApplicationShutdown {
 	) {
 		//this.onMessage = this.onMessage.bind(this);
 
-		this.userByIdCache = new Cache<CacheableUser>(Infinity);
-		this.localUserByNativeTokenCache = new Cache<CacheableLocalUser | null>(Infinity);
-		this.localUserByIdCache = new Cache<CacheableLocalUser>(Infinity);
-		this.uriPersonCache = new Cache<CacheableUser | null>(Infinity);
+		this.userByIdCache = new Cache<User>(Infinity);
+		this.localUserByNativeTokenCache = new Cache<ILocalUser | null>(Infinity);
+		this.localUserByIdCache = new Cache<ILocalUser>(Infinity);
+		this.uriPersonCache = new Cache<User | null>(Infinity);
 
 		this.redisSubscriber.on('message', this.onMessage);
 	}
@@ -45,10 +45,10 @@ export class UserCacheService implements OnApplicationShutdown {
 				case 'userChangeSuspendedState':
 				case 'remoteUserUpdated': {
 					const user = await this.usersRepository.findOneByOrFail({ id: body.id });
-					this.userByIdCache.set(user.id, user as CacheableUser);
+					this.userByIdCache.set(user.id, user);
 					for (const [k, v] of this.uriPersonCache.cache.entries()) {
 						if (v.value?.id === user.id) {
-							this.uriPersonCache.set(k, user as CacheableUser);
+							this.uriPersonCache.set(k, user);
 						}
 					}
 					if (this.userEntityService.isLocalUser(user)) {
@@ -78,7 +78,7 @@ export class UserCacheService implements OnApplicationShutdown {
 
 	@bindThis
 	public findById(userId: User['id']) {
-		return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }) as Promise<CacheableUser>);
+		return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }));
 	}
 
 	@bindThis
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index c0347c60eb..589842a419 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -1,5 +1,5 @@
 import { Inject, Injectable } from '@nestjs/common';
-import type { CacheableUser, ILocalUser, IRemoteUser, User } from '@/models/entities/User.js';
+import type { ILocalUser, IRemoteUser, User } from '@/models/entities/User.js';
 import { IdentifiableError } from '@/misc/identifiable-error.js';
 import { QueueService } from '@/core/QueueService.js';
 import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
@@ -434,7 +434,7 @@ export class UserFollowingService {
 		followee: {
 			id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox'];
 		},
-		follower: User | CacheableUser,
+		follower: User,
 	): Promise<void> {
 		const request = await this.followRequestsRepository.findOneBy({
 			followeeId: followee.id,
diff --git a/packages/backend/src/core/activitypub/ApAudienceService.ts b/packages/backend/src/core/activitypub/ApAudienceService.ts
index 64f01644a7..ee14f4ddd7 100644
--- a/packages/backend/src/core/activitypub/ApAudienceService.ts
+++ b/packages/backend/src/core/activitypub/ApAudienceService.ts
@@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
 import { In } from 'typeorm';
 import promiseLimit from 'promise-limit';
 import { DI } from '@/di-symbols.js';
-import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js';
+import type { IRemoteUser, User } from '@/models/entities/User.js';
 import { concat, toArray, toSingle, unique } from '@/misc/prelude/array.js';
 import { bindThis } from '@/decorators.js';
 import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
@@ -14,8 +14,8 @@ type Visibility = 'public' | 'home' | 'followers' | 'specified';
 
 type AudienceInfo = {
 	visibility: Visibility,
-	mentionedUsers: CacheableUser[],
-	visibleUsers: CacheableUser[],
+	mentionedUsers: User[],
+	visibleUsers: User[],
 };
 
 @Injectable()
@@ -26,16 +26,16 @@ export class ApAudienceService {
 	}
 
 	@bindThis
-	public async parseAudience(actor: CacheableRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise<AudienceInfo> {
+	public async parseAudience(actor: IRemoteUser, to?: ApObject, cc?: ApObject, resolver?: Resolver): Promise<AudienceInfo> {
 		const toGroups = this.groupingAudience(getApIds(to), actor);
 		const ccGroups = this.groupingAudience(getApIds(cc), actor);
 	
 		const others = unique(concat([toGroups.other, ccGroups.other]));
 	
-		const limit = promiseLimit<CacheableUser | null>(2);
+		const limit = promiseLimit<User | null>(2);
 		const mentionedUsers = (await Promise.all(
 			others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))),
-		)).filter((x): x is CacheableUser => x != null);
+		)).filter((x): x is User => x != null);
 	
 		if (toGroups.public.length > 0) {
 			return {
@@ -69,7 +69,7 @@ export class ApAudienceService {
 	}
 	
 	@bindThis
-	private groupingAudience(ids: string[], actor: CacheableRemoteUser) {
+	private groupingAudience(ids: string[], actor: IRemoteUser) {
 		const groups = {
 			public: [] as string[],
 			followers: [] as string[],
@@ -101,7 +101,7 @@ export class ApAudienceService {
 	}
 	
 	@bindThis
-	private isFollowers(id: string, actor: CacheableRemoteUser) {
+	private isFollowers(id: string, actor: IRemoteUser) {
 		return (
 			id === (actor.followersUri ?? `${actor.uri}/followers`)
 		);
diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts
index b057f39b05..5af9e29069 100644
--- a/packages/backend/src/core/activitypub/ApDbResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts
@@ -3,13 +3,13 @@ import escapeRegexp from 'escape-regexp';
 import { DI } from '@/di-symbols.js';
 import type { MessagingMessagesRepository, NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js';
 import type { Config } from '@/config.js';
-import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js';
 import { Cache } from '@/misc/cache.js';
 import type { UserPublickey } from '@/models/entities/UserPublickey.js';
 import { UserCacheService } from '@/core/UserCacheService.js';
 import type { Note } from '@/models/entities/Note.js';
 import type { MessagingMessage } from '@/models/entities/MessagingMessage.js';
 import { bindThis } from '@/decorators.js';
+import { IRemoteUser, User } from '@/models/entities/User.js';
 import { getApId } from './type.js';
 import { ApPersonService } from './models/ApPersonService.js';
 import type { IObject } from './type.js';
@@ -122,7 +122,7 @@ export class ApDbResolverService {
 	 * AP Person => Misskey User in DB
 	 */
 	@bindThis
-	public async getUserFromApId(value: string | IObject): Promise<CacheableUser | null> {
+	public async getUserFromApId(value: string | IObject): Promise<User | null> {
 		const parsed = this.parseUri(value);
 
 		if (parsed.local) {
@@ -130,11 +130,11 @@ export class ApDbResolverService {
 
 			return await this.userCacheService.userByIdCache.fetchMaybe(parsed.id, () => this.usersRepository.findOneBy({
 				id: parsed.id,
-			}).then(x => (x as CacheableUser | null) ?? undefined)) ?? null;
+			}).then(x => x ?? undefined)) ?? null;
 		} else {
 			return await this.userCacheService.uriPersonCache.fetch(parsed.uri, () => this.usersRepository.findOneBy({
 				uri: parsed.uri,
-			}) as Promise<CacheableUser | null>);
+			}));
 		}
 	}
 
@@ -143,7 +143,7 @@ export class ApDbResolverService {
 	 */
 	@bindThis
 	public async getAuthUserFromKeyId(keyId: string): Promise<{
-		user: CacheableRemoteUser;
+		user: IRemoteUser;
 		key: UserPublickey;
 	} | null> {
 		const key = await this.publicKeyCache.fetch(keyId, async () => {
@@ -159,7 +159,7 @@ export class ApDbResolverService {
 		if (key == null) return null;
 
 		return {
-			user: await this.userCacheService.findById(key.userId) as CacheableRemoteUser,
+			user: await this.userCacheService.findById(key.userId) as IRemoteUser,
 			key,
 		};
 	}
@@ -169,10 +169,10 @@ export class ApDbResolverService {
 	 */
 	@bindThis
 	public async getAuthUserFromApId(uri: string): Promise<{
-		user: CacheableRemoteUser;
+		user: IRemoteUser;
 		key: UserPublickey | null;
 	} | null> {
-		const user = await this.apPersonService.resolvePerson(uri) as CacheableRemoteUser;
+		const user = await this.apPersonService.resolvePerson(uri) as IRemoteUser;
 
 		if (user == null) return null;
 
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 02bb0ca4ec..d514e9845e 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common';
 import { In } from 'typeorm';
 import { DI } from '@/di-symbols.js';
 import type { Config } from '@/config.js';
-import type { CacheableRemoteUser, CacheableUser } from '@/models/entities/User.js';
 import { UserFollowingService } from '@/core/UserFollowingService.js';
 import { ReactionService } from '@/core/ReactionService.js';
 import { RelayService } from '@/core/RelayService.js';
@@ -23,6 +22,7 @@ import { QueueService } from '@/core/QueueService.js';
 import { MessagingService } from '@/core/MessagingService.js';
 import type { UsersRepository, NotesRepository, FollowingsRepository, MessagingMessagesRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/index.js';
 import { bindThis } from '@/decorators.js';
+import type { IRemoteUser } from '@/models/entities/User.js';
 import { getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isPost, isRead, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
 import { ApNoteService } from './models/ApNoteService.js';
 import { ApLoggerService } from './ApLoggerService.js';
@@ -87,7 +87,7 @@ export class ApInboxService {
 	}
 	
 	@bindThis
-	public async performActivity(actor: CacheableRemoteUser, activity: IObject) {
+	public async performActivity(actor: IRemoteUser, activity: IObject) {
 		if (isCollectionOrOrderedCollection(activity)) {
 			const resolver = this.apResolverService.createResolver();
 			for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) {
@@ -115,7 +115,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	public async performOneActivity(actor: CacheableRemoteUser, activity: IObject): Promise<void> {
+	public async performOneActivity(actor: IRemoteUser, activity: IObject): Promise<void> {
 		if (actor.isSuspended) return;
 
 		if (isCreate(activity)) {
@@ -152,7 +152,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async follow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
+	private async follow(actor: IRemoteUser, activity: IFollow): Promise<string> {
 		const followee = await this.apDbResolverService.getUserFromApId(activity.object);
 	
 		if (followee == null) {
@@ -168,7 +168,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async like(actor: CacheableRemoteUser, activity: ILike): Promise<string> {
+	private async like(actor: IRemoteUser, activity: ILike): Promise<string> {
 		const targetUri = getApId(activity.object);
 
 		const note = await this.apNoteService.fetchNote(targetUri);
@@ -186,7 +186,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async read(actor: CacheableRemoteUser, activity: IRead): Promise<string> {
+	private async read(actor: IRemoteUser, activity: IRead): Promise<string> {
 		const id = await getApId(activity.object);
 
 		if (!this.utilityService.isSelfHost(this.utilityService.extractDbHost(id))) {
@@ -209,7 +209,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async accept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> {
+	private async accept(actor: IRemoteUser, activity: IAccept): Promise<string> {
 		const uri = activity.id ?? activity;
 
 		this.logger.info(`Accept: ${uri}`);
@@ -227,7 +227,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async acceptFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
+	private async acceptFollow(actor: IRemoteUser, activity: IFollow): Promise<string> {
 		// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
 
 		const follower = await this.apDbResolverService.getUserFromApId(activity.actor);
@@ -251,7 +251,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async add(actor: CacheableRemoteUser, activity: IAdd): Promise<void> {
+	private async add(actor: IRemoteUser, activity: IAdd): Promise<void> {
 		if ('actor' in activity && actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
@@ -271,7 +271,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async announce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<void> {
+	private async announce(actor: IRemoteUser, activity: IAnnounce): Promise<void> {
 		const uri = getApId(activity);
 
 		this.logger.info(`Announce: ${uri}`);
@@ -282,7 +282,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async announceNote(actor: CacheableRemoteUser, activity: IAnnounce, targetUri: string): Promise<void> {
+	private async announceNote(actor: IRemoteUser, activity: IAnnounce, targetUri: string): Promise<void> {
 		const uri = getApId(activity);
 
 		if (actor.isSuspended) {
@@ -342,7 +342,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async block(actor: CacheableRemoteUser, activity: IBlock): Promise<string> {
+	private async block(actor: IRemoteUser, activity: IBlock): Promise<string> {
 		// ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず
 
 		const blockee = await this.apDbResolverService.getUserFromApId(activity.object);
@@ -360,7 +360,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async create(actor: CacheableRemoteUser, activity: ICreate): Promise<void> {
+	private async create(actor: IRemoteUser, activity: ICreate): Promise<void> {
 		const uri = getApId(activity);
 
 		this.logger.info(`Create: ${uri}`);
@@ -396,7 +396,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async createNote(resolver: Resolver, actor: CacheableRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise<string> {
+	private async createNote(resolver: Resolver, actor: IRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise<string> {
 		const uri = getApId(note);
 
 		if (typeof note === 'object') {
@@ -431,7 +431,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async delete(actor: CacheableRemoteUser, activity: IDelete): Promise<string> {
+	private async delete(actor: IRemoteUser, activity: IDelete): Promise<string> {
 		if ('actor' in activity && actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
@@ -473,7 +473,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async deleteActor(actor: CacheableRemoteUser, uri: string): Promise<string> {
+	private async deleteActor(actor: IRemoteUser, uri: string): Promise<string> {
 		this.logger.info(`Deleting the Actor: ${uri}`);
 	
 		if (actor.uri !== uri) {
@@ -495,7 +495,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async deleteNote(actor: CacheableRemoteUser, uri: string): Promise<string> {
+	private async deleteNote(actor: IRemoteUser, uri: string): Promise<string> {
 		this.logger.info(`Deleting the Note: ${uri}`);
 	
 		const unlock = await this.appLockService.getApLock(uri);
@@ -528,7 +528,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async flag(actor: CacheableRemoteUser, activity: IFlag): Promise<string> {
+	private async flag(actor: IRemoteUser, activity: IFlag): Promise<string> {
 		// objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので
 		// 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する
 		const uris = getApIds(activity.object);
@@ -553,7 +553,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async reject(actor: CacheableRemoteUser, activity: IReject): Promise<string> {
+	private async reject(actor: IRemoteUser, activity: IReject): Promise<string> {
 		const uri = activity.id ?? activity;
 
 		this.logger.info(`Reject: ${uri}`);
@@ -571,7 +571,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async rejectFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
+	private async rejectFollow(actor: IRemoteUser, activity: IFollow): Promise<string> {
 		// ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある
 	
 		const follower = await this.apDbResolverService.getUserFromApId(activity.actor);
@@ -595,7 +595,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async remove(actor: CacheableRemoteUser, activity: IRemove): Promise<void> {
+	private async remove(actor: IRemoteUser, activity: IRemove): Promise<void> {
 		if ('actor' in activity && actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
@@ -615,7 +615,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async undo(actor: CacheableRemoteUser, activity: IUndo): Promise<string> {
+	private async undo(actor: IRemoteUser, activity: IUndo): Promise<string> {
 		if ('actor' in activity && actor.uri !== activity.actor) {
 			throw new Error('invalid actor');
 		}
@@ -641,7 +641,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async undoAccept(actor: CacheableRemoteUser, activity: IAccept): Promise<string> {
+	private async undoAccept(actor: IRemoteUser, activity: IAccept): Promise<string> {
 		const follower = await this.apDbResolverService.getUserFromApId(activity.object);
 		if (follower == null) {
 			return 'skip: follower not found';
@@ -661,7 +661,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async undoAnnounce(actor: CacheableRemoteUser, activity: IAnnounce): Promise<string> {
+	private async undoAnnounce(actor: IRemoteUser, activity: IAnnounce): Promise<string> {
 		const uri = getApId(activity);
 
 		const note = await this.notesRepository.findOneBy({
@@ -676,7 +676,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async undoBlock(actor: CacheableRemoteUser, activity: IBlock): Promise<string> {
+	private async undoBlock(actor: IRemoteUser, activity: IBlock): Promise<string> {
 		const blockee = await this.apDbResolverService.getUserFromApId(activity.object);
 
 		if (blockee == null) {
@@ -687,12 +687,12 @@ export class ApInboxService {
 			return 'skip: ブロック解除しようとしているユーザーはローカルユーザーではありません';
 		}
 
-		await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }) as CacheableUser, blockee);
+		await this.userBlockingService.unblock(await this.usersRepository.findOneByOrFail({ id: actor.id }), blockee);
 		return 'ok';
 	}
 
 	@bindThis
-	private async undoFollow(actor: CacheableRemoteUser, activity: IFollow): Promise<string> {
+	private async undoFollow(actor: IRemoteUser, activity: IFollow): Promise<string> {
 		const followee = await this.apDbResolverService.getUserFromApId(activity.object);
 		if (followee == null) {
 			return 'skip: followee not found';
@@ -726,7 +726,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async undoLike(actor: CacheableRemoteUser, activity: ILike): Promise<string> {
+	private async undoLike(actor: IRemoteUser, activity: ILike): Promise<string> {
 		const targetUri = getApId(activity.object);
 
 		const note = await this.apNoteService.fetchNote(targetUri);
@@ -741,7 +741,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async update(actor: CacheableRemoteUser, activity: IUpdate): Promise<string> {
+	private async update(actor: IRemoteUser, activity: IUpdate): Promise<string> {
 		if ('actor' in activity && actor.uri !== activity.actor) {
 			return 'skip: invalid actor';
 		}
diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts
index 928ef1ae79..f14b150138 100644
--- a/packages/backend/src/core/activitypub/models/ApImageService.ts
+++ b/packages/backend/src/core/activitypub/models/ApImageService.ts
@@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
 import { DI } from '@/di-symbols.js';
 import type { DriveFilesRepository } from '@/models/index.js';
 import type { Config } from '@/config.js';
-import type { CacheableRemoteUser } from '@/models/entities/User.js';
+import type { IRemoteUser } from '@/models/entities/User.js';
 import type { DriveFile } from '@/models/entities/DriveFile.js';
 import { MetaService } from '@/core/MetaService.js';
 import { truncate } from '@/misc/truncate.js';
@@ -36,7 +36,7 @@ export class ApImageService {
 	 * Imageを作成します。
 	 */
 	@bindThis
-	public async createImage(actor: CacheableRemoteUser, value: any): Promise<DriveFile> {
+	public async createImage(actor: IRemoteUser, value: any): Promise<DriveFile> {
 		// 投稿者が凍結されていたらスキップ
 		if (actor.isSuspended) {
 			throw new Error('actor has been suspended');
@@ -88,7 +88,7 @@ export class ApImageService {
 	 * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。
 	 */
 	@bindThis
-	public async resolveImage(actor: CacheableRemoteUser, value: any): Promise<DriveFile> {
+	public async resolveImage(actor: IRemoteUser, value: any): Promise<DriveFile> {
 		// TODO
 
 		// リモートサーバーからフェッチしてきて登録
diff --git a/packages/backend/src/core/activitypub/models/ApMentionService.ts b/packages/backend/src/core/activitypub/models/ApMentionService.ts
index 41e6c6b14f..1ed9fb89dd 100644
--- a/packages/backend/src/core/activitypub/models/ApMentionService.ts
+++ b/packages/backend/src/core/activitypub/models/ApMentionService.ts
@@ -1,15 +1,14 @@
 import { Inject, Injectable } from '@nestjs/common';
 import promiseLimit from 'promise-limit';
 import { DI } from '@/di-symbols.js';
-import type { UsersRepository } from '@/models/index.js';
+import type { User, UsersRepository } from '@/models/index.js';
 import type { Config } from '@/config.js';
 import { toArray, unique } from '@/misc/prelude/array.js';
-import type { CacheableUser } from '@/models/entities/User.js';
+import { bindThis } from '@/decorators.js';
 import { isMention } from '../type.js';
 import { ApResolverService, Resolver } from '../ApResolverService.js';
 import { ApPersonService } from './ApPersonService.js';
 import type { IObject, IApMention } from '../type.js';
-import { bindThis } from '@/decorators.js';
 
 @Injectable()
 export class ApMentionService {
@@ -26,10 +25,10 @@ export class ApMentionService {
 	public async extractApMentions(tags: IObject | IObject[] | null | undefined, resolver: Resolver) {
 		const hrefs = unique(this.extractApMentionObjects(tags).map(x => x.href as string));
 
-		const limit = promiseLimit<CacheableUser | null>(2);
+		const limit = promiseLimit<User | null>(2);
 		const mentionedUsers = (await Promise.all(
 			hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))),
-		)).filter((x): x is CacheableUser => x != null);
+		)).filter((x): x is User => x != null);
 	
 		return mentionedUsers;
 	}
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index dc47fdf800..0292a27d94 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -3,7 +3,7 @@ import promiseLimit from 'promise-limit';
 import { DI } from '@/di-symbols.js';
 import type { MessagingMessagesRepository, PollsRepository, EmojisRepository, UsersRepository } from '@/models/index.js';
 import type { Config } from '@/config.js';
-import type { CacheableRemoteUser } from '@/models/entities/User.js';
+import type { IRemoteUser } from '@/models/entities/User.js';
 import type { Note } from '@/models/entities/Note.js';
 import { toArray, toSingle, unique } from '@/misc/prelude/array.js';
 import type { Emoji } from '@/models/entities/Emoji.js';
@@ -146,7 +146,7 @@ export class ApNoteService {
 		this.logger.info(`Creating the Note: ${note.id}`);
 	
 		// 投稿者をフェッチ
-		const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as CacheableRemoteUser;
+		const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo!), resolver) as IRemoteUser;
 	
 		// 投稿者が凍結されていたらスキップ
 		if (actor.isSuspended) {
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 4869656f1d..9dca065529 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -5,7 +5,7 @@ import { ModuleRef } from '@nestjs/core';
 import { DI } from '@/di-symbols.js';
 import type { FollowingsRepository, InstancesRepository, UserProfilesRepository, UserPublickeysRepository, UsersRepository } from '@/models/index.js';
 import type { Config } from '@/config.js';
-import type { CacheableUser, IRemoteUser } from '@/models/entities/User.js';
+import type { IRemoteUser } from '@/models/entities/User.js';
 import { User } from '@/models/entities/User.js';
 import { truncate } from '@/misc/truncate.js';
 import type { UserCacheService } from '@/core/UserCacheService.js';
@@ -197,7 +197,7 @@ export class ApPersonService implements OnModuleInit {
 	 * Misskeyに対象のPersonが登録されていればそれを返します。
 	 */
 	@bindThis
-	public async fetchPerson(uri: string, resolver?: Resolver): Promise<CacheableUser | null> {
+	public async fetchPerson(uri: string, resolver?: Resolver): Promise<User | null> {
 		if (typeof uri !== 'string') throw new Error('uri is not string');
 
 		const cached = this.userCacheService.uriPersonCache.get(uri);
@@ -206,13 +206,13 @@ export class ApPersonService implements OnModuleInit {
 		// URIがこのサーバーを指しているならデータベースからフェッチ
 		if (uri.startsWith(this.config.url + '/')) {
 			const id = uri.split('/').pop();
-			const u = await this.usersRepository.findOneBy({ id }) as null | CacheableUser;
+			const u = await this.usersRepository.findOneBy({ id });
 			if (u) this.userCacheService.uriPersonCache.set(uri, u);
 			return u;
 		}
 
 		//#region このサーバーに既に登録されていたらそれを返す
-		const exist = await this.usersRepository.findOneBy({ uri }) as null | CacheableUser;
+		const exist = await this.usersRepository.findOneBy({ uri });
 
 		if (exist) {
 			this.userCacheService.uriPersonCache.set(uri, exist);
@@ -500,7 +500,7 @@ export class ApPersonService implements OnModuleInit {
 	 * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。
 	 */
 	@bindThis
-	public async resolvePerson(uri: string, resolver?: Resolver): Promise<CacheableUser> {
+	public async resolvePerson(uri: string, resolver?: Resolver): Promise<User> {
 		if (typeof uri !== 'string') throw new Error('uri is not string');
 
 		//#region このサーバーに既に登録されていたらそれを返す
@@ -513,7 +513,7 @@ export class ApPersonService implements OnModuleInit {
 
 		// リモートサーバーからフェッチしてきて登録
 		if (resolver == null) resolver = this.apResolverService.createResolver();
-		return await this.createPerson(uri, resolver) as CacheableUser;
+		return await this.createPerson(uri, resolver);
 	}
 
 	@bindThis
diff --git a/packages/backend/src/models/entities/User.ts b/packages/backend/src/models/entities/User.ts
index 9cfe79787a..8d476ab0a6 100644
--- a/packages/backend/src/models/entities/User.ts
+++ b/packages/backend/src/models/entities/User.ts
@@ -217,6 +217,7 @@ export class User {
 
 export interface ILocalUser extends User {
 	host: null;
+	uri: null;
 }
 
 export interface IRemoteUser extends User {
@@ -224,12 +225,6 @@ export interface IRemoteUser extends User {
 	uri: string;
 }
 
-export type CacheableLocalUser = ILocalUser;
-
-export type CacheableRemoteUser = IRemoteUser;
-
-export type CacheableUser = CacheableLocalUser | CacheableRemoteUser;
-
 export const localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const;
 export const passwordSchema = { type: 'string', minLength: 1 } as const;
 export const nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const;
diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts
index f814368a7a..a41222c487 100644
--- a/packages/backend/src/queue/processors/InboxProcessorService.ts
+++ b/packages/backend/src/queue/processors/InboxProcessorService.ts
@@ -16,7 +16,7 @@ import InstanceChart from '@/core/chart/charts/instance.js';
 import ApRequestChart from '@/core/chart/charts/ap-request.js';
 import FederationChart from '@/core/chart/charts/federation.js';
 import { getApId } from '@/core/activitypub/type.js';
-import type { CacheableRemoteUser } from '@/models/entities/User.js';
+import type { IRemoteUser } from '@/models/entities/User.js';
 import type { UserPublickey } from '@/models/entities/UserPublickey.js';
 import { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js';
 import { StatusError } from '@/misc/status-error.js';
@@ -87,7 +87,7 @@ export class InboxProcessorService {
 
 		// HTTP-Signature keyIdを元にDBから取得
 		let authUser: {
-		user: CacheableRemoteUser;
+		user: IRemoteUser;
 		key: UserPublickey | null;
 	} | null = await this.apDbResolverService.getAuthUserFromKeyId(signature.keyId);
 
diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts
index 2f3e7a44a9..3a05413bc8 100644
--- a/packages/backend/src/server/api/ApiCallService.ts
+++ b/packages/backend/src/server/api/ApiCallService.ts
@@ -5,7 +5,7 @@ import { promisify } from 'node:util';
 import { Inject, Injectable } from '@nestjs/common';
 import { DI } from '@/di-symbols.js';
 import { getIpHash } from '@/misc/get-ip-hash.js';
-import type { CacheableLocalUser, ILocalUser, User } from '@/models/entities/User.js';
+import type { ILocalUser, User } from '@/models/entities/User.js';
 import type { AccessToken } from '@/models/entities/AccessToken.js';
 import type Logger from '@/logger.js';
 import type { UserIpsRepository } from '@/models/index.js';
@@ -194,7 +194,7 @@ export class ApiCallService implements OnApplicationShutdown {
 	@bindThis
 	private async call(
 		ep: IEndpoint & { exec: any },
-		user: CacheableLocalUser | null | undefined,
+		user: ILocalUser | null | undefined,
 		token: AccessToken | null | undefined,
 		data: any,
 		file: {
diff --git a/packages/backend/src/server/api/AuthenticateService.ts b/packages/backend/src/server/api/AuthenticateService.ts
index 8b39f6c924..b9f6af4ffe 100644
--- a/packages/backend/src/server/api/AuthenticateService.ts
+++ b/packages/backend/src/server/api/AuthenticateService.ts
@@ -1,7 +1,7 @@
 import { Inject, Injectable } from '@nestjs/common';
 import { DI } from '@/di-symbols.js';
 import type { AccessTokensRepository, AppsRepository, UsersRepository } from '@/models/index.js';
-import type { CacheableLocalUser, ILocalUser } from '@/models/entities/User.js';
+import type { ILocalUser } from '@/models/entities/User.js';
 import type { AccessToken } from '@/models/entities/AccessToken.js';
 import { Cache } from '@/misc/cache.js';
 import type { App } from '@/models/entities/App.js';
@@ -36,7 +36,7 @@ export class AuthenticateService {
 	}
 
 	@bindThis
-	public async authenticate(token: string | null | undefined): Promise<[CacheableLocalUser | null | undefined, AccessToken | null | undefined]> {
+	public async authenticate(token: string | null | undefined): Promise<[ILocalUser | null | undefined, AccessToken | null | undefined]> {
 		if (token == null) {
 			return [null, null];
 		}
diff --git a/packages/backend/src/server/api/endpoint-base.ts b/packages/backend/src/server/api/endpoint-base.ts
index b27329b9a9..56dad62862 100644
--- a/packages/backend/src/server/api/endpoint-base.ts
+++ b/packages/backend/src/server/api/endpoint-base.ts
@@ -1,7 +1,7 @@
 import * as fs from 'node:fs';
 import Ajv from 'ajv';
 import type { Schema, SchemaType } from '@/misc/schema.js';
-import type { CacheableLocalUser } from '@/models/entities/User.js';
+import type { ILocalUser } from '@/models/entities/User.js';
 import type { AccessToken } from '@/models/entities/AccessToken.js';
 import { ApiError } from './error.js';
 import type { IEndpointMeta } from './endpoints.js';
@@ -21,16 +21,16 @@ type File = {
 
 // TODO: paramsの型をT['params']のスキーマ定義から推論する
 type executor<T extends IEndpointMeta, Ps extends Schema> =
-	(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) =>
+	(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) =>
 		Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
 
 export abstract class Endpoint<T extends IEndpointMeta, Ps extends Schema> {
-	public exec: (params: any, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>;
+	public exec: (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>;
 
 	constructor(meta: T, paramDef: Ps, cb: executor<T, Ps>) {
 		const validate = ajv.compile(paramDef);
 
-		this.exec = (params: any, user: T['requireCredential'] extends true ? CacheableLocalUser : CacheableLocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => {
+		this.exec = (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => {
 			let cleanup: undefined | (() => void) = undefined;
 	
 			if (meta.requireFile) {
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index 9470dd3cbb..e758c5e3fa 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -3,7 +3,7 @@ import ms from 'ms';
 import { Endpoint } from '@/server/api/endpoint-base.js';
 import type { UsersRepository, NotesRepository } from '@/models/index.js';
 import type { Note } from '@/models/entities/Note.js';
-import type { CacheableLocalUser, User } from '@/models/entities/User.js';
+import type { ILocalUser, User } from '@/models/entities/User.js';
 import { isActor, isPost, getApId } from '@/core/activitypub/type.js';
 import type { SchemaType } from '@/misc/schema.js';
 import { ApResolverService } from '@/core/activitypub/ApResolverService.js';
@@ -114,7 +114,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 	 * URIからUserかNoteを解決する
 	 */
 	@bindThis
-	private async fetchAny(uri: string, me: CacheableLocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
+	private async fetchAny(uri: string, me: ILocalUser | null | undefined): Promise<SchemaType<typeof meta['res']> | null> {
 	// ブロックしてたら中断
 		const fetchedMeta = await this.metaService.fetch();
 		if (this.utilityService.isBlockedHost(fetchedMeta.blockedHosts, this.utilityService.extractDbHost(uri))) return null;
@@ -147,7 +147,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
 	}
 
 	@bindThis
-	private async mergePack(me: CacheableLocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
+	private async mergePack(me: ILocalUser | null | undefined, user: User | null | undefined, note: Note | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
 		if (user != null) {
 			return {
 				type: 'User',