 61fae45390
			
		
	
	61fae45390
	
	
	
		
			
			* feat: 通報を受けた際にメールまたはWebhookで通知を送出出来るようにする * モデログに対応&エンドポイントを単一オブジェクトでのサポートに変更(API経由で大量に作るシチュエーションもないと思うので) * fix spdx * fix migration * fix migration * fix models * add e2e webhook * tweak * fix modlog * fix bugs * add tests and fix bugs * add tests and fix bugs * add tests * fix path * regenerate locale * 混入除去 * 混入除去 * add abuseReportResolved * fix pnpm-lock.yaml * add abuseReportResolved test * fix bugs * fix ui * add tests * fix CHANGELOG.md * add tests * add RoleService.getModeratorIds tests * WebhookServiceをUserとSystemに分割 * fix CHANGELOG.md * fix test * insertOneを使う用に * fix * regenerate locales * revert version * separate webhook job queue * fix * 🎨 * Update QueueProcessorService.ts --------- Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
		
			
				
	
	
		
			256 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: syuilo and misskey-project
 | |
|  * SPDX-License-Identifier: AGPL-3.0-only
 | |
|  */
 | |
| 
 | |
| // https://github.com/typeorm/typeorm/issues/2400
 | |
| import pg from 'pg';
 | |
| import { DataSource, Logger } from 'typeorm';
 | |
| import * as highlight from 'cli-highlight';
 | |
| import { entities as charts } from '@/core/chart/entities.js';
 | |
| 
 | |
