Sharkey/packages/backend/src/server/api/stream/channels/role-timeline.ts
Chocolate Pie c96bc36fed
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>
2023-12-27 15:08:59 +09:00

90 lines
2.6 KiB
TypeScript

/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Injectable } from '@nestjs/common';
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 { RoleService } from '@/core/RoleService.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import Channel, { type MiChannelService } from '../channel.js';
class RoleTimelineChannel extends Channel {
public readonly chName = 'roleTimeline';
public static shouldShare = false;
public static requireCredential = false as const;
private roleId: string;
constructor(
private noteEntityService: NoteEntityService,
private roleservice: RoleService,
id: string,
connection: Channel['connection'],
) {
super(id, connection);
//this.onNote = this.onNote.bind(this);
}
@bindThis
public async init(params: any) {
this.roleId = params.roleId as string;
this.subscriber.on(`roleTimelineStream:${this.roleId}`, this.onEvent);
}
@bindThis
private async onEvent(data: GlobalEvents['roleTimeline']['payload']) {
if (data.type === 'note') {
const note = data.body;
if (!(await this.roleservice.isExplorable({ id: this.roleId }))) {
return;
}
if (note.visibility !== 'public') return;
// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.userIdsWhoMeMuting)) return;
// 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する
if (isUserRelated(note, this.userIdsWhoBlockingMe)) return;
if (note.renote && !note.text && isUserRelated(note, this.userIdsWhoMeMutingRenotes)) return;
this.send('note', note);
} else {
this.send(data.type, data.body);
}
}
@bindThis
public dispose() {
// Unsubscribe events
this.subscriber.off(`roleTimelineStream:${this.roleId}`, this.onEvent);
}
}
@Injectable()
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,
private roleservice: RoleService,
) {
}
@bindThis
public create(id: string, connection: Channel['connection']): RoleTimelineChannel {
return new RoleTimelineChannel(
this.noteEntityService,
this.roleservice,
id,
connection,
);
}
}