[backend] Automatically generate vapid/web-push keys

Co-authored-by: Johann150 (563f3672a9)
This commit is contained in:
Laura Hausmann 2023-10-13 19:17:30 +02:00
parent b53b7a8654
commit f14b3cec97
No known key found for this signature in database
GPG Key ID: D044E84C5BE01605
10 changed files with 35 additions and 94 deletions

View File

@ -15,12 +15,6 @@ This document describes things you can do after successfully installing Iceshrim
- Install [LibreTranslate](https://libretranslate.com/) - Install [LibreTranslate](https://libretranslate.com/)
- Get an API URL and API key, copy and paste them into Control Panel > General > Libre Translate - Get an API URL and API key, copy and paste them into Control Panel > General > Libre Translate
## Enabling push notifications
- Run `npx web-push generate-vapid-keys`
- Docker Compose users: `docker compose exec web npx web-push generate-vapid-keys`
- Put public and private keys into Control Panel > General > Service Worker
## Object Storage (S3) ## Object Storage (S3)
Recommended if using Docker Recommended if using Docker

View File

@ -0,0 +1,26 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import push from 'web-push';
export class AutoGenerateVapidKeys1697216726757 implements MigrationInterface {
// Based on FoundKey's 1668374092227-forceEnablePush.js
name = 'AutoGenerateVapidKeys1697216726757';
public async up(queryRunner: QueryRunner): Promise<void> {
// set VAPID keys if not yet set
const { publicKey, privateKey } = push.generateVAPIDKeys();
await queryRunner.query(`UPDATE "meta" SET "swPublicKey" = $1, "swPrivateKey" = $2 WHERE "swPublicKey" IS NULL OR "swPrivateKey" IS NULL`, [publicKey, privateKey]);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableServiceWorker"`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "swPublicKey" SET NOT NULL`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "swPrivateKey" SET NOT NULL`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "swPrivateKey" DROP NOT NULL`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "swPublicKey" DROP NOT NULL`);
await queryRunner.query(`ALTER TABLE "meta" ADD "enableServiceWorker" boolean NOT NULL DEFAULT false`);
// since VAPID keys are set and the service worker may have been enabled before, make sure it is now enabled
await queryRunner.query(`UPDATE "meta" SET "enableServiceWorker" = true`);
// can't unset the VAPID keys because we do not know if we set them in the migration
}
}

View File

@ -337,22 +337,17 @@ export class Meta {
}) })
public smtpPass: string | null; public smtpPass: string | null;
@Column("boolean", { @Column("varchar", {
default: false, length: 128,
nullable: false,
}) })
public enableServiceWorker: boolean; public swPublicKey: string;
@Column("varchar", { @Column("varchar", {
length: 128, length: 128,
nullable: true, nullable: false,
}) })
public swPublicKey: string | null; public swPrivateKey: string;
@Column("varchar", {
length: 128,
nullable: true,
})
public swPrivateKey: string | null;
@Column("boolean", { @Column("boolean", {
default: false, default: false,

View File

@ -156,11 +156,6 @@ export const meta = {
optional: false, optional: false,
nullable: false, nullable: false,
}, },
enableServiceWorker: {
type: "boolean",
optional: false,
nullable: false,
},
translatorAvailable: { translatorAvailable: {
type: "boolean", type: "boolean",
optional: false, optional: false,
@ -518,7 +513,6 @@ export default define(meta, paramDef, async (ps, me) => {
enableTwitterIntegration: instance.enableTwitterIntegration, enableTwitterIntegration: instance.enableTwitterIntegration,
enableGithubIntegration: instance.enableGithubIntegration, enableGithubIntegration: instance.enableGithubIntegration,
enableDiscordIntegration: instance.enableDiscordIntegration, enableDiscordIntegration: instance.enableDiscordIntegration,
enableServiceWorker: instance.enableServiceWorker,
translatorAvailable: translatorAvailable:
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null, instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
pinnedPages: instance.pinnedPages, pinnedPages: instance.pinnedPages,

View File

@ -148,7 +148,6 @@ export const paramDef = {
smtpPort: { type: "integer", nullable: true }, smtpPort: { type: "integer", nullable: true },
smtpUser: { type: "string", nullable: true }, smtpUser: { type: "string", nullable: true },
smtpPass: { type: "string", nullable: true }, smtpPass: { type: "string", nullable: true },
enableServiceWorker: { type: "boolean" },
swPublicKey: { type: "string", nullable: true }, swPublicKey: { type: "string", nullable: true },
swPrivateKey: { type: "string", nullable: true }, swPrivateKey: { type: "string", nullable: true },
tosUrl: { type: "string", nullable: true }, tosUrl: { type: "string", nullable: true },
@ -463,10 +462,6 @@ export default define(meta, paramDef, async (ps, me) => {
set.errorImageUrl = ps.errorImageUrl; set.errorImageUrl = ps.errorImageUrl;
} }
if (ps.enableServiceWorker !== undefined) {
set.enableServiceWorker = ps.enableServiceWorker;
}
if (ps.swPublicKey !== undefined) { if (ps.swPublicKey !== undefined) {
set.swPublicKey = ps.swPublicKey; set.swPublicKey = ps.swPublicKey;
} }

View File

@ -266,11 +266,6 @@ export const meta = {
optional: false, optional: false,
nullable: false, nullable: false,
}, },
enableServiceWorker: {
type: "boolean",
optional: false,
nullable: false,
},
translatorAvailable: { translatorAvailable: {
type: "boolean", type: "boolean",
optional: false, optional: false,
@ -377,13 +372,13 @@ export const meta = {
}, },
defaultReaction: { defaultReaction: {
type: "string", type: "string",
optional: "false", optional: false,
nullable: false, nullable: false,
default: "⭐", default: "⭐",
}, },
donationLink: { donationLink: {
type: "string", type: "string",
optional: "true", optional: true,
nullable: true, nullable: true,
}, },
}, },
@ -472,8 +467,6 @@ export default define(meta, paramDef, async (ps, me) => {
enableGithubIntegration: instance.enableGithubIntegration, enableGithubIntegration: instance.enableGithubIntegration,
enableDiscordIntegration: instance.enableDiscordIntegration, enableDiscordIntegration: instance.enableDiscordIntegration,
enableServiceWorker: instance.enableServiceWorker,
translatorAvailable: translatorAvailable:
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null, instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
defaultReaction: instance.defaultReaction, defaultReaction: instance.defaultReaction,
@ -515,7 +508,7 @@ export default define(meta, paramDef, async (ps, me) => {
twitter: instance.enableTwitterIntegration, twitter: instance.enableTwitterIntegration,
github: instance.enableGithubIntegration, github: instance.enableGithubIntegration,
discord: instance.enableDiscordIntegration, discord: instance.enableDiscordIntegration,
serviceWorker: instance.enableServiceWorker, serviceWorker: true,
postEditing: true, postEditing: true,
postImports: instance.experimentalFeatures?.postImports || false, postImports: instance.experimentalFeatures?.postImports || false,
miauth: true, miauth: true,

View File

@ -93,7 +93,6 @@ const nodeinfo2 = async () => {
enableGithubIntegration: meta.enableGithubIntegration, enableGithubIntegration: meta.enableGithubIntegration,
enableDiscordIntegration: meta.enableDiscordIntegration, enableDiscordIntegration: meta.enableDiscordIntegration,
enableEmail: meta.enableEmail, enableEmail: meta.enableEmail,
enableServiceWorker: meta.enableServiceWorker,
proxyAccountName: proxyAccount ? proxyAccount.username : null, proxyAccountName: proxyAccount ? proxyAccount.username : null,
themeColor: meta.themeColor || "#31748f", themeColor: meta.themeColor || "#31748f",
}, },

View File

@ -47,13 +47,6 @@ export async function pushNotification<T extends keyof pushNotificationsTypes>(
) { ) {
const meta = await fetchMeta(); const meta = await fetchMeta();
if (
!meta.enableServiceWorker ||
meta.swPublicKey == null ||
meta.swPrivateKey == null
)
return;
// アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録 // アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録
push.setVapidDetails(config.url, meta.swPublicKey, meta.swPrivateKey); push.setVapidDetails(config.url, meta.swPublicKey, meta.swPrivateKey);

View File

@ -317,44 +317,6 @@
</FormSplit> </FormSplit>
</FormSection> </FormSection>
<FormSection>
<template #label>ServiceWorker</template>
<FormSwitch
v-model="enableServiceWorker"
class="_formBlock"
>
<template #label>{{
i18n.ts.enableServiceworker
}}</template>
<template #caption>{{
i18n.ts.serviceworkerInfo
}}</template>
</FormSwitch>
<template v-if="enableServiceWorker">
<FormInput
v-model="swPublicKey"
class="_formBlock"
>
<template #prefix
><i class="ph-key ph-bold ph-lg"></i
></template>
<template #label>Public key</template>
</FormInput>
<FormInput
v-model="swPrivateKey"
class="_formBlock"
>
<template #prefix
><i class="ph-key ph-bold ph-lg"></i
></template>
<template #label>Private key</template>
</FormInput>
</template>
</FormSection>
<FormSection> <FormSection>
<template #label>Server Performance</template> <template #label>Server Performance</template>
<FormSwitch <FormSwitch
@ -467,9 +429,6 @@ let localDriveCapacityMb: any = $ref(0);
let remoteDriveCapacityMb: any = $ref(0); let remoteDriveCapacityMb: any = $ref(0);
let enableRegistration: boolean = $ref(false); let enableRegistration: boolean = $ref(false);
let emailRequiredForSignup: boolean = $ref(false); let emailRequiredForSignup: boolean = $ref(false);
let enableServiceWorker: boolean = $ref(false);
let swPublicKey: any = $ref(null);
let swPrivateKey: any = $ref(null);
let deeplAuthKey: string = $ref(""); let deeplAuthKey: string = $ref("");
let deeplIsPro: boolean = $ref(false); let deeplIsPro: boolean = $ref(false);
let libreTranslateApiUrl: string = $ref(""); let libreTranslateApiUrl: string = $ref("");
@ -507,9 +466,6 @@ async function init() {
remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb; remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb;
enableRegistration = !meta.disableRegistration; enableRegistration = !meta.disableRegistration;
emailRequiredForSignup = meta.emailRequiredForSignup; emailRequiredForSignup = meta.emailRequiredForSignup;
enableServiceWorker = meta.enableServiceWorker;
swPublicKey = meta.swPublickey;
swPrivateKey = meta.swPrivateKey;
deeplAuthKey = meta.deeplAuthKey; deeplAuthKey = meta.deeplAuthKey;
deeplIsPro = meta.deeplIsPro; deeplIsPro = meta.deeplIsPro;
libreTranslateApiUrl = meta.libreTranslateApiUrl; libreTranslateApiUrl = meta.libreTranslateApiUrl;
@ -554,9 +510,6 @@ function save() {
remoteDriveCapacityMb: parseInt(remoteDriveCapacityMb, 10), remoteDriveCapacityMb: parseInt(remoteDriveCapacityMb, 10),
disableRegistration: !enableRegistration, disableRegistration: !enableRegistration,
emailRequiredForSignup, emailRequiredForSignup,
enableServiceWorker,
swPublicKey,
swPrivateKey,
deeplAuthKey, deeplAuthKey,
deeplIsPro, deeplIsPro,
libreTranslateApiUrl, libreTranslateApiUrl,

View File

@ -299,7 +299,6 @@ export type LiteInstanceMetadata = {
enableTwitterIntegration: boolean; enableTwitterIntegration: boolean;
enableGithubIntegration: boolean; enableGithubIntegration: boolean;
enableDiscordIntegration: boolean; enableDiscordIntegration: boolean;
enableServiceWorker: boolean;
searchEngine: string; searchEngine: string;
emojis: CustomEmoji[]; emojis: CustomEmoji[];
images: { images: {