| import { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
 | |
| import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js';
 | |
| import { MiAccessToken } from '@/models/AccessToken.js';
 | |
| import { MiAd } from '@/models/Ad.js';
 | |
| import { MiAnnouncement } from '@/models/Announcement.js';
 | |
| import { MiAnnouncementRead } from '@/models/AnnouncementRead.js';
 | |
| import { MiAntenna } from '@/models/Antenna.js';
 | |
| import { MiApp } from '@/models/App.js';
 | |
| import { MiAvatarDecoration } from '@/models/AvatarDecoration.js';
 | |
| import { MiAuthSession } from '@/models/AuthSession.js';
 | |
| import { MiBlocking } from '@/models/Blocking.js';
 | |
| import { MiChannelFollowing } from '@/models/ChannelFollowing.js';
 | |
| import { MiChannelFavorite } from '@/models/ChannelFavorite.js';
 | |
| import { MiClip } from '@/models/Clip.js';
 | |
| import { MiClipNote } from '@/models/ClipNote.js';
 | |
| import { MiClipFavorite } from '@/models/ClipFavorite.js';
 | |
| import { MiDriveFile } from '@/models/DriveFile.js';
 | |
| import { MiDriveFolder } from '@/models/DriveFolder.js';
 | |
| import { MiEmoji } from '@/models/Emoji.js';
 | |
| import { MiFollowing } from '@/models/Following.js';
 | |
| import { MiFollowRequest } from '@/models/FollowRequest.js';
 | |
| import { MiGalleryLike } from '@/models/GalleryLike.js';
 | |
| import { MiGalleryPost } from '@/models/GalleryPost.js';
 | |
| import { MiHashtag } from '@/models/Hashtag.js';
 | |
| import { MiInstance } from '@/models/Instance.js';
 | |
| import { MiMeta } from '@/models/Meta.js';
 | |
| import { MiModerationLog } from '@/models/ModerationLog.js';
 | |
| import { MiMuting } from '@/models/Muting.js';
 | |
| import { MiRenoteMuting } from '@/models/RenoteMuting.js';
 | |
| import { MiNote } from '@/models/Note.js';
 | |
| import { MiNoteFavorite } from '@/models/NoteFavorite.js';
 | |
| import { MiNoteReaction } from '@/models/NoteReaction.js';
 | |
| import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js';
 | |
| import { MiNoteUnread } from '@/models/NoteUnread.js';
 | |
| import { MiPage } from '@/models/Page.js';
 | |
| import { MiPageLike } from '@/models/PageLike.js';
 | |
| import { MiPasswordResetRequest } from '@/models/PasswordResetRequest.js';
 | |
| import { MiPoll } from '@/models/Poll.js';
 | |
| import { MiPollVote } from '@/models/PollVote.js';
 | |
| import { MiPromoNote } from '@/models/PromoNote.js';
 | |
| import { MiPromoRead } from '@/models/PromoRead.js';
 | |
| import { MiRegistrationTicket } from '@/models/RegistrationTicket.js';
 | |
| import { MiRegistryItem } from '@/models/RegistryItem.js';
 | |
| import { MiRelay } from '@/models/Relay.js';
 | |
| import { MiSignin } from '@/models/Signin.js';
 | |
| import { MiSwSubscription } from '@/models/SwSubscription.js';
 | |
| import { MiUsedUsername } from '@/models/UsedUsername.js';
 | |
| import { MiUser } from '@/models/User.js';
 | |
| import { MiUserIp } from '@/models/UserIp.js';
 | |
| import { MiUserKeypair } from '@/models/UserKeypair.js';
 | |
| import { MiUserList } from '@/models/UserList.js';
 | |
| import { MiUserListFavorite } from '@/models/UserListFavorite.js';
 | |
| import { MiUserListMembership } from '@/models/UserListMembership.js';
 | |
| import { MiUserNotePining } from '@/models/UserNotePining.js';
 | |
| import { MiUserPending } from '@/models/UserPending.js';
 | |
| import { MiUserProfile } from '@/models/UserProfile.js';
 | |
| import { MiUserPublickey } from '@/models/UserPublickey.js';
 | |
| import { MiUserSecurityKey } from '@/models/UserSecurityKey.js';
 | |
| import { MiWebhook } from '@/models/Webhook.js';
 | |
| import { MiSystemWebhook } from '@/models/SystemWebhook.js';
 | |
| import { MiChannel } from '@/models/Channel.js';
 | |
| import { MiRetentionAggregation } from '@/models/RetentionAggregation.js';
 | |
| import { MiRole } from '@/models/Role.js';
 | |
| import { MiRoleAssignment } from '@/models/RoleAssignment.js';
 | |
| import { MiFlash } from '@/models/Flash.js';
 | |
| import { MiFlashLike } from '@/models/FlashLike.js';
 | |
| import { MiUserMemo } from '@/models/UserMemo.js';
 | |
| import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js';
 | |
| import { MiReversiGame } from '@/models/ReversiGame.js';
 | |
| 
 | |
| import { Config } from '@/config.js';
 | |
| import MisskeyLogger from '@/logger.js';
 | |
| import { bindThis } from '@/decorators.js';
 | |
| 
 | |
| pg.types.setTypeParser(20, Number);
 | |
| 
 | |
| export const dbLogger = new MisskeyLogger('db');
 | |
| 
 | |
| const sqlLogger = dbLogger.createSubLogger('sql', 'gray');
 | |
| 
 | |
| class MyCustomLogger implements Logger {
 | |
| 	@bindThis
 | |
| 	private highlight(sql: string) {
 | |
| 		return highlight.highlight(sql, {
 | |
| 			language: 'sql', ignoreIllegals: true,
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public logQuery(query: string, parameters?: any[]) {
 | |
| 		sqlLogger.info(this.highlight(query).substring(0, 100));
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public logQueryError(error: string, query: string, parameters?: any[]) {
 | |
| 		sqlLogger.error(this.highlight(query));
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public logQuerySlow(time: number, query: string, parameters?: any[]) {
 | |
| 		sqlLogger.warn(this.highlight(query));
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public logSchemaBuild(message: string) {
 | |
| 		sqlLogger.info(message);
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public log(message: string) {
 | |
| 		sqlLogger.info(message);
 | |
| 	}
 | |
| 
 | |
| 	@bindThis
 | |
| 	public logMigration(message: string) {
 | |
| 		sqlLogger.info(message);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| export const entities = [
 | |
| 	MiAnnouncement,
 | |
| 	MiAnnouncementRead,
 | |
| 	MiMeta,
 | |
| 	MiInstance,
 | |
| 	MiApp,
 | |
| 	MiAvatarDecoration,
 | |
| 	MiAuthSession,
 | |
| 	MiAccessToken,
 | |
| 	MiUser,
 | |
| 	MiUserProfile,
 | |
| 	MiUserKeypair,
 | |
| 	MiUserPublickey,
 | |
| 	MiUserList,
 | |
| 	MiUserListFavorite,
 | |
| 	MiUserListMembership,
 | |
| 	MiUserNotePining,
 | |
| 	MiUserSecurityKey,
 | |
| 	MiUsedUsername,
 | |
| 	MiFollowing,
 | |
| 	MiFollowRequest,
 | |
| 	MiMuting,
 | |
| 	MiRenoteMuting,
 | |
| 	MiBlocking,
 | |
| 	MiNote,
 | |
| 	MiNoteFavorite,
 | |
| 	MiNoteReaction,
 | |
| 	MiNoteThreadMuting,
 | |
| 	MiNoteUnread,
 | |
| 	MiPage,
 | |
| 	MiPageLike,
 | |
| 	MiGalleryPost,
 | |
| 	MiGalleryLike,
 | |
| 	MiDriveFile,
 | |
| 	MiDriveFolder,
 | |
| 	MiPoll,
 | |
| 	MiPollVote,
 | |
| 	MiEmoji,
 | |
| 	MiHashtag,
 | |
| 	MiSwSubscription,
 | |
| 	MiAbuseUserReport,
 | |
| 	MiAbuseReportNotificationRecipient,
 | |
| 	MiRegistrationTicket,
 | |
| 	MiSignin,
 | |
| 	MiModerationLog,
 | |
| 	MiClip,
 | |
| 	MiClipNote,
 | |
| 	MiClipFavorite,
 | |
| 	MiAntenna,
 | |
| 	MiPromoNote,
 | |
| 	MiPromoRead,
 | |
| 	MiRelay,
 | |
| 	MiChannel,
 | |
| 	MiChannelFollowing,
 | |
| 	MiChannelFavorite,
 | |
| 	MiRegistryItem,
 | |
| 	MiAd,
 | |
| 	MiPasswordResetRequest,
 | |
| 	MiUserPending,
 | |
| 	MiWebhook,
 | |
| 	MiSystemWebhook,
 | |
| 	MiUserIp,
 | |
| 	MiRetentionAggregation,
 | |
| 	MiRole,
 | |
| 	MiRoleAssignment,
 | |
| 	MiFlash,
 | |
| 	MiFlashLike,
 | |
| 	MiUserMemo,
 | |
| 	MiBubbleGameRecord,
 | |
| 	MiReversiGame,
 | |
| 	...charts,
 | |
| ];
 | |
| 
 | |
| const log = process.env.NODE_ENV !== 'production';
 | |
| 
 | |
| export function createPostgresDataSource(config: Config) {
 | |
| 	return new DataSource({
 | |
| 		type: 'postgres',
 | |
| 		host: config.db.host,
 | |
| 		port: config.db.port,
 | |
| 		username: config.db.user,
 | |
| 		password: config.db.pass,
 | |
| 		database: config.db.db,
 | |
| 		extra: {
 | |
| 			statement_timeout: 1000 * 10,
 | |
| 			...config.db.extra,
 | |
| 		},
 | |
| 		...(config.dbReplications ? {
 | |
| 			replication: {
 | |
| 				master: {
 | |
| 					host: config.db.host,
 | |
| 					port: config.db.port,
 | |
| 					username: config.db.user,
 | |
| 					password: config.db.pass,
 | |
| 					database: config.db.db,
 | |
| 				},
 | |
| 				slaves: config.dbSlaves!.map(rep => ({
 | |
| 					host: rep.host,
 | |
| 					port: rep.port,
 | |
| 					username: rep.user,
 | |
| 					password: rep.pass,
 | |
| 					database: rep.db,
 | |
| 				})),
 | |
| 			},
 | |
| 		} : {}),
 | |
| 		synchronize: process.env.NODE_ENV === 'test',
 | |
| 		dropSchema: process.env.NODE_ENV === 'test',
 | |
| 		cache: !config.db.disableCache && process.env.NODE_ENV !== 'test' ? { // dbをcloseしても何故かredisのコネクションが内部的に残り続けるようで、テストの際に支障が出るため無効にする(キャッシュも含めてテストしたいため本当は有効にしたいが...)
 | |
| 			type: 'ioredis',
 | |
| 			options: {
 | |
| 				host: config.redis.host,
 | |
| 				port: config.redis.port,
 | |
| 				family: config.redis.family ?? 0,
 | |
| 				password: config.redis.pass,
 | |
| 				keyPrefix: `${config.redis.prefix}:query:`,
 | |
| 				db: config.redis.db ?? 0,
 | |
| 			},
 | |
| 		} : false,
 | |
| 		logging: log,
 | |
| 		logger: log ? new MyCustomLogger() : undefined,
 | |
| 		maxQueryExecutionTime: 300,
 | |
| 		entities: entities,
 | |
| 		migrations: ['../../migration/*.js'],
 | |
| 	});
 | |
| }
 |