diff options
author | Chocobozzz <me@florianbigard.com> | 2021-03-11 16:54:52 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-03-24 18:18:41 +0100 |
commit | 32a18cbf33a7cdbbe3d4885d32e4b67e19cdc1cf (patch) | |
tree | 1db53245688a6b7839cab00f9d65e6c1c1774b00 /server/lib | |
parent | 3fbc6974334ca58c068f0f9def0b0a40db2a6de1 (diff) | |
download | PeerTube-32a18cbf33a7cdbbe3d4885d32e4b67e19cdc1cf.tar.gz PeerTube-32a18cbf33a7cdbbe3d4885d32e4b67e19cdc1cf.tar.zst PeerTube-32a18cbf33a7cdbbe3d4885d32e4b67e19cdc1cf.zip |
Add new plugin/peertube version notifs
Diffstat (limited to 'server/lib')
-rw-r--r-- | server/lib/emailer.ts | 42 | ||||
-rw-r--r-- | server/lib/emails/peertube-version-new/html.pug | 9 | ||||
-rw-r--r-- | server/lib/emails/plugin-version-new/html.pug | 9 | ||||
-rw-r--r-- | server/lib/notifier.ts | 74 | ||||
-rw-r--r-- | server/lib/schedulers/peertube-version-check-scheduler.ts | 55 | ||||
-rw-r--r-- | server/lib/schedulers/plugins-check-scheduler.ts | 6 | ||||
-rw-r--r-- | server/lib/user.ts | 4 |
7 files changed, 194 insertions, 5 deletions
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts index 969eae77b..187d4e86d 100644 --- a/server/lib/emailer.ts +++ b/server/lib/emailer.ts | |||
@@ -12,7 +12,7 @@ import { isTestInstance, root } from '../helpers/core-utils' | |||
12 | import { bunyanLogger, logger } from '../helpers/logger' | 12 | import { bunyanLogger, logger } from '../helpers/logger' |
13 | import { CONFIG, isEmailEnabled } from '../initializers/config' | 13 | import { CONFIG, isEmailEnabled } from '../initializers/config' |
14 | import { WEBSERVER } from '../initializers/constants' | 14 | import { WEBSERVER } from '../initializers/constants' |
15 | import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorFollowFull, MUser } from '../types/models' | 15 | import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorFollowFull, MPlugin, MUser } from '../types/models' |
16 | import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video' | 16 | import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video' |
17 | import { JobQueue } from './job-queue' | 17 | import { JobQueue } from './job-queue' |
18 | 18 | ||
@@ -403,7 +403,7 @@ class Emailer { | |||
403 | } | 403 | } |
404 | 404 | ||
405 | async addVideoAutoBlacklistModeratorsNotification (to: string[], videoBlacklist: MVideoBlacklistLightVideo) { | 405 | async addVideoAutoBlacklistModeratorsNotification (to: string[], videoBlacklist: MVideoBlacklistLightVideo) { |
406 | const VIDEO_AUTO_BLACKLIST_URL = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list' | 406 | const videoAutoBlacklistUrl = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list' |
407 | const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath() | 407 | const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath() |
408 | const channel = (await VideoChannelModel.loadByIdAndPopulateAccount(videoBlacklist.Video.channelId)).toFormattedSummaryJSON() | 408 | const channel = (await VideoChannelModel.loadByIdAndPopulateAccount(videoBlacklist.Video.channelId)).toFormattedSummaryJSON() |
409 | 409 | ||
@@ -417,7 +417,7 @@ class Emailer { | |||
417 | videoName: videoBlacklist.Video.name, | 417 | videoName: videoBlacklist.Video.name, |
418 | action: { | 418 | action: { |
419 | text: 'Review autoblacklist', | 419 | text: 'Review autoblacklist', |
420 | url: VIDEO_AUTO_BLACKLIST_URL | 420 | url: videoAutoBlacklistUrl |
421 | } | 421 | } |
422 | } | 422 | } |
423 | } | 423 | } |
@@ -472,6 +472,42 @@ class Emailer { | |||
472 | return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) | 472 | return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) |
473 | } | 473 | } |
474 | 474 | ||
475 | addNewPeerTubeVersionNotification (to: string[], latestVersion: string) { | ||
476 | const subject = `A new PeerTube version is available: ${latestVersion}` | ||
477 | |||
478 | const emailPayload: EmailPayload = { | ||
479 | to, | ||
480 | template: 'peertube-version-new', | ||
481 | subject, | ||
482 | text: subject, | ||
483 | locals: { | ||
484 | latestVersion | ||
485 | } | ||
486 | } | ||
487 | |||
488 | return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) | ||
489 | } | ||
490 | |||
491 | addNewPlugionVersionNotification (to: string[], plugin: MPlugin) { | ||
492 | const pluginUrl = WEBSERVER.URL + '/admin/plugins/list-installed?pluginType=' + plugin.type | ||
493 | |||
494 | const subject = `A new plugin/theme version is available: ${plugin.name}@${plugin.latestVersion}` | ||
495 | |||
496 | const emailPayload: EmailPayload = { | ||
497 | to, | ||
498 | template: 'plugin-version-new', | ||
499 | subject, | ||
500 | text: subject, | ||
501 | locals: { | ||
502 | pluginName: plugin.name, | ||
503 | latestVersion: plugin.latestVersion, | ||
504 | pluginUrl | ||
505 | } | ||
506 | } | ||
507 | |||
508 | return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) | ||
509 | } | ||
510 | |||
475 | addPasswordResetEmailJob (username: string, to: string, resetPasswordUrl: string) { | 511 | addPasswordResetEmailJob (username: string, to: string, resetPasswordUrl: string) { |
476 | const emailPayload: EmailPayload = { | 512 | const emailPayload: EmailPayload = { |
477 | template: 'password-reset', | 513 | template: 'password-reset', |
diff --git a/server/lib/emails/peertube-version-new/html.pug b/server/lib/emails/peertube-version-new/html.pug new file mode 100644 index 000000000..2f4d9399d --- /dev/null +++ b/server/lib/emails/peertube-version-new/html.pug | |||
@@ -0,0 +1,9 @@ | |||
1 | extends ../common/greetings | ||
2 | |||
3 | block title | ||
4 | | New PeerTube version available | ||
5 | |||
6 | block content | ||
7 | p | ||
8 | | A new version of PeerTube is available: #{latestVersion}. | ||
9 | | You can check the latest news on #[a(href="https://joinpeertube.org/news") JoinPeerTube]. | ||
diff --git a/server/lib/emails/plugin-version-new/html.pug b/server/lib/emails/plugin-version-new/html.pug new file mode 100644 index 000000000..86d3d87e8 --- /dev/null +++ b/server/lib/emails/plugin-version-new/html.pug | |||
@@ -0,0 +1,9 @@ | |||
1 | extends ../common/greetings | ||
2 | |||
3 | block title | ||
4 | | New plugin version available | ||
5 | |||
6 | block content | ||
7 | p | ||
8 | | A new version of the plugin/theme #{pluginName} is available: #{latestVersion}. | ||
9 | | You might want to upgrade it on #[a(href=pluginUrl) the PeerTube admin interface]. | ||
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts index 740c274d7..da7f7cc05 100644 --- a/server/lib/notifier.ts +++ b/server/lib/notifier.ts | |||
@@ -19,7 +19,7 @@ import { CONFIG } from '../initializers/config' | |||
19 | import { AccountBlocklistModel } from '../models/account/account-blocklist' | 19 | import { AccountBlocklistModel } from '../models/account/account-blocklist' |
20 | import { UserModel } from '../models/account/user' | 20 | import { UserModel } from '../models/account/user' |
21 | import { UserNotificationModel } from '../models/account/user-notification' | 21 | import { UserNotificationModel } from '../models/account/user-notification' |
22 | import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull } from '../types/models' | 22 | import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull, MApplication, MPlugin } from '../types/models' |
23 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' | 23 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' |
24 | import { isBlockedByServerOrAccount } from './blocklist' | 24 | import { isBlockedByServerOrAccount } from './blocklist' |
25 | import { Emailer } from './emailer' | 25 | import { Emailer } from './emailer' |
@@ -144,6 +144,20 @@ class Notifier { | |||
144 | }) | 144 | }) |
145 | } | 145 | } |
146 | 146 | ||
147 | notifyOfNewPeerTubeVersion (application: MApplication, latestVersion: string) { | ||
148 | this.notifyAdminsOfNewPeerTubeVersion(application, latestVersion) | ||
149 | .catch(err => { | ||
150 | logger.error('Cannot notify on new PeerTubeb version %s.', latestVersion, { err }) | ||
151 | }) | ||
152 | } | ||
153 | |||
154 | notifyOfNewPluginVersion (plugin: MPlugin) { | ||
155 | this.notifyAdminsOfNewPluginVersion(plugin) | ||
156 | .catch(err => { | ||
157 | logger.error('Cannot notify on new plugin version %s.', plugin.name, { err }) | ||
158 | }) | ||
159 | } | ||
160 | |||
147 | private async notifySubscribersOfNewVideo (video: MVideoAccountLight) { | 161 | private async notifySubscribersOfNewVideo (video: MVideoAccountLight) { |
148 | // List all followers that are users | 162 | // List all followers that are users |
149 | const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId) | 163 | const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId) |
@@ -667,6 +681,64 @@ class Notifier { | |||
667 | return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender }) | 681 | return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender }) |
668 | } | 682 | } |
669 | 683 | ||
684 | private async notifyAdminsOfNewPeerTubeVersion (application: MApplication, latestVersion: string) { | ||
685 | // Use the debug right to know who is an administrator | ||
686 | const admins = await UserModel.listWithRight(UserRight.MANAGE_DEBUG) | ||
687 | if (admins.length === 0) return | ||
688 | |||
689 | logger.info('Notifying %s admins of new PeerTube version %s.', admins.length, latestVersion) | ||
690 | |||
691 | function settingGetter (user: MUserWithNotificationSetting) { | ||
692 | return user.NotificationSetting.newPeerTubeVersion | ||
693 | } | ||
694 | |||
695 | async function notificationCreator (user: MUserWithNotificationSetting) { | ||
696 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
697 | type: UserNotificationType.NEW_PEERTUBE_VERSION, | ||
698 | userId: user.id, | ||
699 | applicationId: application.id | ||
700 | }) | ||
701 | notification.Application = application | ||
702 | |||
703 | return notification | ||
704 | } | ||
705 | |||
706 | function emailSender (emails: string[]) { | ||
707 | return Emailer.Instance.addNewPeerTubeVersionNotification(emails, latestVersion) | ||
708 | } | ||
709 | |||
710 | return this.notify({ users: admins, settingGetter, notificationCreator, emailSender }) | ||
711 | } | ||
712 | |||
713 | private async notifyAdminsOfNewPluginVersion (plugin: MPlugin) { | ||
714 | // Use the debug right to know who is an administrator | ||
715 | const admins = await UserModel.listWithRight(UserRight.MANAGE_DEBUG) | ||
716 | if (admins.length === 0) return | ||
717 | |||
718 | logger.info('Notifying %s admins of new plugin version %s@%s.', admins.length, plugin.name, plugin.latestVersion) | ||
719 | |||
720 | function settingGetter (user: MUserWithNotificationSetting) { | ||
721 | return user.NotificationSetting.newPluginVersion | ||
722 | } | ||
723 | |||
724 | async function notificationCreator (user: MUserWithNotificationSetting) { | ||
725 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
726 | type: UserNotificationType.NEW_PLUGIN_VERSION, | ||
727 | userId: user.id, | ||
728 | pluginId: plugin.id | ||
729 | }) | ||
730 | notification.Plugin = plugin | ||
731 | |||
732 | return notification | ||
733 | } | ||
734 | |||
735 | function emailSender (emails: string[]) { | ||
736 | return Emailer.Instance.addNewPlugionVersionNotification(emails, plugin) | ||
737 | } | ||
738 | |||
739 | return this.notify({ users: admins, settingGetter, notificationCreator, emailSender }) | ||
740 | } | ||
741 | |||
670 | private async notify<T extends MUserWithNotificationSetting> (options: { | 742 | private async notify<T extends MUserWithNotificationSetting> (options: { |
671 | users: T[] | 743 | users: T[] |
672 | notificationCreator: (user: T) => Promise<UserNotificationModelForApi> | 744 | notificationCreator: (user: T) => Promise<UserNotificationModelForApi> |
diff --git a/server/lib/schedulers/peertube-version-check-scheduler.ts b/server/lib/schedulers/peertube-version-check-scheduler.ts new file mode 100644 index 000000000..c8960465c --- /dev/null +++ b/server/lib/schedulers/peertube-version-check-scheduler.ts | |||
@@ -0,0 +1,55 @@ | |||
1 | |||
2 | import { doJSONRequest } from '@server/helpers/requests' | ||
3 | import { ApplicationModel } from '@server/models/application/application' | ||
4 | import { compareSemVer } from '@shared/core-utils' | ||
5 | import { JoinPeerTubeVersions } from '@shared/models' | ||
6 | import { logger } from '../../helpers/logger' | ||
7 | import { CONFIG } from '../../initializers/config' | ||
8 | import { PEERTUBE_VERSION, SCHEDULER_INTERVALS_MS } from '../../initializers/constants' | ||
9 | import { Notifier } from '../notifier' | ||
10 | import { AbstractScheduler } from './abstract-scheduler' | ||
11 | |||
12 | export class PeerTubeVersionCheckScheduler extends AbstractScheduler { | ||
13 | |||
14 | private static instance: AbstractScheduler | ||
15 | |||
16 | protected schedulerIntervalMs = SCHEDULER_INTERVALS_MS.checkPeerTubeVersion | ||
17 | |||
18 | private constructor () { | ||
19 | super() | ||
20 | } | ||
21 | |||
22 | protected async internalExecute () { | ||
23 | return this.checkLatestVersion() | ||
24 | } | ||
25 | |||
26 | private async checkLatestVersion () { | ||
27 | if (CONFIG.PEERTUBE.CHECK_LATEST_VERSION.ENABLED === false) return | ||
28 | |||
29 | logger.info('Checking latest PeerTube version.') | ||
30 | |||
31 | const { body } = await doJSONRequest<JoinPeerTubeVersions>(CONFIG.PEERTUBE.CHECK_LATEST_VERSION.URL) | ||
32 | |||
33 | if (!body?.peertube?.latestVersion) { | ||
34 | logger.warn('Cannot check latest PeerTube version: body is invalid.', { body }) | ||
35 | return | ||
36 | } | ||
37 | |||
38 | const latestVersion = body.peertube.latestVersion | ||
39 | const application = await ApplicationModel.load() | ||
40 | |||
41 | // Already checked this version | ||
42 | if (application.latestPeerTubeVersion === latestVersion) return | ||
43 | |||
44 | if (compareSemVer(PEERTUBE_VERSION, latestVersion) < 0) { | ||
45 | application.latestPeerTubeVersion = latestVersion | ||
46 | await application.save() | ||
47 | |||
48 | Notifier.Instance.notifyOfNewPeerTubeVersion(application, latestVersion) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | static get Instance () { | ||
53 | return this.instance || (this.instance = new this()) | ||
54 | } | ||
55 | } | ||
diff --git a/server/lib/schedulers/plugins-check-scheduler.ts b/server/lib/schedulers/plugins-check-scheduler.ts index 014993e94..9a1ae3ec5 100644 --- a/server/lib/schedulers/plugins-check-scheduler.ts +++ b/server/lib/schedulers/plugins-check-scheduler.ts | |||
@@ -6,6 +6,7 @@ import { PluginModel } from '../../models/server/plugin' | |||
6 | import { chunk } from 'lodash' | 6 | import { chunk } from 'lodash' |
7 | import { getLatestPluginsVersion } from '../plugins/plugin-index' | 7 | import { getLatestPluginsVersion } from '../plugins/plugin-index' |
8 | import { compareSemVer } from '../../../shared/core-utils/miscs/miscs' | 8 | import { compareSemVer } from '../../../shared/core-utils/miscs/miscs' |
9 | import { Notifier } from '../notifier' | ||
9 | 10 | ||
10 | export class PluginsCheckScheduler extends AbstractScheduler { | 11 | export class PluginsCheckScheduler extends AbstractScheduler { |
11 | 12 | ||
@@ -53,6 +54,11 @@ export class PluginsCheckScheduler extends AbstractScheduler { | |||
53 | plugin.latestVersion = result.latestVersion | 54 | plugin.latestVersion = result.latestVersion |
54 | await plugin.save() | 55 | await plugin.save() |
55 | 56 | ||
57 | // Notify if there is an higher plugin version available | ||
58 | if (compareSemVer(plugin.version, result.latestVersion) < 0) { | ||
59 | Notifier.Instance.notifyOfNewPluginVersion(plugin) | ||
60 | } | ||
61 | |||
56 | logger.info('Plugin %s has a new latest version %s.', result.npmName, plugin.latestVersion) | 62 | logger.info('Plugin %s has a new latest version %s.', result.npmName, plugin.latestVersion) |
57 | } | 63 | } |
58 | } | 64 | } |
diff --git a/server/lib/user.ts b/server/lib/user.ts index e1892f22c..9b0a0a2f1 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -193,7 +193,9 @@ function createDefaultUserNotificationSettings (user: MUserId, t: Transaction | | |||
193 | newInstanceFollower: UserNotificationSettingValue.WEB, | 193 | newInstanceFollower: UserNotificationSettingValue.WEB, |
194 | abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | 194 | abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, |
195 | abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | 195 | abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, |
196 | autoInstanceFollowing: UserNotificationSettingValue.WEB | 196 | autoInstanceFollowing: UserNotificationSettingValue.WEB, |
197 | newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
198 | newPluginVersion: UserNotificationSettingValue.WEB | ||
197 | } | 199 | } |
198 | 200 | ||
199 | return UserNotificationSettingModel.create(values, { transaction: t }) | 201 | return UserNotificationSettingModel.create(values, { transaction: t }) |