Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 外部サイトからテーマ・プラグインのインストールができるように #12034

Merged
merged 30 commits into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4ab9eb7
Feat: 外部サイトからテーマ・プラグインのインストールができるように
kakkokari-gtyih Oct 14, 2023
1369b50
Update Changelog
kakkokari-gtyih Oct 14, 2023
43e655f
Change Changelog
kakkokari-gtyih Oct 14, 2023
1d7331d
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 14, 2023
7e876ee
Remove unnecessary imports
kakkokari-gtyih Oct 14, 2023
2dd1378
Merge branch 'external-resources' of https://github.com/kakkokari-gty…
kakkokari-gtyih Oct 14, 2023
9522a36
Update fetch-external-resources.ts
kakkokari-gtyih Oct 15, 2023
2224323
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 15, 2023
29bb48e
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 16, 2023
03b3738
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 16, 2023
d5ac685
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 16, 2023
1635a46
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 17, 2023
578fb2f
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 17, 2023
dade114
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 18, 2023
2d37302
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 18, 2023
4da664f
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 18, 2023
c043ed6
Update CHANGELOG.md
kakkokari-gtyih Oct 18, 2023
c219c55
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 19, 2023
6cd0d6c
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 19, 2023
bad6e00
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 19, 2023
48cf4e6
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 19, 2023
f10ad5a
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 19, 2023
10f47af
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 20, 2023
e204899
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 20, 2023
2190350
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 21, 2023
c2cdec4
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 21, 2023
14930c5
Update CHANGELOG.md
kakkokari-gtyih Oct 21, 2023
5bd58ca
Merge remote-tracking branch 'msky/develop' into external-resources
kakkokari-gtyih Oct 21, 2023
82bb8a7
Merge branch 'external-resources' of https://github.com/kakkokari-gty…
kakkokari-gtyih Oct 21, 2023
f2b5974
Merge branch 'develop' into external-resources
kakkokari-gtyih Oct 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@

-->

## 2023.x.x (unreleased)

### General
-

## Client
- Feat: プラグイン・テーマを外部サイトから直接インストールできるようになりました
- 外部サイトでの実装が必要です。詳細は Misskey Hub をご覧ください
https://misskey-hub.net/docs/advanced/publish-on-your-website.html

### Server
-

## 2023.10.2

### General
Expand Down
55 changes: 55 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2313,6 +2313,61 @@ export interface Locale {
"attachedNotes": string;
"thisPageCanBeSeenFromTheAuthor": string;
};
"_externalResourceInstaller": {
"title": string;
"checkVendorBeforeInstall": string;
"_plugin": {
"title": string;
"metaTitle": string;
};
"_theme": {
"title": string;
"metaTitle": string;
};
"_meta": {
"base": string;
};
"_vendorInfo": {
"title": string;
"endpoint": string;
"hashVerify": string;
};
"_errors": {
"_invalidParams": {
"title": string;
"description": string;
};
"_resourceTypeNotSupported": {
"title": string;
"description": string;
};
"_failedToFetch": {
"title": string;
"fetchErrorDescription": string;
"parseErrorDescription": string;
};
"_hashUnmatched": {
"title": string;
"description": string;
};
"_pluginParseFailed": {
"title": string;
"description": string;
};
"_pluginInstallFailed": {
"title": string;
"description": string;
};
"_themeParseFailed": {
"title": string;
"description": string;
};
"_themeInstallFailed": {
"title": string;
"description": string;
};
};
};
}
declare const locales: {
[lang: string]: Locale;
Expand Down
42 changes: 42 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2225,3 +2225,45 @@ _fileViewer:
uploadedAt: "追加日"
attachedNotes: "添付されているノート"
thisPageCanBeSeenFromTheAuthor: "このページは、このファイルをアップロードしたユーザーしか閲覧できません。"

_externalResourceInstaller:
title: "外部サイトからインストール"
checkVendorBeforeInstall: "配布元が信頼できるかを確認した上でインストールしてください。"
_plugin:
title: "このプラグインをインストールしますか?"
metaTitle: "プラグイン情報"
_theme:
title: "このテーマをインストールしますか?"
metaTitle: "テーマ情報"
_meta:
base: "基本のカラースキーム"
_vendorInfo:
title: "配布元情報"
endpoint: "参照したエンドポイント"
hashVerify: "ファイル整合性の確認"
_errors:
_invalidParams:
title: "パラメータが不足しています"
description: "外部サイトからデータを取得するために必要な情報が不足しています。URLをお確かめください。"
_resourceTypeNotSupported:
title: "この外部リソースには対応していません"
description: "この外部サイトから取得したリソースの種別には対応していません。サイト管理者にお問い合わせください。"
_failedToFetch:
title: "データの取得に失敗しました"
fetchErrorDescription: "外部サイトとの通信に失敗しました。もう一度試しても改善しない場合、サイト管理者にお問い合わせください。"
parseErrorDescription: "外部サイトから取得したデータが読み取れませんでした。サイト管理者にお問い合わせください。"
_hashUnmatched:
title: "正しいデータが取得できませんでした"
description: "提供されたデータの整合性の確認に失敗しました。セキュリティ上、インストールは続行できません。サイト管理者にお問い合わせください。"
_pluginParseFailed:
title: "AiScript エラー"
description: "データは取得できたものの、AiScriptの解析時にエラーがあったため読み込めませんでした。プラグインの作者にお問い合わせください。エラーの詳細はJavascriptコンソールをご確認ください。"
_pluginInstallFailed:
title: "プラグインのインストールに失敗しました"
description: "プラグインのインストール中に問題が発生しました。もう一度お試しください。エラーの詳細はJavascriptコンソールをご覧ください。"
_themeParseFailed:
title: "テーマ解析エラー"
description: "データは取得できたものの、テーマファイルの解析時にエラーがあったため読み込めませんでした。テーマの作者にお問い合わせください。エラーの詳細はJavascriptコンソールをご確認ください。"
_themeInstallFailed:
title: "テーマのインストールに失敗しました"
description: "テーマのインストール中に問題が発生しました。もう一度お試しください。エラーの詳細はJavascriptコンソールをご覧ください。"
4 changes: 4 additions & 0 deletions packages/backend/src/server/api/EndpointsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -1073,6 +1075,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$users_achievements,
$users_updateMemo,
$fetchRss,
$fetchExternalResources,
$retention,
],
exports: [
Expand Down Expand Up @@ -1424,6 +1427,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$users_achievements,
$users_updateMemo,
$fetchRss,
$fetchExternalResources,
$retention,
],
})
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/server/api/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -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],
];

Expand Down
Original file line number Diff line number Diff line change
@@ -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,
};
});
}
}
23 changes: 14 additions & 9 deletions packages/frontend/src/components/global/MkUrl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,28 @@ import * as os from '@/os.js';
import { useTooltip } from '@/scripts/use-tooltip.js';
import { safeURIDecode } from '@/scripts/safe-uri-decode.js';

const props = defineProps<{
const props = withDefaults(defineProps<{
url: string;
rel?: string;
}>();
showUrlPreview?: boolean;
}>(), {
showUrlPreview: true,
});

const self = props.url.startsWith(local);
const url = new URL(props.url);
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('invalid url');
const el = ref();

useTooltip(el, (showing) => {
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
showing,
url: props.url,
source: el.value,
}, {}, 'closed');
});
if (props.showUrlPreview) {
useTooltip(el, (showing) => {
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
showing,
url: props.url,
source: el.value,
}, {}, 'closed');
});
}

const schema = url.protocol;
const hostname = decodePunycode(url.hostname);
Expand Down
Loading
Loading