This commit is contained in:
syuilo 2018-12-20 04:08:13 +09:00
parent 710ba526fa
commit 454632d785
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
9 changed files with 91 additions and 25 deletions

View file

@ -1164,6 +1164,12 @@ admin/views/instance.vue:
smtp-port: "SMTPポート" smtp-port: "SMTPポート"
smtp-user: "SMTPユーザー" smtp-user: "SMTPユーザー"
smtp-pass: "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: admin/views/charts.vue:
title: "チャート" title: "チャート"

View file

@ -57,6 +57,15 @@
</ui-horizon-group> </ui-horizon-group>
<ui-switch v-model="smtpSecure" :disabled="!enableEmail">{{ $t('smtp-secure') }}<span slot="desc">{{ $t('smtp-secure-info') }}</span></ui-switch> <ui-switch v-model="smtpSecure" :disabled="!enableEmail">{{ $t('smtp-secure') }}<span slot="desc">{{ $t('smtp-secure-info') }}</span></ui-switch>
</section> </section>
<section>
<header><fa :icon="faBolt"/> {{ $t('serviceworker-config') }}</header>
<ui-switch v-model="enableServiceWorker">{{ $t('enable-serviceworker') }}<span slot="desc">{{ $t('serviceworker-info') }}</span></ui-switch>
<ui-info>{{ $t('vapid-info') }}<br><code>npm i web-push -g<br>web-push generate-vapid-keys</code></ui-info>
<ui-horizon-group inputs class="fit-bottom">
<ui-input v-model="swPublicKey" :disabled="!enableServiceWorker"><i slot="icon"><fa icon="key"/></i>{{ $t('vapid-publickey') }}</ui-input>
<ui-input v-model="swPrivateKey" :disabled="!enableServiceWorker"><i slot="icon"><fa icon="key"/></i>{{ $t('vapid-privatekey') }}</ui-input>
</ui-horizon-group>
</section>
<section> <section>
<header>summaly Proxy</header> <header>summaly Proxy</header>
<ui-input v-model="summalyProxy">URL</ui-input> <ui-input v-model="summalyProxy">URL</ui-input>
@ -126,7 +135,7 @@ import Vue from 'vue';
import i18n from '../../i18n'; import i18n from '../../i18n';
import { url, host } from '../../config'; import { url, host } from '../../config';
import { toUnicode } from 'punycode'; 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'; import { faEnvelope as farEnvelope } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({ export default Vue.extend({
@ -174,7 +183,10 @@ export default Vue.extend({
smtpPort: null, smtpPort: null,
smtpUser: null, smtpUser: null,
smtpPass: 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.smtpPort = meta.smtpPort;
this.smtpUser = meta.smtpUser; this.smtpUser = meta.smtpUser;
this.smtpPass = meta.smtpPass; 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, smtpHost: this.smtpHost,
smtpPort: parseInt(this.smtpPort, 10), smtpPort: parseInt(this.smtpPort, 10),
smtpUser: this.smtpUser, smtpUser: this.smtpUser,
smtpPass: this.smtpPass smtpPass: this.smtpPass,
enableServiceWorker: this.enableServiceWorker,
swPublicKey: this.swPublicKey,
swPrivateKey: this.swPrivateKey
}).then(() => { }).then(() => {
this.$root.dialog({ this.$root.dialog({
type: 'success', type: 'success',

View file

@ -39,14 +39,6 @@ export type Source = {
accesslog?: string; accesslog?: string;
/**
* Service Worker
*/
sw?: {
publicKey: string;
privateKey: string;
};
clusterLimit?: number; clusterLimit?: number;
}; };

View file

@ -19,7 +19,8 @@ const defaultMeta: any = {
enableExternalUserRecommendation: false, enableExternalUserRecommendation: false,
externalUserRecommendationEngine: 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}', externalUserRecommendationEngine: 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}',
externalUserRecommendationTimeout: 300000, 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<IMeta> { export default async function(): Promise<IMeta> {

View file

@ -223,4 +223,8 @@ export type IMeta = {
smtpPort?: number; smtpPort?: number;
smtpUser?: string; smtpUser?: string;
smtpPass?: string; smtpPass?: string;
enableServiceWorker?: boolean;
swPublicKey?: string;
swPrivateKey?: string;
}; };

View file

@ -2,17 +2,26 @@ const push = require('web-push');
import * as mongo from 'mongodb'; import * as mongo from 'mongodb';
import Subscription from './models/sw-subscription'; import Subscription from './models/sw-subscription';
import config from './config'; import config from './config';
import fetchMeta from './misc/fetch-meta';
import { IMeta } from './models/meta';
if (config.sw) { let meta: IMeta = null;
setInterval(() => {
fetchMeta().then(m => {
meta = m;
if (meta.enableServiceWorker) {
// アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録 // アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録
push.setVapidDetails( push.setVapidDetails(config.url,
config.url, meta.swPublicKey,
config.sw.publicKey, meta.swPrivateKey);
config.sw.privateKey);
} }
});
}, 3000);
export default async function(userId: mongo.ObjectID | string, type: string, body?: any) { export default async function(userId: mongo.ObjectID | string, type: string, body?: any) {
if (!config.sw) return; if (!meta.enableServiceWorker) return;
if (typeof userId === 'string') { if (typeof userId === 'string') {
userId = new mongo.ObjectID(userId); userId = new mongo.ObjectID(userId);

View file

@ -285,6 +285,27 @@ export const meta = {
'ja-JP': 'SMTPサーバのパスワード' '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; 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({}, { await Meta.update({}, {
$set: set $set: set
}, { upsert: true }); }, { upsert: true });

View file

@ -63,7 +63,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
cacheRemoteFiles: instance.cacheRemoteFiles, cacheRemoteFiles: instance.cacheRemoteFiles,
enableRecaptcha: instance.enableRecaptcha, enableRecaptcha: instance.enableRecaptcha,
recaptchaSiteKey: instance.recaptchaSiteKey, recaptchaSiteKey: instance.recaptchaSiteKey,
swPublickey: null, swPublickey: instance.swPublicKey,
bannerUrl: instance.bannerUrl, bannerUrl: instance.bannerUrl,
errorImageUrl: instance.errorImageUrl, errorImageUrl: instance.errorImageUrl,
maxNoteTextLength: instance.maxNoteTextLength, maxNoteTextLength: instance.maxNoteTextLength,
@ -85,7 +85,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
twitter: instance.enableTwitterIntegration, twitter: instance.enableTwitterIntegration,
github: instance.enableGithubIntegration, github: instance.enableGithubIntegration,
discord: instance.enableDiscordIntegration, discord: instance.enableDiscordIntegration,
serviceWorker: config.sw ? true : false, serviceWorker: instance.enableServiceWorker,
userRecommendation: { userRecommendation: {
external: instance.enableExternalUserRecommendation, external: instance.enableExternalUserRecommendation,
engine: instance.externalUserRecommendationEngine, engine: instance.externalUserRecommendationEngine,
@ -114,6 +114,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
response.smtpPort = instance.smtpPort; response.smtpPort = instance.smtpPort;
response.smtpUser = instance.smtpUser; response.smtpUser = instance.smtpUser;
response.smtpPass = instance.smtpPass; response.smtpPass = instance.smtpPass;
response.swPrivateKey = instance.swPrivateKey;
} }
res(response); res(response);

View file

@ -1,7 +1,7 @@
import $ from 'cafy'; import $ from 'cafy';
import Subscription from '../../../../models/sw-subscription'; import Subscription from '../../../../models/sw-subscription';
import config from '../../../../config';
import define from '../../define'; import define from '../../define';
import fetchMeta from '../../../../misc/fetch-meta';
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -31,10 +31,12 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
deletedAt: { $exists: false } deletedAt: { $exists: false }
}); });
const instance = await fetchMeta();
if (exist != null) { if (exist != null) {
return res({ return res({
state: 'already-subscribed', 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({ res({
state: 'subscribed', state: 'subscribed',
key: config.sw.publicKey key: instance.swPublicKey
}); });
})); }));