Merge pull request from GHSA-7pxq-6xx9-xpgm
* fix: fix improper authorization when accessing with third-party application
* refactor: refactor type definitions
* fix: get rid of unnecessary access limitation
* enhance: サードパーティアプリケーションがWebsocket APIを使えるように
* fix: add missing parentheses
* Revert "fix(backend): add missing kind definition for admin endpoints to improve security"
This reverts commit 5150053275.
* frontend: 翻訳の抜けを訂正, read:adminとwrite:adminはアクセス発行トークンのデフォルトでは非表示にする
* enhance(test): misskey-ghsa-7pxq-6xx9-xpgmに関するテストを追加
* enhance(test): Websocket APIに対するテストも追加
* enhance(refactor): `@/misc/api-permissions.ts`を`misskey-js/permissions`に統合
* fix(frontend): アクセストークン発行UIで全ての権限を有効にした際、管理者用APIへのアクセスも許可してしまう問題を修正
* enhance(backend): Websocketの接続に最低限必要な権限を変更
* fix(backend): `/api/admin/meta`をサードパーティアプリケーションからはアクセスできないように
* fix(backend): エンドポイントにアクセスするために必要な権限を変更
* fix(frontend/locale): Add missing type declaration
* chore: update `misskey-js/src/autogen`
---------
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
			
			
This commit is contained in:
		| @@ -5,12 +5,13 @@ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class AdminChannel extends Channel { | ||||
| 	public readonly chName = 'admin'; | ||||
| 	public static shouldShare = true; | ||||
| 	public static requireCredential = true; | ||||
| 	public static requireCredential = true as const; | ||||
| 	public static kind = 'read:admin:stream'; | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async init(params: any) { | ||||
| @@ -22,9 +23,10 @@ class AdminChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class AdminChannelService { | ||||
| export class AdminChannelService implements MiChannelService<true> { | ||||
| 	public readonly shouldShare = AdminChannel.shouldShare; | ||||
| 	public readonly requireCredential = AdminChannel.requireCredential; | ||||
| 	public readonly kind = AdminChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 	) { | ||||
|   | ||||
| @@ -8,12 +8,13 @@ import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import type { GlobalEvents } from '@/core/GlobalEventService.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class AntennaChannel extends Channel { | ||||
| 	public readonly chName = 'antenna'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = true as const; | ||||
| 	public static kind = 'read:account'; | ||||
| 	private antennaId: string; | ||||
|  | ||||
| 	constructor( | ||||
| @@ -62,9 +63,10 @@ class AntennaChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class AntennaChannelService { | ||||
| export class AntennaChannelService implements MiChannelService<true> { | ||||
| 	public readonly shouldShare = AntennaChannel.shouldShare; | ||||
| 	public readonly requireCredential = AntennaChannel.requireCredential; | ||||
| 	public readonly kind = AntennaChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
|   | ||||
| @@ -8,12 +8,12 @@ import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class ChannelChannel extends Channel { | ||||
| 	public readonly chName = 'channel'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
| 	private channelId: string; | ||||
|  | ||||
| 	constructor( | ||||
| @@ -65,9 +65,10 @@ class ChannelChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class ChannelChannelService { | ||||
| export class ChannelChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = ChannelChannel.shouldShare; | ||||
| 	public readonly requireCredential = ChannelChannel.requireCredential; | ||||
| 	public readonly kind = ChannelChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
|   | ||||
| @@ -5,12 +5,13 @@ | ||||
|  | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class DriveChannel extends Channel { | ||||
| 	public readonly chName = 'drive'; | ||||
| 	public static shouldShare = true; | ||||
| 	public static requireCredential = true; | ||||
| 	public static requireCredential = true as const; | ||||
| 	public static kind = 'read:account'; | ||||
|  | ||||
| 	@bindThis | ||||
| 	public async init(params: any) { | ||||
| @@ -22,9 +23,10 @@ class DriveChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class DriveChannelService { | ||||
| export class DriveChannelService implements MiChannelService<true> { | ||||
| 	public readonly shouldShare = DriveChannel.shouldShare; | ||||
| 	public readonly requireCredential = DriveChannel.requireCredential; | ||||
| 	public readonly kind = DriveChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 	) { | ||||
|   | ||||
| @@ -12,12 +12,12 @@ import { MetaService } from '@/core/MetaService.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class GlobalTimelineChannel extends Channel { | ||||
| 	public readonly chName = 'globalTimeline'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
| 	private withRenotes: boolean; | ||||
| 	private withFiles: boolean; | ||||
|  | ||||
| @@ -91,9 +91,10 @@ class GlobalTimelineChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class GlobalTimelineChannelService { | ||||
| export class GlobalTimelineChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = GlobalTimelineChannel.shouldShare; | ||||
| 	public readonly requireCredential = GlobalTimelineChannel.requireCredential; | ||||
| 	public readonly kind = GlobalTimelineChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private metaService: MetaService, | ||||
|   | ||||
| @@ -9,12 +9,12 @@ import { isUserRelated } from '@/misc/is-user-related.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class HashtagChannel extends Channel { | ||||
| 	public readonly chName = 'hashtag'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
| 	private q: string[][]; | ||||
|  | ||||
| 	constructor( | ||||
| @@ -70,9 +70,10 @@ class HashtagChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class HashtagChannelService { | ||||
| export class HashtagChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = HashtagChannel.shouldShare; | ||||
| 	public readonly requireCredential = HashtagChannel.requireCredential; | ||||
| 	public readonly kind = HashtagChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
|   | ||||
| @@ -10,12 +10,13 @@ import { isInstanceMuted } from '@/misc/is-instance-muted.js'; | ||||
| import type { Packed } from '@/misc/json-schema.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class HomeTimelineChannel extends Channel { | ||||
| 	public readonly chName = 'homeTimeline'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = true; | ||||
| 	public static requireCredential = true as const; | ||||
| 	public static kind = 'read:account'; | ||||
| 	private withRenotes: boolean; | ||||
| 	private withFiles: boolean; | ||||
|  | ||||
| @@ -99,9 +100,10 @@ class HomeTimelineChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class HomeTimelineChannelService { | ||||
| export class HomeTimelineChannelService implements MiChannelService<true> { | ||||
| 	public readonly shouldShare = HomeTimelineChannel.shouldShare; | ||||
| 	public readonly requireCredential = HomeTimelineChannel.requireCredential; | ||||
| 	public readonly kind = HomeTimelineChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
|   | ||||
| @@ -12,12 +12,13 @@ import { MetaService } from '@/core/MetaService.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class HybridTimelineChannel extends Channel { | ||||
| 	public readonly chName = 'hybridTimeline'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = true; | ||||
| 	public static requireCredential = true as const; | ||||
| 	public static kind = 'read:account'; | ||||
| 	private withRenotes: boolean; | ||||
| 	private withReplies: boolean; | ||||
| 	private withFiles: boolean; | ||||
| @@ -114,9 +115,10 @@ class HybridTimelineChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class HybridTimelineChannelService { | ||||
| export class HybridTimelineChannelService implements MiChannelService<true> { | ||||
| 	public readonly shouldShare = HybridTimelineChannel.shouldShare; | ||||
| 	public readonly requireCredential = HybridTimelineChannel.requireCredential; | ||||
| 	public readonly kind = HybridTimelineChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private metaService: MetaService, | ||||
|   | ||||
| @@ -11,12 +11,12 @@ import { MetaService } from '@/core/MetaService.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class LocalTimelineChannel extends Channel { | ||||
| 	public readonly chName = 'localTimeline'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
| 	private withRenotes: boolean; | ||||
| 	private withReplies: boolean; | ||||
| 	private withFiles: boolean; | ||||
| @@ -90,9 +90,10 @@ class LocalTimelineChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class LocalTimelineChannelService { | ||||
| export class LocalTimelineChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = LocalTimelineChannel.shouldShare; | ||||
| 	public readonly requireCredential = LocalTimelineChannel.requireCredential; | ||||
| 	public readonly kind = LocalTimelineChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private metaService: MetaService, | ||||
|   | ||||
| @@ -7,12 +7,13 @@ import { Injectable } from '@nestjs/common'; | ||||
| import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js'; | ||||
| import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class MainChannel extends Channel { | ||||
| 	public readonly chName = 'main'; | ||||
| 	public static shouldShare = true; | ||||
| 	public static requireCredential = true; | ||||
| 	public static requireCredential = true as const; | ||||
| 	public static kind = 'read:account'; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
| @@ -63,9 +64,10 @@ class MainChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class MainChannelService { | ||||
| export class MainChannelService implements MiChannelService<true> { | ||||
| 	public readonly shouldShare = MainChannel.shouldShare; | ||||
| 	public readonly requireCredential = MainChannel.requireCredential; | ||||
| 	public readonly kind = MainChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
|   | ||||
| @@ -6,14 +6,14 @@ | ||||
| import Xev from 'xev'; | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| const ev = new Xev(); | ||||
|  | ||||
| class QueueStatsChannel extends Channel { | ||||
| 	public readonly chName = 'queueStats'; | ||||
| 	public static shouldShare = true; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
|  | ||||
| 	constructor(id: string, connection: Channel['connection']) { | ||||
| 		super(id, connection); | ||||
| @@ -53,9 +53,10 @@ class QueueStatsChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class QueueStatsChannelService { | ||||
| export class QueueStatsChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = QueueStatsChannel.shouldShare; | ||||
| 	public readonly requireCredential = QueueStatsChannel.requireCredential; | ||||
| 	public readonly kind = QueueStatsChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 	) { | ||||
|   | ||||
| @@ -10,12 +10,12 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { RoleService } from '@/core/RoleService.js'; | ||||
| import type { GlobalEvents } from '@/core/GlobalEventService.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class RoleTimelineChannel extends Channel { | ||||
| 	public readonly chName = 'roleTimeline'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
| 	private roleId: string; | ||||
|  | ||||
| 	constructor( | ||||
| @@ -67,9 +67,10 @@ class RoleTimelineChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class RoleTimelineChannelService { | ||||
| export class RoleTimelineChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = RoleTimelineChannel.shouldShare; | ||||
| 	public readonly requireCredential = RoleTimelineChannel.requireCredential; | ||||
| 	public readonly kind = RoleTimelineChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		private noteEntityService: NoteEntityService, | ||||
|   | ||||
| @@ -6,14 +6,14 @@ | ||||
| import Xev from 'xev'; | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| const ev = new Xev(); | ||||
|  | ||||
| class ServerStatsChannel extends Channel { | ||||
| 	public readonly chName = 'serverStats'; | ||||
| 	public static shouldShare = true; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
|  | ||||
| 	constructor(id: string, connection: Channel['connection']) { | ||||
| 		super(id, connection); | ||||
| @@ -53,9 +53,10 @@ class ServerStatsChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class ServerStatsChannelService { | ||||
| export class ServerStatsChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = ServerStatsChannel.shouldShare; | ||||
| 	public readonly requireCredential = ServerStatsChannel.requireCredential; | ||||
| 	public readonly kind = ServerStatsChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 	) { | ||||
|   | ||||
| @@ -11,12 +11,12 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { bindThis } from '@/decorators.js'; | ||||
| import { isInstanceMuted } from '@/misc/is-instance-muted.js'; | ||||
| import Channel from '../channel.js'; | ||||
| import Channel, { type MiChannelService } from '../channel.js'; | ||||
|  | ||||
| class UserListChannel extends Channel { | ||||
| 	public readonly chName = 'userList'; | ||||
| 	public static shouldShare = false; | ||||
| 	public static requireCredential = false; | ||||
| 	public static requireCredential = false as const; | ||||
| 	private listId: string; | ||||
| 	private membershipsMap: Record<string, Pick<MiUserListMembership, 'withReplies'> | undefined> = {}; | ||||
| 	private listUsersClock: NodeJS.Timeout; | ||||
| @@ -137,9 +137,10 @@ class UserListChannel extends Channel { | ||||
| } | ||||
|  | ||||
| @Injectable() | ||||
| export class UserListChannelService { | ||||
| export class UserListChannelService implements MiChannelService<false> { | ||||
| 	public readonly shouldShare = UserListChannel.shouldShare; | ||||
| 	public readonly requireCredential = UserListChannel.requireCredential; | ||||
| 	public readonly kind = UserListChannel.kind; | ||||
|  | ||||
| 	constructor( | ||||
| 		@Inject(DI.userListsRepository) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Chocolate Pie
					Chocolate Pie