Feat: 外部サイトからテーマ・プラグインのインストールができるように (#12034)
* Feat: 外部サイトからテーマ・プラグインのインストールができるように * Update Changelog * Change Changelog * Remove unnecessary imports * Update fetch-external-resources.ts * Update CHANGELOG.md * Update CHANGELOG.md
This commit is contained in:
		| @@ -357,6 +357,7 @@ import * as ep___users_show from './endpoints/users/show.js'; | ||||
| import * as ep___users_achievements from './endpoints/users/achievements.js'; | ||||
| import * as ep___users_updateMemo from './endpoints/users/update-memo.js'; | ||||
| import * as ep___fetchRss from './endpoints/fetch-rss.js'; | ||||
| import * as ep___fetchExternalResources from './endpoints/fetch-external-resources.js'; | ||||
| import * as ep___retention from './endpoints/retention.js'; | ||||
| import { GetterService } from './GetterService.js'; | ||||
| import { ApiLoggerService } from './ApiLoggerService.js'; | ||||
| @@ -713,6 +714,7 @@ const $users_show: Provider = { provide: 'ep:users/show', useClass: ep___users_s | ||||
| const $users_achievements: Provider = { provide: 'ep:users/achievements', useClass: ep___users_achievements.default }; | ||||
| const $users_updateMemo: Provider = { provide: 'ep:users/update-memo', useClass: ep___users_updateMemo.default }; | ||||
| const $fetchRss: Provider = { provide: 'ep:fetch-rss', useClass: ep___fetchRss.default }; | ||||
| const $fetchExternalResources: Provider = { provide: 'ep:fetch-external-resources', useClass: ep___fetchExternalResources.default }; | ||||
| const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention.default }; | ||||
|  | ||||
| @Module({ | ||||
| @@ -1073,6 +1075,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention | ||||
| 		$users_achievements, | ||||
| 		$users_updateMemo, | ||||
| 		$fetchRss, | ||||
| 		$fetchExternalResources, | ||||
| 		$retention, | ||||
| 	], | ||||
| 	exports: [ | ||||
| @@ -1424,6 +1427,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention | ||||
| 		$users_achievements, | ||||
| 		$users_updateMemo, | ||||
| 		$fetchRss, | ||||
| 		$fetchExternalResources, | ||||
| 		$retention, | ||||
| 	], | ||||
| }) | ||||
|   | ||||
| @@ -357,6 +357,7 @@ import * as ep___users_show from './endpoints/users/show.js'; | ||||
| import * as ep___users_achievements from './endpoints/users/achievements.js'; | ||||
| import * as ep___users_updateMemo from './endpoints/users/update-memo.js'; | ||||
| import * as ep___fetchRss from './endpoints/fetch-rss.js'; | ||||
| import * as ep___fetchExternalResources from './endpoints/fetch-external-resources.js'; | ||||
| import * as ep___retention from './endpoints/retention.js'; | ||||
|  | ||||
| const eps = [ | ||||
| @@ -711,6 +712,7 @@ const eps = [ | ||||
| 	['users/achievements', ep___users_achievements], | ||||
| 	['users/update-memo', ep___users_updateMemo], | ||||
| 	['fetch-rss', ep___fetchRss], | ||||
| 	['fetch-external-resources', ep___fetchExternalResources], | ||||
| 	['retention', ep___retention], | ||||
| ]; | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,72 @@ | ||||
| /* | ||||
|  * SPDX-FileCopyrightText: syuilo and other misskey contributors | ||||
|  * SPDX-License-Identifier: AGPL-3.0-only | ||||
|  */ | ||||
|  | ||||
| import { createHash } from 'crypto'; | ||||
| import ms from 'ms'; | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { Endpoint } from '@/server/api/endpoint-base.js'; | ||||
| import { HttpRequestService } from '@/core/HttpRequestService.js'; | ||||
| import { ApiError } from '../error.js'; | ||||
|  | ||||
| export const meta = { | ||||
| 	tags: ['meta'], | ||||
|  | ||||
| 	requireCredential: true, | ||||
|  | ||||
| 	limit: { | ||||
| 		duration: ms('1hour'), | ||||
| 		max: 50, | ||||
| 	}, | ||||
|  | ||||
| 	errors: { | ||||
| 		invalidSchema: { | ||||
| 			message: 'External resource returned invalid schema.', | ||||
| 			code: 'EXT_RESOURCE_RETURNED_INVALID_SCHEMA', | ||||
| 			id: 'bb774091-7a15-4a70-9dc5-6ac8cf125856', | ||||
| 		}, | ||||
| 		hashUnmached: { | ||||
| 			message: 'Hash did not match.', | ||||
| 			code: 'EXT_RESOURCE_HASH_DIDNT_MATCH', | ||||
| 			id: '693ba8ba-b486-40df-a174-72f8279b56a4', | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | ||||
| export const paramDef = { | ||||
| 	type: 'object', | ||||
| 	properties: { | ||||
| 		url: { type: 'string' }, | ||||
| 		hash: { type: 'string' }, | ||||
| 	}, | ||||
| 	required: ['url', 'hash'], | ||||
| } as const; | ||||
|  | ||||
| @Injectable() | ||||
| export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export | ||||
| 	constructor( | ||||
| 		private httpRequestService: HttpRequestService, | ||||
| 	) { | ||||
| 		super(meta, paramDef, async (ps) => { | ||||
| 			const res = await this.httpRequestService.getJson<{ | ||||
| 				type: string; | ||||
| 				data: string; | ||||
| 			}>(ps.url); | ||||
|  | ||||
| 			if (!res.data || !res.type) { | ||||
| 				throw new ApiError(meta.errors.invalidSchema); | ||||
| 			} | ||||
|  | ||||
| 			const resHash = createHash('sha512').update(res.data.replace(/\r\n/g, '\n')).digest('hex'); | ||||
| 			if (resHash !== ps.hash) { | ||||
| 				throw new ApiError(meta.errors.hashUnmached); | ||||
| 			} | ||||
|  | ||||
| 			return { | ||||
| 				type: res.type, | ||||
| 				data: res.data, | ||||
| 			}; | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 かっこかり
					かっこかり