diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 9e8be4b71..f8ef6c1f3 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1164,6 +1164,12 @@ admin/views/instance.vue: smtp-port: "SMTPポート" smtp-user: "SMTPユーザー" smtp-pass: "SMTPパスワード" + serviceworker-config: "ServiceWorker" + enable-serviceworker: "ServiceWorkerを有効にする" + serviceworker-info: "プッシュ通知を行うには有効する必要があります。" + vapid-publickey: "VAPID公開鍵" + vapid-privatekey: "VAPID秘密鍵" + vapid-info: "ServiceWorkerを有効にする場合、VAPIDキーペアを生成する必要があります。シェルで次のようにします:" admin/views/charts.vue: title: "チャート" diff --git a/src/client/app/admin/views/instance.vue b/src/client/app/admin/views/instance.vue index b34aa03e3..5a29da034 100644 --- a/src/client/app/admin/views/instance.vue +++ b/src/client/app/admin/views/instance.vue @@ -57,6 +57,15 @@ {{ $t('smtp-secure') }}{{ $t('smtp-secure-info') }} +
+
{{ $t('serviceworker-config') }}
+ {{ $t('enable-serviceworker') }}{{ $t('serviceworker-info') }} + {{ $t('vapid-info') }}
npm i web-push -g
web-push generate-vapid-keys
+ + {{ $t('vapid-publickey') }} + {{ $t('vapid-privatekey') }} + +
summaly Proxy
URL @@ -126,7 +135,7 @@ import Vue from 'vue'; import i18n from '../../i18n'; import { url, host } from '../../config'; import { toUnicode } from 'punycode'; -import { faHeadset, faShieldAlt, faGhost, faUserPlus } from '@fortawesome/free-solid-svg-icons'; +import { faHeadset, faShieldAlt, faGhost, faUserPlus, faBolt } from '@fortawesome/free-solid-svg-icons'; import { faEnvelope as farEnvelope } from '@fortawesome/free-regular-svg-icons'; export default Vue.extend({ @@ -174,7 +183,10 @@ export default Vue.extend({ smtpPort: null, smtpUser: null, smtpPass: null, - faHeadset, faShieldAlt, faGhost, faUserPlus, farEnvelope + enableServiceWorker: false, + swPublicKey: null, + swPrivateKey: null, + faHeadset, faShieldAlt, faGhost, faUserPlus, farEnvelope, faBolt }; }, @@ -217,6 +229,9 @@ export default Vue.extend({ this.smtpPort = meta.smtpPort; this.smtpUser = meta.smtpUser; this.smtpPass = meta.smtpPass; + this.enableServiceWorker = meta.enableServiceWorker; + this.swPublicKey = meta.swPublickey; + this.swPrivateKey = meta.swPrivateKey; }); }, @@ -270,7 +285,10 @@ export default Vue.extend({ smtpHost: this.smtpHost, smtpPort: parseInt(this.smtpPort, 10), smtpUser: this.smtpUser, - smtpPass: this.smtpPass + smtpPass: this.smtpPass, + enableServiceWorker: this.enableServiceWorker, + swPublicKey: this.swPublicKey, + swPrivateKey: this.swPrivateKey }).then(() => { this.$root.dialog({ type: 'success', diff --git a/src/config/types.ts b/src/config/types.ts index 6ca3e3b7f..2ce9c0c80 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -39,14 +39,6 @@ export type Source = { accesslog?: string; - /** - * Service Worker - */ - sw?: { - publicKey: string; - privateKey: string; - }; - clusterLimit?: number; }; diff --git a/src/misc/fetch-meta.ts b/src/misc/fetch-meta.ts index 229c00620..a49e4dbe7 100644 --- a/src/misc/fetch-meta.ts +++ b/src/misc/fetch-meta.ts @@ -19,7 +19,8 @@ const defaultMeta: any = { enableExternalUserRecommendation: false, externalUserRecommendationEngine: 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}', externalUserRecommendationTimeout: 300000, - errorImageUrl: 'https://ai.misskey.xyz/aiart/yubitun.png' + errorImageUrl: 'https://ai.misskey.xyz/aiart/yubitun.png', + enableServiceWorker: false }; export default async function(): Promise { diff --git a/src/models/meta.ts b/src/models/meta.ts index 66cdf76d3..b40fabdfc 100644 --- a/src/models/meta.ts +++ b/src/models/meta.ts @@ -223,4 +223,8 @@ export type IMeta = { smtpPort?: number; smtpUser?: string; smtpPass?: string; + + enableServiceWorker?: boolean; + swPublicKey?: string; + swPrivateKey?: string; }; diff --git a/src/push-sw.ts b/src/push-sw.ts index bfd3b94a5..58e695813 100644 --- a/src/push-sw.ts +++ b/src/push-sw.ts @@ -2,17 +2,26 @@ const push = require('web-push'); import * as mongo from 'mongodb'; import Subscription from './models/sw-subscription'; import config from './config'; +import fetchMeta from './misc/fetch-meta'; +import { IMeta } from './models/meta'; -if (config.sw) { - // アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録 - push.setVapidDetails( - config.url, - config.sw.publicKey, - config.sw.privateKey); -} +let meta: IMeta = null; + +setInterval(() => { + fetchMeta().then(m => { + meta = m; + + if (meta.enableServiceWorker) { + // アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録 + push.setVapidDetails(config.url, + meta.swPublicKey, + meta.swPrivateKey); + } + }); +}, 3000); export default async function(userId: mongo.ObjectID | string, type: string, body?: any) { - if (!config.sw) return; + if (!meta.enableServiceWorker) return; if (typeof userId === 'string') { userId = new mongo.ObjectID(userId); diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts index 5c156442e..6ceb2a98d 100644 --- a/src/server/api/endpoints/admin/update-meta.ts +++ b/src/server/api/endpoints/admin/update-meta.ts @@ -285,6 +285,27 @@ export const meta = { 'ja-JP': 'SMTPサーバのパスワード' } }, + + enableServiceWorker: { + validator: $.bool.optional, + desc: { + 'ja-JP': 'ServiceWorkerを有効にするか否か' + } + }, + + swPublicKey: { + validator: $.str.optional.nullable, + desc: { + 'ja-JP': 'ServiceWorkerのVAPIDキーペアの公開鍵' + } + }, + + swPrivateKey: { + validator: $.str.optional.nullable, + desc: { + 'ja-JP': 'ServiceWorkerのVAPIDキーペアの秘密鍵' + } + }, } }; @@ -447,6 +468,18 @@ export default define(meta, (ps) => new Promise(async (res, rej) => { set.errorImageUrl = ps.errorImageUrl; } + if (ps.enableServiceWorker !== undefined) { + set.enableServiceWorker = ps.enableServiceWorker; + } + + if (ps.swPublicKey !== undefined) { + set.swPublicKey = ps.swPublicKey; + } + + if (ps.swPrivateKey !== undefined) { + set.swPrivateKey = ps.swPrivateKey; + } + await Meta.update({}, { $set: set }, { upsert: true }); diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index 4df728025..57311426a 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -63,7 +63,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => { cacheRemoteFiles: instance.cacheRemoteFiles, enableRecaptcha: instance.enableRecaptcha, recaptchaSiteKey: instance.recaptchaSiteKey, - swPublickey: null, + swPublickey: instance.swPublicKey, bannerUrl: instance.bannerUrl, errorImageUrl: instance.errorImageUrl, maxNoteTextLength: instance.maxNoteTextLength, @@ -85,7 +85,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => { twitter: instance.enableTwitterIntegration, github: instance.enableGithubIntegration, discord: instance.enableDiscordIntegration, - serviceWorker: config.sw ? true : false, + serviceWorker: instance.enableServiceWorker, userRecommendation: { external: instance.enableExternalUserRecommendation, engine: instance.externalUserRecommendationEngine, @@ -114,6 +114,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => { response.smtpPort = instance.smtpPort; response.smtpUser = instance.smtpUser; response.smtpPass = instance.smtpPass; + response.swPrivateKey = instance.swPrivateKey; } res(response); diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts index c5c003bde..095c1b765 100644 --- a/src/server/api/endpoints/sw/register.ts +++ b/src/server/api/endpoints/sw/register.ts @@ -1,7 +1,7 @@ import $ from 'cafy'; import Subscription from '../../../../models/sw-subscription'; -import config from '../../../../config'; import define from '../../define'; +import fetchMeta from '../../../../misc/fetch-meta'; export const meta = { requireCredential: true, @@ -31,10 +31,12 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => { deletedAt: { $exists: false } }); + const instance = await fetchMeta(); + if (exist != null) { return res({ state: 'already-subscribed', - key: config.sw.publicKey + key: instance.swPublicKey }); } @@ -47,6 +49,6 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => { res({ state: 'subscribed', - key: config.sw.publicKey + key: instance.swPublicKey }); }));