From c296aad5c30913a8f95cad5f826294de532d38d5 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 13 Jun 2023 05:20:47 -0400 Subject: [PATCH 01/76] user admin features --- app/controllers/admin.js | 8 + app/controllers/chat.js | 17 +- app/services/chat.js | 10 + app/services/user.js | 18 ++ app/views/admin/index.pug | 50 +++++ app/views/admin/user/components/list-item.pug | 14 ++ app/views/chat/components/message.pug | 8 +- client/js/site-chat.js | 3 +- client/less/site/chat.less | 173 +++++++++--------- 9 files changed, 209 insertions(+), 92 deletions(-) create mode 100644 app/views/admin/user/components/list-item.pug diff --git a/app/controllers/admin.js b/app/controllers/admin.js index 4a4a387..71c1d2d 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -74,9 +74,11 @@ class AdminController extends SiteController { async getHomeView (req, res) { const { + chat: chatService, coreNode: coreNodeService, dashboard: dashboardService, logan: loganService, + user: userService, } = this.dtp.services; res.locals.stats = { @@ -87,6 +89,12 @@ class AdminController extends SiteController { res.locals.pageTitle = `Admin Dashbord for ${this.dtp.config.site.name}`; + res.locals.recentMembers = await userService.getRecent(10); + res.locals.admins = await userService.getAdmins(); + res.locals.moderators = await userService.getModerators(); + + res.locals.recentChat = await chatService.getRecent(10); + loganService.sendRequestEvent(module.exports, req, { level: 'info', event: 'getHomeView', diff --git a/app/controllers/chat.js b/app/controllers/chat.js index 82cf2a8..d3518b9 100644 --- a/app/controllers/chat.js +++ b/app/controllers/chat.js @@ -366,16 +366,21 @@ class ChatController extends SiteController { async getRoomEditor (req, res) { const { logan: loganService } = this.dtp.services; + + const logData = { }; + if (res.locals.room) { + logData.room = { + _id: res.locals.room._id, + name: res.locals.room.name, + }; + } + loganService.sendRequestEvent(module.exports, req, { level: 'info', event: 'getRoomEditor', - data: { - room: { - _id: res.locals.room._id, - name: res.locals.room.name, - }, - }, + data: logData, }); + res.render('chat/room/editor'); } diff --git a/app/services/chat.js b/app/services/chat.js index 64a24c3..cc1da01 100644 --- a/app/services/chat.js +++ b/app/services/chat.js @@ -785,6 +785,16 @@ class ChatService extends SiteService { return reaction.toObject(); } + async getRecent (limit = 10) { + const messages = await ChatMessage + .find({ }) + .sort({ created: -1 }) + .limit(limit) + .populate(this.populateChatMessage) + .lean(); + return messages; + } + async removeForUser (user) { const { logan: loganService } = this.dtp.services; diff --git a/app/services/user.js b/app/services/user.js index 28c1dea..03f4a0f 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -508,6 +508,24 @@ class UserService extends SiteService { return users; } + async getAdmins ( ) { + const admins = await User + .find({ 'flags.isAdmin': true }) + .select(UserService.USER_SELECT) + .sort({ username: 1 }) + .lean(); + return admins; + } + + async getModerators ( ) { + const moderators = await User + .find({ 'flags.isModerator': true }) + .select(UserService.USER_SELECT) + .sort({ username: 1 }) + .lean(); + return moderators; + } + async setUserSettings (user, settings) { const { crypto: cryptoService, diff --git a/app/views/admin/index.pug b/app/views/admin/index.pug index 6efb3d8..86ff8f1 100644 --- a/app/views/admin/index.pug +++ b/app/views/admin/index.pug @@ -1,6 +1,9 @@ extends layouts/main block content + include user/components/list-item + include ../chat/components/message + div(uk-grid) div(class="uk-width-1-1 uk-width-auto@m") h3= site.name @@ -25,6 +28,53 @@ block content h3 Hourly Sign-Ups canvas(id="hourly-signups") + .uk-margin + div(uk-grid) + div(class="uk-width-1-1 uk-width-1-3@l") + h3 Admins + if Array.isArray(admins) && (admins.length > 0) + ul.uk-list.uk-list-divider + each member in admins + li + +renderUserListItem(member) + else + div There are no system admins. + + h3 Moderators + if Array.isArray(moderators) && (moderators.length > 0) + ul.uk-list.uk-list-divider + each member in moderators + li + +renderUserListItem(member) + else + div There are no system-level moderators. + + div(class="uk-width-1-1 uk-width-1-3@l") + h3 Recent Chat + if Array.isArray(recentChat) && (recentChat.length > 0) + ul.uk-list.uk-list-divider + each message in recentChat + li + div(uk-grid).uk-grid-small + .uk-width-expand + +renderChatMessage(message, { fullWidth: true }) + .uk-width-auto + a(href=`/admin/user/local/${message.author._id}`, uk-tooltip={ title: 'Manage user account' }).uk-button.uk-button-default.uk-button-small.uk-border-rounded + span + i.fas.fa-wrench + else + div There is no recent chat. + + div(class="uk-width-1-1 uk-width-1-3@l") + h3 Recent Members + if Array.isArray(recentMembers) && (recentMembers.length > 0) + ul.uk-list.uk-list-divider + each member in recentMembers + li + +renderUserListItem(member) + else + div There are no recent members. + block viewjs script(src="/chart.js/chart.min.js") script(src="/chartjs-adapter-moment/chartjs-adapter-moment.min.js") diff --git a/app/views/admin/user/components/list-item.pug b/app/views/admin/user/components/list-item.pug new file mode 100644 index 0000000..123f74b --- /dev/null +++ b/app/views/admin/user/components/list-item.pug @@ -0,0 +1,14 @@ +mixin renderUserListItem (user) + div(uk-grid).uk-grid-small + .uk-width-auto + +renderProfileIcon(user) + .uk-width-expand + .uk-text-bold(style="line-height: 1;").uk-text-truncate= user.displayName || user.username + .uk-text-small.uk-text-muted + a(href= getUserProfileUrl(user))= user.username + .uk-text-small.uk-text-truncate= user.bio + .uk-text-small.uk-text-muted created #{moment(user.created).fromNow()} + .uk-width-auto + a(href=`/admin/user/local/${user._id}`, uk-tooltip={ title: 'Manage user account' }).uk-button.uk-button-default.uk-button-small.uk-border-rounded + span + i.fas.fa-wrench \ No newline at end of file diff --git a/app/views/chat/components/message.pug b/app/views/chat/components/message.pug index ea5f39b..017c94a 100644 --- a/app/views/chat/components/message.pug +++ b/app/views/chat/components/message.pug @@ -2,8 +2,10 @@ include ../../sticker/components/sticker mixin renderChatMessage (message, options = { }) - var authorName = message.author.displayName || message.author.username; div( - data-message-id= message._id, data-author-id= message.author._id - ).chat-message + data-message-id= message._id, + data-author-id= message.author._id, + class={ 'full-width': options.fullWidth }, + ).site-chat-message .uk-margin-small div(uk-grid).uk-grid-small .uk-width-auto @@ -34,7 +36,7 @@ mixin renderChatMessage (message, options = { }) //- "time" is filled in by the JavaScript client using the browser's locale //- information so that "time" is always in the user's display timezone. - .chat-timestamp(data-dtp-timestamp= message.created).uk-text-small + .chat-timestamp(data-dtp-timestamp= message.created).uk-text-small.uk-text-muted if Array.isArray(message.stickers) && (message.stickers.length > 0) each sticker in message.stickers diff --git a/client/js/site-chat.js b/client/js/site-chat.js index 56c7a8f..226dd9f 100644 --- a/client/js/site-chat.js +++ b/client/js/site-chat.js @@ -35,7 +35,6 @@ export default class SiteChat { if (this.ui.messageList) { this.ui.messageList.addEventListener('scroll', this.onChatMessageListScroll.bind(this)); - this.updateTimestamps(); setTimeout(( ) => { this.log.info('constructor', 'scrolling chat', { top: this.ui.messageList.scrollHeight }); this.ui.messageList.scrollTo({ top: this.ui.messageList.scrollHeight, behavior: 'instant' }); @@ -62,6 +61,8 @@ export default class SiteChat { this.mutedUsers = window.localStorage.mutedUsers ? JSON.parse(window.localStorage.mutedUsers) : [ ]; this.filterChatView(); } + + this.updateTimestamps(); } async filterChatView ( ) { diff --git a/client/less/site/chat.less b/client/less/site/chat.less index b227219..5863c73 100644 --- a/client/less/site/chat.less +++ b/client/less/site/chat.less @@ -13,6 +13,97 @@ background-color: @content-background-color; } +.site-chat-message { + padding: @grid-small-gutter-vertical @grid-small-gutter-horizontal; + margin: (@grid-small-gutter-vertical / 2) @grid-small-gutter-horizontal; + + border: solid 1px @content-border-color; + border-radius: 8px; + + background: @content-background-color; + color: inherit; + font-size: var(--dtp-chat-font-size); + + &.full-width { + margin-left: 0; + margin-right: 0; + + &:first-of-type { margin-top: 0; } + + &:last-of-type { margin-bottom: 0; } + } + + &.system-message { + background: #e8e8e8; + color: #1a1a1a; + + &[data-message-type="info"] { + background: #068be4; + color: white; + } + &[data-message-type="warning"] { + background: #e4c306; + color: white; + } + &[data-message-type="error"] { + background: #ff00131a; + color: white; + } + } + + .chat-username { + font-weight: bold; + font-size: var(--dtp-chat-font-size); + line-height: 1; + color: var(--dtp-chat-username-color); + } + + img.chat-author-image { + width: auto; + height: 40px; + border-radius: 4px; + } + + .chat-content { + line-height: 1.2em; + font-size: var(--dtp-chat-font-size); + color: inherit; + overflow-wrap: break-word; + + p:last-child { + margin-bottom: 0; + } + } + + .chat-timestamp { + color: var(--dtp-chat-timestamp-color); + } + + .chat-sticker { + display: inline-block; + margin-top: 4px; + margin-right: 8px; + color: inherit; + + video { + width: auto; + height: 100px; + } + } + + .chat-user-menu { + + button.chat-menu-button { + padding: 0; + margin: 0; + background: transparent; + outline: none; + border: none; + line-height: 1; + } + } +} + #site-chat-container { overflow: auto; background-color: @content-container-color; @@ -145,88 +236,6 @@ background-color: @scrollbar-thumb-color; } - - .chat-message { - padding: @grid-small-gutter-vertical @grid-small-gutter-horizontal; - margin: (@grid-small-gutter-vertical / 2) @grid-small-gutter-horizontal; - - border: solid 1px @content-border-color; - border-radius: 8px; - - background: @content-background-color; - color: inherit; - font-size: var(--dtp-chat-font-size); - - &.system-message { - background: #e8e8e8; - color: #1a1a1a; - - &[data-message-type="info"] { - background: #068be4; - color: white; - } - &[data-message-type="warning"] { - background: #e4c306; - color: white; - } - &[data-message-type="error"] { - background: #ff00131a; - color: white; - } - } - - .chat-username { - font-weight: bold; - font-size: var(--dtp-chat-font-size); - line-height: 1; - color: var(--dtp-chat-username-color); - } - - img.chat-author-image { - width: auto; - height: 40px; - border-radius: 4px; - } - - .chat-content { - line-height: 1.2em; - font-size: var(--dtp-chat-font-size); - color: inherit; - overflow-wrap: break-word; - - p:last-child { - margin-bottom: 0; - } - } - - .chat-timestamp { - color: var(--dtp-chat-timestamp-color); - } - - .chat-sticker { - display: inline-block; - margin-top: 4px; - margin-right: 8px; - color: inherit; - - video { - width: auto; - height: 100px; - } - } - - .chat-user-menu { - - button.chat-menu-button { - padding: 0; - margin: 0; - background: transparent; - outline: none; - border: none; - line-height: 1; - } - } - } } .chat-message-menu { From 85b1f0757ecd79c7bcbc2fa11e1a7f1867d70ca8 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 13 Jun 2023 05:20:55 -0400 Subject: [PATCH 02/76] v0.8.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1facfb..30e8888 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.4", + "version": "0.8.5", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 3b8a832cad7cd1d42ce40adf58c0256e6af8964f Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 16 Jun 2023 20:56:56 -0400 Subject: [PATCH 03/76] admin/management --- app/controllers/admin.js | 2 + app/controllers/admin/attachment.js | 138 ++++++++++++++++++ app/controllers/admin/image.js | 107 ++++++++++++++ app/controllers/image.js | 5 +- app/controllers/user.js | 12 +- app/services/attachment.js | 17 +++ app/services/image.js | 12 ++ app/services/logan.js | 18 +-- app/services/user.js | 38 ++++- app/views/admin/attachment/index.pug | 21 +++ app/views/admin/components/menu.pug | 12 ++ app/views/admin/image/index.pug | 45 ++++++ app/views/admin/user/components/list-item.pug | 3 +- client/js/site-admin-app.js | 7 + 14 files changed, 421 insertions(+), 16 deletions(-) create mode 100644 app/controllers/admin/attachment.js create mode 100644 app/controllers/admin/image.js create mode 100644 app/views/admin/attachment/index.pug create mode 100644 app/views/admin/image/index.pug diff --git a/app/controllers/admin.js b/app/controllers/admin.js index 71c1d2d..ee0d400 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -43,10 +43,12 @@ class AdminController extends SiteController { ); router.use('/announcement', await this.loadChild(path.join(__dirname, 'admin', 'announcement'))); + router.use('/attachment', await this.loadChild(path.join(__dirname, 'admin', 'attachment'))); router.use('/content-report', await this.loadChild(path.join(__dirname, 'admin', 'content-report'))); router.use('/core-node', await this.loadChild(path.join(__dirname, 'admin', 'core-node'))); router.use('/core-user', await this.loadChild(path.join(__dirname, 'admin', 'core-user'))); router.use('/host', await this.loadChild(path.join(__dirname, 'admin', 'host'))); + router.use('/image', await this.loadChild(path.join(__dirname, 'admin', 'image'))); router.use('/job-queue', await this.loadChild(path.join(__dirname, 'admin', 'job-queue'))); router.use('/log', await this.loadChild(path.join(__dirname, 'admin', 'log'))); router.use('/newsletter', await this.loadChild(path.join(__dirname, 'admin', 'newsletter'))); diff --git a/app/controllers/admin/attachment.js b/app/controllers/admin/attachment.js new file mode 100644 index 0000000..27163eb --- /dev/null +++ b/app/controllers/admin/attachment.js @@ -0,0 +1,138 @@ +// admin/attachment.js +// Copyright (C) 2022 DTP Technologies, LLC +// License: Apache-2.0 + +'use strict'; + +const express = require('express'); + +const { SiteController } = require('../../../lib/site-lib'); + +class AttachmentAdminController extends SiteController { + + constructor (dtp) { + super(dtp, module.exports); + } + + async start ( ) { + const router = express.Router(); + router.use(async (req, res, next) => { + res.locals.currentView = 'admin'; + res.locals.adminView = 'attachment'; + return next(); + }); + + router.param('attachmentId', this.populateAttachmentId.bind(this)); + + router.post('/:attachmentId', this.postUpdateAttachment.bind(this)); + + router.get('/create', this.getAttachmentEditor.bind(this)); + router.get('/:attachmentId', this.getAttachmentEditor.bind(this)); + + router.get('/', this.getDashboard.bind(this)); + + router.delete('/:attachmentId', this.deleteAttachment.bind(this)); + + return router; + } + + async populateAttachmentId (req, res, next, attachmentId) { + const { + attachment: attachmentService, + logan: loganService, + } = this.dtp.services; + try { + res.locals.attachment = await attachmentService.getById(attachmentId); + return next(); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populateAttachmentId', + message: `failed to populate attachment: ${error.message}`, + data: { attachmentId, error }, + }); + return next(error); + } + } + + async postUpdateAttachment (req, res, next) { + const { + attachment: attachmentService, + logan: loganService, + } = this.dtp.services; + try { + await attachmentService.update(res.locals.attachment, req.body); + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postUpdateAttachment', + data: { + attachment: { + _id: res.locals.attachment._id, + }, + }, + }); + res.redirect('/admin/attachment'); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postUpdateAttachment', + message: `failed to update attachment: ${error.message}`, + data: { error }, + }); + return next(error); + } + } + + async getAttachmentEditor (req, res) { + res.render('admin/attachment/editor'); + } + + async getDashboard (req, res, next) { + const { attachment: attachmentService } = this.dtp.services; + try { + res.locals.pagination = this.getPaginationParameters(req, 20); + res.locals.attachments = await attachmentService.getRecent(res.locals.pagination); + res.render('admin/attachment/index'); + } catch (error) { + return next(error); + } + } + + async deleteAttachment (req, res) { + const { + attachment: attachmentService, + logan: loganService, + } = this.dtp.services; + try { + const displayList = this.createDisplayList('delete-attachment'); + await attachmentService.remove(res.locals.attachment); + displayList.reload(); + + res.status(200).json({ success: true, displayList }); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'deleteAttachment', + data: { attachment: { _id: res.locals.attachment._id } }, + }); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'deleteAttachment', + message: `failed to delete attachment: ${error.message}`, + data: { error }, + }); + res.status(error.statusCode || 500).json({ + success: false, + message: error.message, + }); + } + } +} + +module.exports = { + name: 'adminAttachment', + slug: 'adminAttachment', + className: 'AttachmentAdminController', + create: async (dtp) => { return new AttachmentAdminController(dtp); }, +}; \ No newline at end of file diff --git a/app/controllers/admin/image.js b/app/controllers/admin/image.js new file mode 100644 index 0000000..3e2df35 --- /dev/null +++ b/app/controllers/admin/image.js @@ -0,0 +1,107 @@ +// admin/image.js +// Copyright (C) 2022 DTP Technologies, LLC +// License: Apache-2.0 + +'use strict'; + +const express = require('express'); + +const { SiteController } = require('../../../lib/site-lib'); + +class ImageAdminController extends SiteController { + + constructor (dtp) { + super(dtp, module.exports); + } + + async start ( ) { + const router = express.Router(); + router.use(async (req, res, next) => { + res.locals.currentView = 'admin'; + res.locals.adminView = 'image'; + return next(); + }); + + router.param('imageId', this.populateImageId.bind(this)); + + router.get('/:imageId', this.getImageView.bind(this)); + + router.get('/', this.getDashboard.bind(this)); + + router.delete('/:imageId', this.deleteImage.bind(this)); + + return router; + } + + async populateImageId (req, res, next, imageId) { + const { + image: imageService, + logan: loganService, + } = this.dtp.services; + try { + res.locals.image = await imageService.getImageById(imageId); + return next(); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populateImageId', + message: `failed to populate image: ${error.message}`, + data: { imageId, error }, + }); + return next(error); + } + } + + async getImageView (req, res) { + res.render('admin/image/view'); + } + + async getDashboard (req, res, next) { + const { image: imageService } = this.dtp.services; + try { + res.locals.pagination = this.getPaginationParameters(req, 20); + res.locals.images = await imageService.getRecentImages(res.locals.pagination); + res.render('admin/image/index'); + } catch (error) { + return next(error); + } + } + + async deleteImage (req, res) { + const { + image: imageService, + logan: loganService, + } = this.dtp.services; + try { + const displayList = this.createDisplayList('delete-image'); + await imageService.deleteImage(res.locals.image); + displayList.reload(); + + res.status(200).json({ success: true, displayList }); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'deleteImage', + data: { image: { _id: res.locals.image._id } }, + }); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'deleteImage', + message: `failed to delete image: ${error.message}`, + data: { error }, + }); + res.status(error.statusCode || 500).json({ + success: false, + message: error.message, + }); + } + } +} + +module.exports = { + name: 'adminImage', + slug: 'adminImage', + className: 'ImageAdminController', + create: async (dtp) => { return new ImageAdminController(dtp); }, +}; \ No newline at end of file diff --git a/app/controllers/image.js b/app/controllers/image.js index 83a38f9..c8bb9ce 100644 --- a/app/controllers/image.js +++ b/app/controllers/image.js @@ -9,7 +9,7 @@ const fs = require('fs'); const express = require('express'); const mongoose = require('mongoose'); -const { SiteController/*, SiteError*/ } = require('../../lib/site-lib'); +const { SiteController, SiteError } = require('../../lib/site-lib'); class ImageController extends SiteController { @@ -60,6 +60,9 @@ class ImageController extends SiteController { try { res.locals.imageId = mongoose.Types.ObjectId(imageId); res.locals.image = await this.dtp.services.image.getImageById(res.locals.imageId); + if (!res.locals.image) { + throw new SiteError(404, 'Image not found'); + } return next(); } catch (error) { this.log.error('failed to populate image', { error }); diff --git a/app/controllers/user.js b/app/controllers/user.js index bbcedf7..e6a9fea 100644 --- a/app/controllers/user.js +++ b/app/controllers/user.js @@ -119,13 +119,13 @@ class UserController extends SiteController { ); router.get( - '/:userId/otp-setup', + '/:localUserId/otp-setup', limiterService.createMiddleware(limiterService.config.user.getOtpSetup), otpSetup, this.getOtpSetup.bind(this), ); router.get( - '/:userId/otp-disable', + '/:localUserId/otp-disable', limiterService.createMiddleware(limiterService.config.user.getOtpDisable), authRequired, this.getOtpDisable.bind(this), @@ -148,7 +148,7 @@ class UserController extends SiteController { ); router.delete( - '/:userId/profile-photo', + '/:localUserId/profile-photo', limiterService.createMiddleware(limiterService.config.user.deleteProfilePhoto), authRequired, checkProfileOwner, @@ -334,6 +334,12 @@ class UserController extends SiteController { }); } catch (error) { this.log.error('failed to create new user', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postCreateUser', + message: `failed to create user account: ${error.message}`, + data: { definition: req.body, error }, + }); return next(error); } } diff --git a/app/services/attachment.js b/app/services/attachment.js index 8c086f9..4d9f1f9 100644 --- a/app/services/attachment.js +++ b/app/services/attachment.js @@ -126,6 +126,23 @@ class AttachmentService extends SiteService { return attachments; } + /** + * Access all attachments sorted by most recent with pagination. This is for + * use by Admin tools. + * @param {*} pagination required pagination parameters (skip and cpp) + * @returns Array of attachments + */ + async getRecent (pagination) { + const attachments = await Attachment + .find() + .sort({ created: -1 }) + .skip(pagination.skip) + .limit(pagination.cpp) + .populate(this.populateAttachment) + .lean(); + return attachments; + } + /** * * @param {mongoose.Types.ObjectId} attachmentId The ID of the attachment diff --git a/app/services/image.js b/app/services/image.js index 23eeab0..bc32251 100644 --- a/app/services/image.js +++ b/app/services/image.js @@ -100,6 +100,18 @@ class ImageService extends SiteService { return images; } + async getRecentImages (pagination) { + const images = await SiteImage + .find() + .sort({ created: -1 }) + .skip(pagination.skip) + .limit(pagination.cpp) + .populate(this.populateImage) + .lean(); + const totalImageCount = await SiteImage.estimatedDocumentCount(); + return { images, totalImageCount }; + } + async deleteImage(image) { const { minio: minioService } = this.dtp.services; diff --git a/app/services/logan.js b/app/services/logan.js index 94e78ef..8b22ef0 100644 --- a/app/services/logan.js +++ b/app/services/logan.js @@ -19,9 +19,6 @@ class LoganService extends SiteService { } async sendRequestEvent (component, req, event) { - if (process.env.DTP_LOGAN !== 'enabled') { - return; - } if (req.user) { event.data = event.data || { }; event.data.user = { @@ -34,20 +31,21 @@ class LoganService extends SiteService { } async sendEvent (component, event) { - if (process.env.DTP_LOGAN !== 'enabled') { - return; - } try { - const loganScheme = process.env.DTP_LOGAN_SCHEME || 'http'; - const loganUrl = `${loganScheme}://${process.env.DTP_LOGAN_HOST}/api/event`; - event.host = os.hostname(); event['component.slug'] = component.slug; event['component.name'] = component.className || component.name; - this.log[event.level]('sending Logan event', { event }); + this.log[event.level]('application event', { event }); + if (process.env.DTP_LOGAN !== 'enabled') { + return; + } + + const loganScheme = process.env.DTP_LOGAN_SCHEME || 'http'; + const loganUrl = `${loganScheme}://${process.env.DTP_LOGAN_HOST}/api/event`; const payload = JSON.stringify(event); + const response = await fetch(loganUrl, { method: 'POST', headers: { diff --git a/app/services/user.js b/app/services/user.js index 03f4a0f..7348d33 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -69,6 +69,7 @@ class UserService extends SiteService { } = this.dtp.services; try { + this.checkRestrictedKeys('create', userDefinition); userDefinition.email = userDefinition.email.trim().toLowerCase(); // strip characters we don't want to allow in username @@ -205,6 +206,8 @@ class UserService extends SiteService { throw SiteError(403, 'Invalid user account operation'); } + this.checkRestrictedKeys('create', userDefinition); + userDefinition.username = striptags(userDefinition.username.trim().replace(/[^A-Za-z0-9\-_]/gi, '')); const username_lc = userDefinition.username.toLowerCase(); @@ -683,7 +686,18 @@ class UserService extends SiteService { const { image: imageService } = this.dtp.services; this.log.info('remove profile photo', { user: user._id }); - user = await this.getUserAccount(user._id); + switch (user.type) { + case 'User': + user = await this.getLocalUserAccount(user._id); + break; + + case 'CoreUser': + user = await this.getCoreUserAccount(user._id); + break; + + default: + throw new SiteError(400, 'Invalid User type'); + } if (user.picture.large) { await imageService.deleteImage(user.picture.large); } @@ -834,6 +848,28 @@ class UserService extends SiteService { await stickerService.removeForUser(user); await userNotificationService.removeForUser(user); } + + checkRestrictedKeys (method, definition) { + const { logan: loganService } = this.dtp.services; + const restrictedKeys = [ + 'isAdmin', 'isModerator', 'isEmailVerified', + 'canLogin', 'canChat', 'canComment', 'canReport', + 'optInSystem', 'optInMarketing', + ]; + + const keys = Object.keys(definition); + for (const restrictedKey of restrictedKeys) { + if (keys.includes(restrictedKey)) { + loganService.sendEvent(module.exports, { + level: 'alert', + event: method, + message: 'malicious fields detected', + data: { definition }, + }); + throw new SiteError(403, 'invalid request'); + } + } + } } module.exports = { diff --git a/app/views/admin/attachment/index.pug b/app/views/admin/attachment/index.pug new file mode 100644 index 0000000..5120f13 --- /dev/null +++ b/app/views/admin/attachment/index.pug @@ -0,0 +1,21 @@ +extends ../layouts/main +block content + + h1 Attachments + + if Array.isArray(attachments) && (attachments.length > 0) + ul.uk-list.uk-list-divider + each attachment in attachments + li + div(uk-grid).uk-grid-small.uk-flex-middle + .uk-width-expand + //- had to abort while writing the renderer for an attachment. + //- will be back to finish this and have an attachment browser/manager. + pre= JSON.stringify(attachment, null, 2) + + .uk-width-auto + button(type="button", data-attachment-id= attachment._id, onclick="return dtp.adminApp.deleteAttachment(event);").uk-button.dtp-button-danger.uk-border-rounded + span + i.fas.fa-trash + else + div There are no attachments. \ No newline at end of file diff --git a/app/views/admin/components/menu.pug b/app/views/admin/components/menu.pug index 2adc469..9f6b90a 100644 --- a/app/views/admin/components/menu.pug +++ b/app/views/admin/components/menu.pug @@ -33,6 +33,18 @@ ul(uk-nav).uk-nav-default i.fas.fa-bullhorn span.uk-margin-small-left Announcements + li(class={ 'uk-active': (adminView === 'attachment') }) + a(href="/admin/attachment") + span.nav-item-icon + i.fas.fa-file + span.uk-margin-small-left Attachments + + li(class={ 'uk-active': (adminView === 'image') }) + a(href="/admin/image") + span.nav-item-icon + i.fas.fa-image + span.uk-margin-small-left Images + li(class={ 'uk-active': (adminView === 'user') }) a(href="/admin/user") span.nav-item-icon diff --git a/app/views/admin/image/index.pug b/app/views/admin/image/index.pug new file mode 100644 index 0000000..81f40d7 --- /dev/null +++ b/app/views/admin/image/index.pug @@ -0,0 +1,45 @@ +extends ../layouts/main +block content + + include ../user/components/list-item + include ../../components/pagination-bar + + h1.uk-text-center Image Manager + + if Array.isArray(images.images) && (images.images.length > 0) + div(uk-grid).uk-flex-center + each image in images.images + .uk-width-medium + .uk-margin-small(uk-lightbox) + a(href=`/image/${image._id}`, data-type="image", data-caption=`id: ${image._id}`) + div + img(src= `/image/${image._id}`).responsive + + if image.owner + .uk-margin-small + +renderUserListItem(image.owner) + + .uk-margin-small.uk-text-center + button(type="button").uk-button.uk-button-default.uk-button-small.uk-border-rounded + span Image Menu + + div(uk-drop={ mode: 'click', pos: 'top-center' }).uk-card.uk-card-default.uk-card-small.uk-border-rounded + .uk-card-header + .uk-text-small.uk-text-muted.uk-text-center id:#{image._id} + .uk-card-body + ul.uk-nav.uk-dropdown-nav + li + a(href="#", data-image-id= image._id, onclick="dtp.adminApp.deleteImage(event);") + span + i.fas.fa-trash + span.uk-margin-small-left Delete image + li + a(href=`/admin/image/${image._id}/archive-user`).uk-text-truncate + span + i.fas.fa-file-archive + span.uk-margin-small-left Archive and ban #[span.uk-text-bold= image.owner.username] + + +renderPaginationBar('/admin/image', images.totalImageCount) + + else + .uk-text-center There are no images. \ No newline at end of file diff --git a/app/views/admin/user/components/list-item.pug b/app/views/admin/user/components/list-item.pug index 123f74b..ebdd631 100644 --- a/app/views/admin/user/components/list-item.pug +++ b/app/views/admin/user/components/list-item.pug @@ -7,7 +7,8 @@ mixin renderUserListItem (user) .uk-text-small.uk-text-muted a(href= getUserProfileUrl(user))= user.username .uk-text-small.uk-text-truncate= user.bio - .uk-text-small.uk-text-muted created #{moment(user.created).fromNow()} + if user.created + .uk-text-small.uk-text-muted created #{moment(user.created).fromNow()} .uk-width-auto a(href=`/admin/user/local/${user._id}`, uk-tooltip={ title: 'Manage user account' }).uk-button.uk-button-default.uk-button-small.uk-border-rounded span diff --git a/client/js/site-admin-app.js b/client/js/site-admin-app.js index 67d729f..6ba76b5 100644 --- a/client/js/site-admin-app.js +++ b/client/js/site-admin-app.js @@ -452,6 +452,13 @@ export default class DtpSiteAdminHostStatsApp extends DtpApp { return; } + + async deleteImage (event) { + const target = event.currentTarget || event.target; + const imageId = target.getAttribute('data-image-id'); + const response = await fetch(`/admin/image/${imageId}`, { method: 'DELETE' }); + return this.processResponse(response); + } } dtp.DtpSiteAdminHostStatsApp = DtpSiteAdminHostStatsApp; \ No newline at end of file From 997c3aad774b241f5fdd71b1d318729a7240df35 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 12:56:26 -0400 Subject: [PATCH 04/76] user archive - stores all data related to one user to a .zip file on storage - bans the user - removes the user --- .env.default | 1 + app/controllers/admin/attachment.js | 7 +- app/controllers/admin/image.js | 16 +- app/controllers/admin/user.js | 212 ++++++++++ app/models/user-archive.js | 29 ++ app/services/display-engine.js | 4 - app/services/image.js | 13 +- app/services/minio.js | 1 - app/services/session.js | 2 +- app/services/sms.js | 1 - app/services/user.js | 101 ++++- app/views/admin/components/menu.pug | 6 + app/views/admin/image/archive-user.pug | 28 ++ app/views/admin/user/archive/confirm.pug | 28 ++ app/views/admin/user/archive/index.pug | 41 ++ app/views/admin/user/archive/job.pug | 7 + app/views/admin/user/archive/view.pug | 83 ++++ app/views/admin/user/form.pug | 2 + app/views/admin/user/index.pug | 13 + app/workers/reeeper.js | 2 + app/workers/reeeper/job/archive-user-local.js | 381 ++++++++++++++++++ 21 files changed, 962 insertions(+), 16 deletions(-) create mode 100644 app/models/user-archive.js create mode 100644 app/views/admin/image/archive-user.pug create mode 100644 app/views/admin/user/archive/confirm.pug create mode 100644 app/views/admin/user/archive/index.pug create mode 100644 app/views/admin/user/archive/job.pug create mode 100644 app/views/admin/user/archive/view.pug create mode 100644 app/workers/reeeper/job/archive-user-local.js diff --git a/.env.default b/.env.default index c40424f..d789b37 100644 --- a/.env.default +++ b/.env.default @@ -86,6 +86,7 @@ MINIO_USE_SSL=disabled MINIO_ACCESS_KEY= MINIO_SECRET_KEY= +MINIO_ADMIN_BUCKET=yourapp-admin MINIO_IMAGE_BUCKET=yourapp-images MINIO_VIDEO_BUCKET=yourapp-videos MINIO_ATTACHMENT_BUCKET=yourapp-attachments diff --git a/app/controllers/admin/attachment.js b/app/controllers/admin/attachment.js index 27163eb..a521f30 100644 --- a/app/controllers/admin/attachment.js +++ b/app/controllers/admin/attachment.js @@ -26,8 +26,7 @@ class AttachmentAdminController extends SiteController { router.post('/:attachmentId', this.postUpdateAttachment.bind(this)); - router.get('/create', this.getAttachmentEditor.bind(this)); - router.get('/:attachmentId', this.getAttachmentEditor.bind(this)); + router.get('/:attachmentId', this.getAttachmentView.bind(this)); router.get('/', this.getDashboard.bind(this)); @@ -83,8 +82,8 @@ class AttachmentAdminController extends SiteController { } } - async getAttachmentEditor (req, res) { - res.render('admin/attachment/editor'); + async getAttachmentView (req, res) { + res.render('admin/attachment/view'); } async getDashboard (req, res, next) { diff --git a/app/controllers/admin/image.js b/app/controllers/admin/image.js index 3e2df35..af3c2c0 100644 --- a/app/controllers/admin/image.js +++ b/app/controllers/admin/image.js @@ -6,7 +6,7 @@ const express = require('express'); -const { SiteController } = require('../../../lib/site-lib'); +const { SiteController, SiteError } = require('../../../lib/site-lib'); class ImageAdminController extends SiteController { @@ -24,6 +24,7 @@ class ImageAdminController extends SiteController { router.param('imageId', this.populateImageId.bind(this)); + router.get('/:imageId/archive-user', this.getUserArchiveView.bind(this)); router.get('/:imageId', this.getImageView.bind(this)); router.get('/', this.getDashboard.bind(this)); @@ -40,6 +41,9 @@ class ImageAdminController extends SiteController { } = this.dtp.services; try { res.locals.image = await imageService.getImageById(imageId); + if (!res.locals.image) { + throw new SiteError(404, 'Image not found'); + } return next(); } catch (error) { loganService.sendRequestEvent(module.exports, req, { @@ -52,6 +56,16 @@ class ImageAdminController extends SiteController { } } + async getUserArchiveView (req, res, next) { + const { image: imageService } = this.dtp.services; + try { + res.locals.imageHistory = await imageService.getRecentImagesForOwner(res.locals.image.owner, 10); + res.render('admin/image/archive-user'); + } catch (error) { + return next(error); + } + } + async getImageView (req, res) { res.render('admin/image/view'); } diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index b851b7e..dd1cf2d 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -15,6 +15,14 @@ class UserAdminController extends SiteController { } async start ( ) { + const { jobQueue: jobQueueService } = this.dtp.services; + + this.jobQueues = { }; + this.jobQueues.reeeper = await jobQueueService.getJobQueue( + 'reeeper', + this.dtp.config.jobQueues.reeeper, + ); + const router = express.Router(); router.use(async (req, res, next) => { res.locals.currentView = 'admin'; @@ -23,11 +31,26 @@ class UserAdminController extends SiteController { }); router.param('localUserId', this.populateLocalUserId.bind(this)); + router.param('archiveJobId', this.populateArchiveJobId.bind(this)); + router.param('archiveId', this.populateArchiveId.bind(this)); + + router.post('/local/:localUserId/archive', this.postArchiveLocalUser.bind(this)); router.post('/local/:localUserId', this.postUpdateLocalUser.bind(this)); + + router.get('/local/:localUserId/archive/confirm', this.getArchiveLocalUserConfirm.bind(this)); router.get('/local/:localUserId', this.getLocalUserView.bind(this)); + router.get('/archive/job/:archiveJobId', this.getUserArchiveJobView.bind(this)); + + router.post('/archive/:archiveId/action', this.postArchiveAction.bind(this)); + router.get('/archive/:archiveId/file', this.getUserArchiveFile.bind(this)); + router.get('/archive/:archiveId', this.getUserArchiveView.bind(this)); + + router.get('/archive', this.getUserArchiveIndex.bind(this)); + router.get('/', this.getHomeView.bind(this)); + return router; } @@ -44,6 +67,68 @@ class UserAdminController extends SiteController { } } + async populateArchiveJobId (req, res, next, archiveJobId) { + try { + res.locals.job = await this.jobQueues.reeeper.getJob(archiveJobId); + if (!res.locals.job) { + throw new SiteError(404, 'Job not found'); + } + return next(); + } catch (error) { + this.log.error('failed to populate Bull queue job', { archiveJobId, error }); + return next(error); + } + } + + async populateArchiveId (req, res, next, archiveId) { + const { user: userService } = this.dtp.services; + try { + res.locals.archive = await userService.getArchiveById(archiveId); + if (!res.locals.archive) { + throw new SiteError(404, 'Archive not found'); + } + return next(); + } catch (error) { + this.log.error('failed to populate UserArchive', { archiveId, error }); + return next(error); + } + } + + async postArchiveLocalUser (req, res, next) { + const { + logan: loganService, + user: userService, + } = this.dtp.services; + try { + const user = await userService.getLocalUserAccount(req.body.userId); + if (!user) { + throw new SiteError(404, 'User not found'); + } + res.locals.job = await userService.archiveLocalUser(user); + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postArchiveUser', + data: { + job: res.locals.job.id, + user: user, + }, + }); + res.redirect(`/admin/user/archive/job/${res.locals.job.id}`); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postArchiveUser', + data: { + offender: { + _id: req.body.userId, + }, + error, + }, + }); + return next(error); + } + } + async postUpdateLocalUser (req, res, next) { const { logan: loganService, @@ -100,6 +185,133 @@ class UserAdminController extends SiteController { } } + async getUserArchiveJobView (req, res) { + res.locals.adminView = 'user-archive'; + res.render('admin/user/archive/job'); + } + + async getArchiveLocalUserConfirm (req, res) { + res.locals.adminView = 'user-archive'; + res.render('admin/user/archive/confirm'); + } + + async postArchiveAction (req, res, next) { + const { + logan: loganService, + user: userService, + } = this.dtp.services; + try { + switch (req.body.action) { + case 'update': + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postArchiveAction', + message: 'updating user archive record', + data: { + archive: { + _id: res.locals.archive._id, + user: { + _id: res.locals.archive.user._id, + username: res.locals.archive.user.username, + }, + }, + }, + }); + await userService.updateArchive(res.locals.archive, req.body); + return res.redirect(`/admin/user/archive/${res.locals.archive._id}`); + + case 'delete-file': + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postArchiveAction', + message: 'removing user archive file', + data: { + archive: { + _id: res.locals.archive._id, + user: { + _id: res.locals.archive.user._id, + username: res.locals.archive.user.username, + }, + }, + }, + }); + await userService.deleteArchiveFile(res.locals.archive); + return res.redirect(`/admin/user/archive/${res.locals.archive._id}`); + + case 'delete': + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postArchiveAction', + message: 'removing user archive', + data: { + archive: { + _id: res.locals.archive._id, + user: { + _id: res.locals.archive.user._id, + username: res.locals.archive.user.username, + }, + }, + }, + }); + await userService.deleteArchive(res.locals.archive); + return res.redirect(`/admin/user/archive`); + + default: + // unknown/invalid action + break; + } + + throw new SiteError(400, `Invalid user archive action: ${req.body.action}`); + + } catch (error) { + this.log.error('failed to delete archive file', { error }); + return next(error); + } + } + + async getUserArchiveFile (req, res, next) { + const { minio: minioService } = this.dtp.services; + try { + res.locals.adminView = 'user-archive'; + + this.log.debug('archive', { archive: res.locals.archive }); + const stream = await minioService.openDownloadStream({ + bucket: res.locals.archive.archive.bucket, + key: res.locals.archive.archive.key, + }); + + res.status(200); + res.set('Content-Type', 'application/zip'); + res.set('Content-Size', res.locals.archive.archive.size); + res.set('Content-Disposition', `attachment; filename="user-${res.locals.archive.user._id}.zip"`); + + stream.pipe(res); + } catch (error) { + this.log.error('failed to stream user archive file', { error }); + return next(error); + } + } + + async getUserArchiveView (req, res) { + res.locals.adminView = 'user-archive'; + res.render('admin/user/archive/view'); + } + + async getUserArchiveIndex (req, res, next) { + const { user: userService } = this.dtp.services; + try { + res.locals.adminView = 'user-archive'; + + res.locals.pagination = this.getPaginationParameters(req, 20); + res.locals.archive = await userService.getArchives(res.locals.pagination); + + res.render('admin/user/archive/index'); + } catch (error) { + this.log.error('failed to render the User archives index', { error }); + return next(error); + } + } + async getHomeView (req, res, next) { const { user: userService } = this.dtp.services; try { diff --git a/app/models/user-archive.js b/app/models/user-archive.js new file mode 100644 index 0000000..842fc67 --- /dev/null +++ b/app/models/user-archive.js @@ -0,0 +1,29 @@ +// user-archive.js +// Copyright (C) 2022 DTP Technologies, LLC +// License: Apache-2.0 + +'use strict'; + +const mongoose = require('mongoose'); + +const Schema = mongoose.Schema; + +const UserArchiveSchema = new Schema({ + created: { type: Date, default: Date.now, required: true, index: -1 }, + user: { + _id: { type: Schema.ObjectId, required: true, index: 1 }, + email: { type: String }, + username: { type: String, required: true }, + }, + archive: { + bucket: { type: String, required: true }, + key: { type: String, required: true }, + etag: { type: String, required: true }, + size: { type: Number, required: true }, + }, + notes: { type: String }, +}); + +module.exports = (conn) => { + return conn.model('UserArchive', UserArchiveSchema); +}; \ No newline at end of file diff --git a/app/services/display-engine.js b/app/services/display-engine.js index 56296eb..66ba9b4 100644 --- a/app/services/display-engine.js +++ b/app/services/display-engine.js @@ -132,10 +132,6 @@ class DisplayEngineService extends SiteService { this.templates = { }; } - async start ( ) { } - - async stop ( ) { } - loadTemplate (name, pugScript) { const scriptFile = path.join(this.dtp.config.root, 'app', 'views', pugScript); this.templates[name] = pug.compileFile(scriptFile); diff --git a/app/services/image.js b/app/services/image.js index bc32251..f7f6068 100644 --- a/app/services/image.js +++ b/app/services/image.js @@ -90,11 +90,11 @@ class ImageService extends SiteService { return image; } - async getRecentImagesForOwner(owner) { + async getRecentImagesForOwner(owner, limit = 10) { const images = await SiteImage .find({ owner: owner._id }) .sort({ created: -1 }) - .limit(10) + .limit(limit) .populate(this.populateImage) .lean(); return images; @@ -112,6 +112,15 @@ class ImageService extends SiteService { return { images, totalImageCount }; } + async downloadImage (image, filename) { + const { minio: minioService } = this.dtp.services; + return minioService.downloadFile({ + bucket: image.file.bucket, + key: image.file.key, + filePath: filename, + }); + } + async deleteImage(image) { const { minio: minioService } = this.dtp.services; diff --git a/app/services/minio.js b/app/services/minio.js index d386cb2..60057ca 100644 --- a/app/services/minio.js +++ b/app/services/minio.js @@ -24,7 +24,6 @@ class MinioService extends SiteService { accessKey: process.env.MINIO_ACCESS_KEY, secretKey: process.env.MINIO_SECRET_KEY, }; - this.log.debug('MinIO config', { minioConfig }); this.minio = new Minio.Client(minioConfig); } diff --git a/app/services/session.js b/app/services/session.js index d4a8cd3..747f6a8 100644 --- a/app/services/session.js +++ b/app/services/session.js @@ -18,7 +18,7 @@ class SessionService extends SiteService { async start ( ) { await super.start(); - this.log.info(`starting ${module.exports.name} service`); + passport.serializeUser(this.serializeUser.bind(this)); passport.deserializeUser(this.deserializeUser.bind(this)); } diff --git a/app/services/sms.js b/app/services/sms.js index 93c26c3..fa110e6 100644 --- a/app/services/sms.js +++ b/app/services/sms.js @@ -18,7 +18,6 @@ class SmsService extends SiteService { async start ( ) { await super.start(); - this.log.info(`starting ${module.exports.name} service`); } async stop ( ) { diff --git a/app/services/user.js b/app/services/user.js index 7348d33..f8d0555 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -11,6 +11,7 @@ const mongoose = require('mongoose'); const User = mongoose.model('User'); const CoreUser = mongoose.model('CoreUser'); const UserBlock = mongoose.model('UserBlock'); +const UserArchive = mongoose.model('UserArchive'); const passport = require('passport'); const PassportLocal = require('passport-local'); @@ -47,13 +48,20 @@ class UserService extends SiteService { async start ( ) { await super.start(); - this.log.info(`starting ${module.exports.name} service`); this.registerPassportLocal(); - if (process.env.DTP_ADMIN === 'enabled') { this.registerPassportAdmin(); } + + const { jobQueue: jobQueueService } = this.dtp.services; + this.jobQueues = { }; + + this.log.info('connecting to job queue', { name: 'reeeper', config: this.dtp.config.jobQueues.reeeper }); + this.jobQueues.reeeper = jobQueueService.getJobQueue( + 'reeeper', + this.dtp.config.jobQueues.reeeper, + ); } async stop ( ) { @@ -870,6 +878,95 @@ class UserService extends SiteService { } } } + + /** + * Create a job to archive and ban a User (local). The job will immediately + * disable the specified user, create a .zip file of their content on storage. + * Once the worker confirms that the archive file is on storage, it creates a + * UserArchive record for it, then completely bans the User. That removes all + * of the User's content. + * + * It then removes the User record entirely. + * + * @param {User} user the User to be archived + * @returns the newly created Bull queue job + */ + async archiveLocalUser (user) { + return this.jobQueues.reeeper.add('archive-user-local', { userId: user._id }); + } + + /** + * Update a UserArchive document + * @param {UserArchive} archive the existing archive to be updated + * @param {*} archiveDefinition new values to be applied + */ + async updateArchive (archive, archiveDefinition) { + const update = { $set: { }, $unset: { } }; + + archiveDefinition.notes = archiveDefinition.notes.trim(); + if (archiveDefinition.notes && (archiveDefinition.notes.length > 0)) { + update.$set.notes = archiveDefinition.notes; + } else { + update.$unset.notes = 1; + } + + await UserArchive.updateOne({ _id: archive._id }, update); + } + + /** + * Fetch an Array of UserArchive documents with pagination. + * @param {DtpPagination} pagination self explanatory + * @returns Array of UserArchive documents (can be empty) + */ + async getArchives (pagination) { + const search = { }; + const archives = await UserArchive + .find(search) + .sort({ created: -1 }) + .skip(pagination.skip) + .limit(pagination.cpp) + .lean(); + const totalArchiveCount = await UserArchive.estimatedDocumentCount(); + return { archives, totalArchiveCount }; + } + + /** + * Fetch a UserArchive record. This does not fetch the archive file. + * @param {UserArchive} archiveId the ID of the archive to fetch + * @returns the requested UserArchive, or null/undefined. + */ + async getArchiveById (archiveId) { + const archive = await UserArchive.findOne({ _id: archiveId }).lean(); + return archive; + } + + /** + * Removes the .zip file attached to a UserArchive. + * @param {UserArchive} archive the archive for which an associated .zip file + * is to be removed + */ + async deleteArchiveFile (archive) { + const { minio: minioService } = this.dtp.services; + if (!archive.archive || !archive.archive.bucket || !archive.archive.key) { + return; // no archive file present, abort + } + await minioService.removeObject(archive.archive.bucket, archive.archive.key); + await UserArchive.updateOne( + { _id: archive._id }, + { + $unset: { archive: 1 }, + }, + ); + } + + /** + * Removes a UserArchive and any attached data. + * @param {UserArchive} archive the UserArchive to be removed. + */ + async deleteArchive (archive) { + await this.deleteArchiveFile(archive); + await UserArchive.deleteOne({ _id: archive._id }); + } } module.exports = { diff --git a/app/views/admin/components/menu.pug b/app/views/admin/components/menu.pug index 9f6b90a..bc3c940 100644 --- a/app/views/admin/components/menu.pug +++ b/app/views/admin/components/menu.pug @@ -51,6 +51,12 @@ ul(uk-nav).uk-nav-default i.fas.fa-user span.uk-margin-small-left Users + li(class={ 'uk-active': (adminView === 'user-archive') }) + a(href="/admin/user/archive") + span.nav-item-icon + i.fas.fa-file-archive + span.uk-margin-small-left User Archive + li(class={ 'uk-active': (adminView === 'content-report') }) a(href="/admin/content-report") span.nav-item-icon diff --git a/app/views/admin/image/archive-user.pug b/app/views/admin/image/archive-user.pug new file mode 100644 index 0000000..e52098b --- /dev/null +++ b/app/views/admin/image/archive-user.pug @@ -0,0 +1,28 @@ +extends ../layouts/main +block content + + include ../user/components/list-item + + form(method="POST", action=`/admin/user/local/${image.owner._id}/archive`).uk-form + input(type="hidden", name="userId", value= image.owner._id) + .uk-card.uk-card-default.uk-card-small + .uk-card-header + h1.uk-card-title Archive Local User + .uk-card-body + p This action will pull all images from storage into an archive file, place the archive file on storage, delete all the image records and storage data, then ban the User. The archive is produced first because images would be deleted during the ban. So, the archive is made, then the user is banned. + + p These are the #{numeral(imageHistory.length).format('0,0')} most recent images uploaded by #{image.owner.username}. + + div(uk-grid) + each image in imageHistory + .uk-width-medium + .uk-margin-small(uk-lightbox) + a(href=`/image/${image._id}`, data-type="image", data-caption=`id: ${image._id}`) + div + img(src= `/image/${image._id}`).responsive + .uk-card-footer.uk-flex.uk-flex-middle + .uk-width-expand + +renderBackButton() + + .uk-width-auto + button(type="submit").uk-button.uk-button-danger.uk-border-rounded Archive User \ No newline at end of file diff --git a/app/views/admin/user/archive/confirm.pug b/app/views/admin/user/archive/confirm.pug new file mode 100644 index 0000000..9f83eaa --- /dev/null +++ b/app/views/admin/user/archive/confirm.pug @@ -0,0 +1,28 @@ +extends ../../layouts/main +block content + + include ../../user/components/list-item + + form(method="POST", action=`/admin/user/local/${userAccount._id}/archive`).uk-form + input(type="hidden", name="userId", value= userAccount._id) + .uk-card.uk-card-default.uk-card-small + .uk-card-header + h1.uk-card-title + span + i.fas.fa-id-card + span.uk-margin-small-left Archive Local User + .uk-card-body + .uk-margin + +renderUserListItem(userAccount) + + .uk-margin + p This action will archive #{userAccount.displayName || userAccount.username}'s content to a .zip file, place the .zip file on storage, create a UserArchive record for this User account, ban this User account, and remove this User account from the database. + + p #{userAccount.displayName || userAccount.username}'s email address and username will become locked, and will remain unavailable for use for as long as this archive exists. + + .uk-card-footer.uk-flex.uk-flex-middle + .uk-width-expand + +renderBackButton() + + .uk-width-auto + button(type="submit").uk-button.uk-button-danger.uk-border-rounded Archive User \ No newline at end of file diff --git a/app/views/admin/user/archive/index.pug b/app/views/admin/user/archive/index.pug new file mode 100644 index 0000000..798399d --- /dev/null +++ b/app/views/admin/user/archive/index.pug @@ -0,0 +1,41 @@ +extends ../../layouts/main +block content + + include ../components/list-item + include ../../../components/pagination-bar + + .uk-card.uk-card-default.uk-card-small.uk-margin + .uk-card-header + h1.uk-card-title + span + i.fas.fa-id-card + span.uk-margin-small-left User Archives + + .uk-card-body + if Array.isArray(archive.archives) && (archive.archives.length > 0) + table.uk-table.uk-table-divider.uk-table-justify + thead + tr + th Username + th User ID + th Created + th Archive + tbody + each record in archive.archives + tr + td= record.user.username + td= record.user._id + td= moment(record.created).format('MMMM DD, YYYY, [at] h:mm a') + td + span + i.fas.fa-file-archive + a(href=`/admin/user/archive/${record._id}`).uk-margin-small-left View Archive + else + div There are no user archives. + + if Array.isArray(archive.archives) && (archive.archives.length > 0) + .uk-card-footer + +renderPaginationBar('/admin/user/archive', archive.totalArchiveCount) + + .uk-margin + .uk-text-small.uk-text-muted.uk-text-center User accounts referenced on this page have been removed from the database and are no longer able to use #{site.name}. \ No newline at end of file diff --git a/app/views/admin/user/archive/job.pug b/app/views/admin/user/archive/job.pug new file mode 100644 index 0000000..fbb33cc --- /dev/null +++ b/app/views/admin/user/archive/job.pug @@ -0,0 +1,7 @@ +extends ../../layouts/main +block content + + include ../components/list-item + + h1 User Archive Job + pre= JSON.stringify(job, null, 2) \ No newline at end of file diff --git a/app/views/admin/user/archive/view.pug b/app/views/admin/user/archive/view.pug new file mode 100644 index 0000000..a0122fe --- /dev/null +++ b/app/views/admin/user/archive/view.pug @@ -0,0 +1,83 @@ +extends ../../layouts/main +block content + + include ../components/list-item + + form(method="POST", action=`/admin/user/archive/${archive._id}/action`).uk-form + .uk-card.uk-card-default.uk-card-small + .uk-card-header + h1.uk-card-title + span + i.fas.fa-id-card + span.uk-margin-small-left User Archive + + .uk-card-body + .uk-margin + div(uk-grid) + .uk-width-auto + .uk-form-label Archive ID + .uk-text-bold= archive._id + .uk-width-auto + .uk-form-label Created + .uk-text-bold= moment(archive.created).format('MMMM DD, YYYY, [at] h:mm:ss a') + .uk-width-auto + .uk-form-label User + .uk-text-bold= archive.user.username + .uk-width-auto + .uk-form-label User ID + .uk-text-bold= archive.user._id + .uk-width-auto + .uk-form-label User email + .uk-text-bold= archive.user.email + + if archive.archive + div(uk-grid) + .uk-width-auto + .uk-form-label Archive file + .uk-text-bold= archive.archive.key.replace(/\/user-archive\//, '') + .uk-width-auto + .uk-form-label Download size + .uk-text-bold= numeral(archive.archive.size).format('0,0.0a') + else + .uk-text-italic (archive file removed) + + .uk-margin + label(for="notes").uk-form-label Notes + textarea(id="notes", name="notes", rows="4", placeholder="Enter notes").uk-textarea.uk-resize-vertical= archive.notes + + .uk-card-footer + div(uk-grid) + .uk-width-expand + div(hidden= !archive.archive, uk-grid) + .uk-width-auto + a(href=`/admin/user/archive/${archive._id}/file`).uk-button.uk-button-default.uk-border-rounded + span + i.fas.fa-download + span.uk-margin-small-left Download#[span(class="uk-visible@s") File] + .uk-width-auto + button( + type="submit", + name="action", + value="delete-file", + uk-tooltip={ title: 'Remove the .zip file attached to the UserArchive' }, + ).uk-button.uk-button-danger.uk-border-rounded + span + i.fas.fa-trash + span.uk-margin-small-left Delete#[span(class="uk-visible@s") File] + + .uk-width-auto + button( + type="submit", + name="action", + value="delete", + uk-tooltip={ title: 'Remove the UserArchive from the database' }, + ).uk-button.uk-button-danger.uk-border-rounded + span + i.fas.fa-save + span.uk-margin-small-left Delete + + .uk-width-auto + button(type="submit", name="action", value="update").uk-button.uk-button-primary.uk-border-rounded + span + i.fas.fa-save + span.uk-margin-small-left Update \ No newline at end of file diff --git a/app/views/admin/user/form.pug b/app/views/admin/user/form.pug index 8564efd..b40c5cf 100644 --- a/app/views/admin/user/form.pug +++ b/app/views/admin/user/form.pug @@ -81,6 +81,8 @@ block content div(uk-grid).uk-grid-small .uk-width-expand +renderBackButton() + .uk-width-auto + a(href=`/admin/user/local/${userAccount._id}/archive/confirm`).uk-button.uk-button-danger.uk-border-rounded Archive User .uk-width-auto button(type="submit", name="action", value="ban").uk-button.uk-button-danger.uk-border-rounded Ban User .uk-width-auto diff --git a/app/views/admin/user/index.pug b/app/views/admin/user/index.pug index 66c17c2..6afbfbc 100644 --- a/app/views/admin/user/index.pug +++ b/app/views/admin/user/index.pug @@ -3,6 +3,19 @@ block content include ../../components/pagination-bar + .uk-margin + div(uk-grid).uk-flex-middle + .uk-width-expand + h1 + span + i.fas.fa-user-cog + span.uk-margin-small-left User Manager + .uk-width-auto + a(href="/admin/user/archive").uk-button.uk-button-default.uk-border-rounded + span.nav-item-icon + i.fas.fa-file-archive + span.uk-margin-small-left Browse Archive + .uk-margin form(method="GET", action="/admin/user").uk-form div(uk-grid).uk-grid-collapse diff --git a/app/workers/reeeper.js b/app/workers/reeeper.js index 0236034..a3de7d7 100644 --- a/app/workers/reeeper.js +++ b/app/workers/reeeper.js @@ -36,6 +36,8 @@ class ReeeperWorker extends SiteWorker { await this.loadProcessor(path.join(__dirname, 'reeeper', 'cron', 'expire-crashed-hosts.js')); await this.loadProcessor(path.join(__dirname, 'reeeper', 'cron', 'expire-announcements.js')); + await this.loadProcessor(path.join(__dirname, 'reeeper', 'job', 'archive-user-local.js')); + await this.startProcessors(); } diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js new file mode 100644 index 0000000..42a967c --- /dev/null +++ b/app/workers/reeeper/job/archive-user-local.js @@ -0,0 +1,381 @@ +// reeeper/job/archive-user-local.js +// Copyright (C) 2022 DTP Technologies, LLC +// License: Apache-2.0 + +'use strict'; + +const path = require('path'); +const fs = require('fs'); + +const util = require('util'); +const execFile = util.promisify(require('child_process').execFile); + +const mime = require('mime'); + +const mongoose = require('mongoose'); +const User = mongoose.model('User'); + +const { SiteWorkerProcess } = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'site-lib')); + +/** + * A job to archive and ban a User (local). + * + * 1. Immediately disable the specified User + * 2. Create a .zip file of the User's content on storage + * 3. Creates a UserArchive record for the file and User + * 4. Ban the User (removes all of the User's content) + * 5. Remove the User record from the database + */ +class ArchiveUserLocalJob extends SiteWorkerProcess { + + static get COMPONENT ( ) { + return { + name: 'archiveUserLocalJob', + slug: 'archive-user-local-job', + }; + } + + static get JOB_NAME ( ) { return 'Local User Archive'; } + static get JOB_SLUG ( ) { return 'archive-user-local'; } + + constructor (worker) { + super(worker, ArchiveUserLocalJob.COMPONENT); + this.jobs = new Set(); + } + + async start ( ) { + await super.start(); + + this.queue = await this.getJobQueue('reeeper', this.dtp.config.jobQueues.reeeper); + + this.log.info('registering job processor', { queue: this.queue.name, job: ArchiveUserLocalJob.JOB_SLUG }); + this.queue.process(ArchiveUserLocalJob.JOB_SLUG, 1, this.processArchiveUserLocal.bind(this)); + } + + async stop ( ) { + try { + if (this.queue) { + this.log.info('halting job queue', { jobCount: this.jobs.size }); + await this.queue.pause(true, false); + delete this.queue; + } + } catch (error) { + this.log.error('failed to halt job queue', { error }); + // fall through + } finally { + await super.stop(); + } + } + + async processArchiveUserLocal (job) { + const { user: userService } = this.dtp.services; + try { + job.data.archivePath = path.join('/tmp', this.dtp.pkg.name, ArchiveUserLocalJob.JOB_SLUG); + this.jobs.add(job); + + job.data.userId = mongoose.Types.ObjectId(job.data.userId); + job.data.user = await userService.getLocalUserAccount(job.data.userId); + + job.data.workPath = path.join(job.data.archivePath, job.data.userId.toString()); + await fs.promises.mkdir(job.data.workPath, { recursive: true }); + + /* + * Save the User account data + */ + await this.archiveUserData(job); + + /* + * Disable the User account (which destroys their session and cookie(s)) + */ + // await this.disableUser(job); + + /* + * Archive the User's content to the workPath on the local file system. + */ + await this.archiveUserChat(job); + await this.archiveUserComments(job); + await this.archiveUserStickers(job); + await this.archiveUserImages(job); + + /* + * Create the .zip file archive, upload it to storage, and create the + * UserArchive record. + */ + await this.createArchiveFile(job); + + this.log.info('banning user', { + user: { + _id: job.data.userId, + username: job.data.user.username, + }, + }); + // await userService.ban(job.data.user); + + this.log.info('removing user', { + user: { + _id: job.data.userId, + username: job.data.user.username, + }, + }); + // await User.deleteOne({ _id: job.data.userId }); + } catch (error) { + this.log.error('failed to delete attachment', { attachmentId: job.data.attachmentId, error }); + throw error; + } finally { + if (job.data.workPath) { + this.log.info('cleaning up work directory'); + await fs.promises.rm(job.data.workPath, { force: true, recursive: true }); + + delete job.data.workPath; + } + this.jobs.delete(job); + this.log.info('job complete', { job: job.id, name: ArchiveUserLocalJob.JOB_NAME }); + } + } + + async archiveUserData (job) { + // fetch the entire User record (all fields) + job.data.fullUser = await User + .findOne({ _id: job.data.user._id }) + .select('+email +passwordSalt +password +flags +permissions +optIn') + .lean(); + if (!job.data.fullUser) { + throw new Error('user does not exist'); + } + + const userFilename = path.join(job.data.workPath, `user-${job.data.user._id}.json`); + await fs.promises.writeFile(userFilename, JSON.stringify(job.data.fullUser, null, 2)); + } + + async disableUser (job) { + this.log.info('disabling local User account', { + user: { + _id: job.data.userId, + username: job.data.user.username, + }, + }); + await User.updateOne( + { _id: job.data.user._id }, + { + $set: { + 'flags.isAdmin': false, + 'flags.isModerator': false, + 'flags.isEmailVerified': false, + 'permissions.canLogin': false, + 'permissions.canChat': false, + 'permissions.canComment': false, + 'permissions.canReport': false, + 'optIn.system': false, + 'optIn.marketing': false, + }, + }, + ); + } + + async archiveUserChat (job) { + const ChatMessage = mongoose.model('ChatMessage'); + const ChatRoom = mongoose.model('ChatRoom'); + + job.data.chatPath = path.join(job.data.workPath, 'chat'); + await fs.promises.mkdir(job.data.chatPath, { recursive: true }); + + this.log.info('archiving user chat', { + user: { + _id: job.data.user._id, + username: job.data.user.username, + }, + }); + + await ChatRoom + .find({ owner: job.data.user._id }) + + .lean() + .cursor() + .eachAsync(async (room) => { + const roomFilename = path.join(job.data.workPath, 'chat', `room-${room._id}`); + await fs.promises.writeFile(roomFilename, JSON.stringify(room, null, 2)); + }); + + await ChatMessage + .find({ author: job.data.user._id }) + .lean() + .cursor() + .eachAsync(async (message) => { + const messageFilename = path.join(job.data.workPath, 'chat', `message-${message._id}.json`); + await fs.promises.writeFile(messageFilename, JSON.stringify(message, null, 2)); + }); + } + + async archiveUserComments (job) { + const Comment = mongoose.model('Comment'); + + job.data.commentPath = path.join(job.data.workPath, 'comments'); + await fs.promises.mkdir(job.data.commentPath, { recursive: true }); + + this.log.info('archiving user comments', { + user: { + _id: job.data.user._id, + username: job.data.user.username, + }, + }); + + await Comment + .find({ author: job.data.userId }) + .cursor() + .eachAsync(async (comment) => { + const commentFilename = path.join(job.data.imagePath, `comment-${comment._id}.json`); + await fs.promises.writeFile(commentFilename, JSON.stringify(comment, null, 2)); + }); + } + + async archiveUserStickers (job) { + const Sticker = mongoose.model('Sticker'); + const { minio: minioService } = this.dtp.services; + + job.data.stickerPath = path.join(job.data.workPath, 'stickers'); + await fs.promises.mkdir(job.data.stickerPath, { recursive: true }); + + job.data.stickerMediaPath = path.join(job.data.stickerPath, 'media'); + await fs.promises.mkdir(job.data.stickerMediaPath, { recursive: true }); + + this.log.info('archiving user stickers', { + user: { + _id: job.data.user._id, + username: job.data.user.username, + }, + }); + + await Sticker + .find({ owner: job.data.userId }) + .cursor() + .eachAsync(async (sticker) => { + const stickerFilename = path.join(job.data.stickerPath, `sticker-${sticker._id}.json`); + await fs.promises.writeFile(stickerFilename, JSON.stringify(sticker, null, 2)); + + if (sticker.original && sticker.original.bucket && sticker.orignal.key && sticker.encoded.type) { + const originalExt = mime.getExtension(sticker.original.type); + const originalFilename = path.join(job.data.stickerMediaPath, `sticker-${sticker._id}.original.${originalExt}`); + await minioService.downloadFile({ + bucket: sticker.original.bucket, + key: sticker.original.key, + filePath: originalFilename, + }); + } + + if (sticker.encoded && sticker.encoded.bucket && sticker.encoded.key && sticker.encoded.type) { + const encodedExt = mime.getExtension(sticker.encoded.type); + const encodedFilename = path.join(job.data.stickerMediaPath, `sticker-${sticker._id}.encoded.${encodedExt}`); + await minioService.downloadFile({ + bucket: sticker.encoded.bucket, + key: sticker.encoded.key, + filePath: encodedFilename, + }); + } + }); + } + + async archiveUserImages (job) { + const SiteImage = mongoose.model('Image'); + const { image: imageService } = this.dtp.services; + + job.data.imagePath = path.join(job.data.workPath, 'images'); + await fs.promises.mkdir(job.data.imagePath, { recursive: true }); + + this.log.info('archiving user images', { + user: { + _id: job.data.user._id, + username: job.data.user.username, + }, + }); + + await SiteImage + .find({ owner: job.data.user._id }) + .cursor() + .eachAsync(async (image) => { + try { + let imageExt = mime.getExtension(image.type); + const imageFilename = path.join(job.data.imagePath, `image-${image._id}.${imageExt}`); + const metadataFilename = path.join(job.data.imagePath, `image-${image._id}.metadata.json`); + + await imageService.downloadImage(image, imageFilename); + await fs.promises.writeFile(metadataFilename, JSON.stringify(image.metadata, null, 2)); + + } catch (error) { + this.log.error('failed to download image', { + image: { _id: image._id }, + error, + }); + } + }); + } + + async createArchiveFile (job) { + const { minio: minioService } = this.dtp.services; + try { + job.data.zipFilename = path.join(job.data.archivePath, `user-${job.data.userId}.zip`); + const zipArgs = [ + '-r', '-9', + job.data.zipFilename, + `${job.data.userId}`, + ]; + const options = { + cwd: job.data.archivePath, + encoding: 'utf8', + }; + await execFile('/usr/bin/zip', zipArgs, options); + + const zipFileStat = await fs.promises.stat(job.data.zipFilename); + this.log.info('zip archive created', { size: zipFileStat.size }); + + job.data.archiveFile = { + bucket: process.env.MINIO_ADMIN_BUCKET, + key: `/user-archive/user-${job.data.userId}.zip`, + }; + + const response = await minioService.uploadFile({ + bucket: job.data.archiveFile.bucket, + key: job.data.archiveFile.key, + filePath: job.data.zipFilename, + metadata: { + job: { + id: job.id, + }, + user: job.data.user, + } + }); + + this.log.info('creating user archive record', { etag: response.etag, size: zipFileStat.size }); + const UserArchive = mongoose.model('UserArchive'); + await UserArchive.create({ + created: job.data.startTime, + user: { + _id: job.data.userId, + username: job.data.user.username, + email: job.data.fullUser.email, + }, + archive: { + bucket: job.data.archiveFile.bucket, + key: job.data.archiveFile.key, + etag: response.etag, + size: zipFileStat.size, + } + }); + } catch (error) { + this.log.error('failed to create archive .zip file', { + user: { + _id: job.data.userId, + username: job.data.user.username, + }, + }); + throw error; + } finally { + try { + await fs.promises.rm(job.data.zipFilename, { force: true }); + } catch (error) { + this.log.error('failed to remove temp .zip file', { error }); + } + } + } +} + +module.exports = ArchiveUserLocalJob; \ No newline at end of file From df36ac5369e2942c58a6558e77d2d338856882e4 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 12:56:59 -0400 Subject: [PATCH 05/76] v0.8.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30e8888..14808d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.5", + "version": "0.8.6", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 35e3e320abc9eae42af54080ddec4e67bb60234d Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 17:16:48 -0400 Subject: [PATCH 06/76] user removal tools (incomplete) to allow for merge of updated Base --- app/services/page.js | 17 ++++++++++++++++- app/services/post.js | 17 +++++++++++++++++ app/services/user.js | 7 +++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/app/services/page.js b/app/services/page.js index ab866a0..a12cf35 100644 --- a/app/services/page.js +++ b/app/services/page.js @@ -186,6 +186,21 @@ class PageService extends SiteService { async deletePage (page) { this.log.info('deleting page', { pageId: page._id }); await Page.deleteOne({ _id: page._id }); + await this.cacheMainMenuPages(); + } + + async removeForAuthor (author) { + await Page + .find({ author: author._id }) + .cursor() + .eachAsync(async (page) => { + try { + await this.deletePage(page); + } catch (error) { + this.log.error('failed to remove page for author', { error }); + // fall through + } + }); } createPageSlug (pageId, pageTitle) { @@ -196,7 +211,7 @@ class PageService extends SiteService { return `${pageSlug}-${pageId}`; } - async cacheMainMenuPages () { + async cacheMainMenuPages ( ) { try { const pages = await Page .find({ status: 'published' }) diff --git a/app/services/post.js b/app/services/post.js index ff04efe..289b894 100644 --- a/app/services/post.js +++ b/app/services/post.js @@ -400,6 +400,23 @@ class PostService extends SiteService { await Post.deleteOne({ _id: post._id }); } + async removeForAuthor (author) { + await Post + .find({ + authorType: author.type, + author: author._id, + }) + .cursor() + .eachAsync(async (post) => { + try { + await this.deletePost(post); + } catch (error) { + this.log.error('failed to remove post for author', { error }); + // fall through + } + }); + } + createPostSlug (postId, postTitle) { if ((typeof postTitle !== 'string') || (postTitle.length < 1)) { throw new Error('Invalid input for making a post slug'); diff --git a/app/services/user.js b/app/services/user.js index 0e38f11..7f469c0 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -902,6 +902,7 @@ class UserService extends SiteService { contentReport: contentReportService, csrfToken: csrfTokenService, otpAuth: otpAuthService, + page: pageService, sticker: stickerService, userNotification: userNotificationService, } = this.dtp.services; @@ -918,12 +919,18 @@ class UserService extends SiteService { 'permissions.canChat': false, 'permissions.canComment': false, 'permissions.canReport': false, + 'permissions.canAuthorPages': false, + 'permissions.canAuthorPosts': false, + 'permissions.canPublishPages': false, + 'permissions.canPublishPosts': false, 'optIn.system': false, 'optIn.marketing': false, }, }, ); + await pageService.removeForAuthor(user); + await chatService.removeForUser(user); await commentService.removeForAuthor(user); await contentReportService.removeForUser(user); From b7b868257f6764c9646f88c837acdce0b98a36e9 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 18:34:40 -0400 Subject: [PATCH 07/76] backport Unified Feed from Sites to Base --- app/controllers/newsroom.js | 60 +++++++++++++++++++++++++++-- app/views/newsroom/index.pug | 9 ++++- app/views/newsroom/unified-feed.pug | 27 +++++++++++++ config/limiter.js | 11 ++++-- 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 app/views/newsroom/unified-feed.pug diff --git a/app/controllers/newsroom.js b/app/controllers/newsroom.js index 1e905c9..4f161bf 100644 --- a/app/controllers/newsroom.js +++ b/app/controllers/newsroom.js @@ -17,6 +17,7 @@ class NewsroomController extends SiteController { async start ( ) { const { dtp } = this; const { limiter: limiterService } = dtp.services; + const limiterConfig = limiterService.config.newsroom; const router = express.Router(); dtp.app.use('/newsroom', router); @@ -28,19 +29,27 @@ class NewsroomController extends SiteController { router.param('feedId', this.populateFeedId.bind(this)); + router.get('/feed', + limiterService.createMiddleware(limiterConfig.getUnifiedFeed), + this.getUnifiedFeed.bind(this), + ); + router.get('/:feedId', - limiterService.createMiddleware(limiterService.config.newsroom.getFeedView), + limiterService.createMiddleware(limiterConfig.getFeedView), this.getFeedView.bind(this), ); router.get('/', - limiterService.createMiddleware(limiterService.config.newsletter.getIndex), + limiterService.createMiddleware(limiterConfig.getIndex), this.getHome.bind(this), ); } async populateFeedId (req, res, next, feedId) { - const { feed: feedService } = this.dtp.services; + const { + feed: feedService, + logan: loganService, + } = this.dtp.services; try { res.locals.feed = await feedService.getById(feedId); if (!res.locals.feed) { @@ -48,11 +57,54 @@ class NewsroomController extends SiteController { } return next(); } catch (error) { - this.log.error('failed to populate feedId', { feedId, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populateFeedId', + message: error.message, + data: { feedId, error }, + }); return next(error); } } + async getUnifiedFeed (req, res) { + const { + feed: feedService, + logan: loganService, + } = this.dtp.services; + try { + res.locals.pagination = this.getPaginationParameters(req, 20); + res.locals.newsroom = await feedService.getNewsfeed(res.locals.pagination); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getUnifiedFeed', + data: { fmt: req.query.fmt || 'html' }, + }); + + switch (req.query.fmt) { + case 'json': + res.status(200).json(res.locals.newsroom); + break; + + default: + res.render('newsroom/unified-feed'); + break; + } + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getUnifiedFeed', + message: error.message, + data: { error }, + }); + res.status(error.statusCode || 500).json({ + success: false, + message: error.message, + }); + } + } + async getFeedView (req, res, next) { const { feed: feedService } = this.dtp.services; try { diff --git a/app/views/newsroom/index.pug b/app/views/newsroom/index.pug index 27fc24a..27f0456 100644 --- a/app/views/newsroom/index.pug +++ b/app/views/newsroom/index.pug @@ -4,7 +4,14 @@ block content section.uk-section.uk-section-default.uk-section-small .uk-container - h1 #{site.name} Newsroom + .uk-margin + div(uk-grid).uk-flex-middle + .uk-width-expand + h1.uk-margin-remove #{site.name} Newsroom + .uk-width-auto + a(href="/newsroom/feed").uk-button.dtp-button-primary.uk-button-small.uk-border-rounded + span View All + if Array.isArray(newsroom.feeds) && (newsroom.feeds.length > 0) div(uk-grid).uk-grid-match each feed in newsroom.feeds diff --git a/app/views/newsroom/unified-feed.pug b/app/views/newsroom/unified-feed.pug new file mode 100644 index 0000000..263f7b2 --- /dev/null +++ b/app/views/newsroom/unified-feed.pug @@ -0,0 +1,27 @@ +extends ../layouts/main +block content + + include ../components/pagination-bar + + section.uk-section.uk-section-default + .uk-container + + article.uk-article + .uk-margin + h1.uk-article-title.uk-margin-remove #{site.name} News Feed + .uk-text-bold #{formatCount(newsroom.totalFeedEntryCount)} articles indexed by #{site.name} in one chronological feed. + + .uk-margin + if Array.isArray(newsroom.entries) && (newsroom.entries.length > 0) + ul.uk-list.uk-list-divider + each entry in newsroom.entries + li + .uk-text-large.uk-text-bold.uk-margin-small + a(href= entry.link, target="shing_reader")= entry.title + .uk-margin-small= entry.description + .uk-text-small source: #[a(href= entry.feed.link, target="_blank")= entry.feed.title] + else + div There are no news feed entries. + + .uk-margin + +renderPaginationBar(`/newsroom/feed`, newsroom.totalFeedEntryCount) \ No newline at end of file diff --git a/config/limiter.js b/config/limiter.js index e49b258..c72c4dd 100644 --- a/config/limiter.js +++ b/config/limiter.js @@ -245,15 +245,20 @@ module.exports = { * NewsroomController */ newsroom: { + getUnifiedFeed: { + total: 15, + expire: ONE_MINUTE, + message: 'You are fetching the unified feed too quickly', + }, getFeedView: { - total: 5, + total: 15, expire: ONE_MINUTE, - message: 'You are reading newsletters too quickly', + message: 'You are fetching news feeds too quickly', }, getIndex: { total: 60, expire: ONE_MINUTE, - message: 'You are fetching newsletters too quickly', + message: 'You are fetching the newsroom too quickly', }, }, From 153e16bc007c84eab185986f9661e8e081c91a02 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 18:36:17 -0400 Subject: [PATCH 08/76] more Logan logging --- app/controllers/newsroom.js | 42 +++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/app/controllers/newsroom.js b/app/controllers/newsroom.js index 4f161bf..d766809 100644 --- a/app/controllers/newsroom.js +++ b/app/controllers/newsroom.js @@ -106,25 +106,59 @@ class NewsroomController extends SiteController { } async getFeedView (req, res, next) { - const { feed: feedService } = this.dtp.services; + const { + feed: feedService, + logan: loganService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 10); res.locals.newsroom = await feedService.getFeedEntries(res.locals.feed, res.locals.pagination); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getFeedView', + data: { + feed: { + _id: res.locals.feed._id, + title: res.locals.feed.title, + }, + }, + }); + res.render('newsroom/feed-view'); } catch (error) { - this.log.error('failed to present newsroom home', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getFeedView', + message: error.message, + data: { error }, + }); return next(error); } } async getHome (req, res, next) { - const { feed: feedService } = this.dtp.services; + const { + feed: feedService, + logan: loganService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 10); res.locals.newsroom = await feedService.getFeeds(res.locals.pagination, { withEntries: true }); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getHome', + }); + res.render('newsroom/index'); } catch (error) { - this.log.error('failed to present newsroom home', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getHome', + message: error.message, + data: { error }, + }); return next(error); } } From 762bdb0ef053a79adc5c0c7958c42161c02a62c3 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 18:36:27 -0400 Subject: [PATCH 09/76] v0.8.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 14808d8..7507c2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.6", + "version": "0.8.7", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From b28c35607243faa541715d079fb6386264e8851c Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 19:02:34 -0400 Subject: [PATCH 10/76] Logan logging --- app/controllers/page.js | 29 ++- app/controllers/post.js | 425 +++++++++++++++++++++++++++++++++------ app/controllers/venue.js | 42 +++- 3 files changed, 426 insertions(+), 70 deletions(-) diff --git a/app/controllers/page.js b/app/controllers/page.js index 9454c99..af7f86d 100644 --- a/app/controllers/page.js +++ b/app/controllers/page.js @@ -35,7 +35,10 @@ class PageController extends SiteController { } async populatePageSlug (req, res, next, pageSlug) { - const { page: pageService } = this.dtp.services; + const { + logan: loganService, + page: pageService, + } = this.dtp.services; try { res.locals.page = await pageService.getBySlug(pageSlug); if (!res.locals.page) { @@ -43,22 +46,42 @@ class PageController extends SiteController { } return next(); } catch (error) { - this.log.error('failed to populate pageSlug', { pageSlug, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populatePageSlug', + message: error.message, + data: { error }, + }); return next(error); } } async getView (req, res, next) { - const { resource: resourceService } = this.dtp.services; + const { + logan: loganService, + resource: resourceService, + } = this.dtp.services; try { if (res.locals.page.status === 'published') { await resourceService.recordView(req, 'Page', res.locals.page._id); } res.locals.pageSlug = res.locals.page.slug; res.locals.pageTitle = `${res.locals.page.title} on ${this.dtp.config.site.name}`; + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getView', + }); + res.render('page/view'); } catch (error) { this.log.error('failed to service page view', { pageId: res.locals.page._id, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getView', + message: error.message, + data: { error }, + }); return next(error); } } diff --git a/app/controllers/post.js b/app/controllers/post.js index f1c62b9..606672e 100644 --- a/app/controllers/post.js +++ b/app/controllers/post.js @@ -93,7 +93,6 @@ class PostController extends SiteController { router.delete( '/:postId/profile-photo', - // limiterService.createMiddleware(limiterService.config.post.deletePostFeatureImage), requireAuthorPrivileges, this.deletePostFeatureImage.bind(this), ); @@ -103,14 +102,15 @@ class PostController extends SiteController { requireAuthorPrivileges, this.deletePost.bind(this), ); - - - + router.get('/tag/:tagSlug', this.getTagSearchView.bind(this)); } async populateUsername (req, res, next, username) { - const { user: userService } = this.dtp.services; + const { + logan: loganService, + user: userService, + } = this.dtp.services; try { res.locals.author = await userService.lookup(username); if (!res.locals.author) { @@ -118,13 +118,21 @@ class PostController extends SiteController { } return next(); } catch (error) { - this.log.error('failed to populate username', { username, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populateUsername', + message: error.message, + data: { error }, + }); return next(error); } } async populatePostSlug (req, res, next, postSlug) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.post = await postService.getBySlug(postSlug); if (!res.locals.post) { @@ -132,13 +140,21 @@ class PostController extends SiteController { } return next(); } catch (error) { - this.log.error('failed to populate postSlug', { postSlug, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populatePostSlug', + message: error.message, + data: { error }, + }); return next(error); } } async populatePostId (req, res, next, postId) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.post = await postService.getById(postId); @@ -147,13 +163,55 @@ class PostController extends SiteController { return next(); } catch (error) { - this.log.error('failed to populate postId', { postId, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populatePostId', + message: error.message, + data: { error }, + }); + return next(error); + } + } + + async populateTagSlug (req, res, next, tagSlug) { + const { + logan: loganService, + post: postService, + } = this.dtp.services; + try { + var allPosts = false; + var statusArray = ['published']; + if (req.user) { + if (req.user.flags.isAdmin) { + statusArray.push('draft'); + allPosts = true; + } + } + res.locals.allPosts = allPosts; + res.locals.tagSlug = tagSlug; + res.locals.tag = tagSlug.replace("_", " "); + res.locals.pagination = this.getPaginationParameters(req, 12); + const {posts, totalPosts} = await postService.getByTags(res.locals.tag, res.locals.pagination, statusArray); + res.locals.posts = posts; + res.locals.totalPosts = totalPosts; + return next(); + + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populateTagSlug', + message: error.message, + data: { error }, + }); return next(error); } } async postBlockCommentAuthor (req, res) { - const { user: userService } = this.dtp.services; + const { + logan: loganService, + user: userService, + } = this.dtp.services; try { const displayList = this.createDisplayList('add-recipient'); await userService.blockUser(req.user._id, req.body.userId); @@ -163,9 +221,27 @@ class PostController extends SiteController { 'bottom-center', 4000, ); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postBlockCommentAuthor', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + }, + blockedUserId: req.body.userId, + }, + }); + res.status(200).json({ success: true, displayList }); } catch (error) { - this.log.error('failed to report comment', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postBlockCommentAuthor', + message: error.message, + data: { error }, + }); return res.status(error.statusCode || 500).json({ success: false, message: error.message, @@ -174,7 +250,10 @@ class PostController extends SiteController { } async postComment (req, res) { - const { comment: commentService } = this.dtp.services; + const { + comment: commentService, + logan: loganService, + } = this.dtp.services; try { const displayList = this.createDisplayList('add-recipient'); @@ -202,14 +281,38 @@ class PostController extends SiteController { 'bottom-center', 4000, ); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postComment', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + }, + comment: { + _id: res.locals.comment._id, + }, + }, + }); + res.status(200).json({ success: true, displayList }); } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postComment', + message: error.message, + data: { error }, + }); res.status(error.statusCode || 500).json({ success: false, message: error.message }); } } async postUpdateImage (req, res) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { const displayList = this.createDisplayList('post-image'); @@ -221,9 +324,26 @@ class PostController extends SiteController { 'bottom-center', 2000, ); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postUpdateImage', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + }, + }, + }); + res.status(200).json({ success: true, displayList }); } catch (error) { - this.log.error('failed to update feature image', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postUpdateImage', + message: error.message, + data: { error }, + }); return res.status(error.statusCode || 500).json({ success: false, message: error.message, @@ -232,11 +352,22 @@ class PostController extends SiteController { } async deletePostFeatureImage (req, res) { + const { logan: loganService } = this.dtp.services; + + loganService.sendRequestEvent(module.exports, req, { + level: 'alert', + message: 'Deleting a post feature image is not yet implemented', + event: 'deletePostFeatureImage', + }); + res.status(500).json({ success: false, message: 'Removing the featured image is not yet implemented'}); } async postUpdatePost (req, res, next) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { if(!req.user.flags.isAdmin){ if (!req.user._id.equals(res.locals.post.author._id) || @@ -245,15 +376,35 @@ class PostController extends SiteController { } } await postService.update(req.user, res.locals.post, req.body); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postUpdatePost', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + }, + }, + }); + res.redirect(`/post/${res.locals.post.slug}`); } catch (error) { - this.log.error('failed to update post', { postId: res.locals.post._id, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postUpdatePost', + message: error.message, + data: { error }, + }); return next(error); } } async postUpdatePostTags (req, res) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { if(!req.user.flags.isAdmin) { @@ -269,9 +420,26 @@ class PostController extends SiteController { 'bottom-center', 2000, ); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postUpdatePostTags', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + }, + }, + }); + res.status(200).json({ success: true, displayList }); } catch (error) { - this.log.error('failed to update post tags', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postUpdatePostTags', + message: error.message, + data: { error }, + }); return res.status(error.statusCode || 500).json({ success: false, message: error.message, @@ -280,18 +448,41 @@ class PostController extends SiteController { } async postCreatePost (req, res, next) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.post = await postService.create(req.user, req.body); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'postCreatePost', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + }, + }, + }); + res.redirect(`/post/${res.locals.post.slug}`); } catch (error) { - this.log.error('failed to create post', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'postCreatePost', + message: error.message, + data: { error }, + }); return next(error); } } async getComments (req, res) { - const { comment: commentService } = this.dtp.services; + const { + comment: commentService, + logan: loganService, + } = this.dtp.services; try { const displayList = this.createDisplayList('add-recipient'); @@ -322,9 +513,19 @@ class PostController extends SiteController { const replyList = `ul#post-comment-list`; displayList.addElement(replyList, 'beforeEnd', html); + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getComments', + }); + res.status(200).json({ success: true, displayList }); } catch (error) { - this.log.error('failed to fetch more comments', { postId: res.locals.post._id, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getComments', + message: error.message, + data: { error }, + }); return res.status(error.statusCode || 500).json({ success: false, message: error.message, @@ -333,7 +534,11 @@ class PostController extends SiteController { } async getView (req, res, next) { - const { comment: commentService, resource: resourceService } = this.dtp.services; + const { + comment: commentService, + logan: loganService, + resource: resourceService, + } = this.dtp.services; try { if (res.locals.post.status !== 'published') { if (!req.user) { @@ -363,68 +568,156 @@ class PostController extends SiteController { if (res.locals.post.image) { res.locals.shareImage = `https://${this.dtp.config.site.domain}/image/${res.locals.post.image._id}`; } + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getView', + }); + res.render('post/view'); } catch (error) { - this.log.error('failed to service post view', { postId: res.locals.post._id, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getView', + message: error.message, + data: { error }, + }); return next(error); } } - async getEditor (req, res) { - res.render('post/editor'); + async getEditor (req, res, next) { + const { logan: loganService } = this.dtp.services; + try { + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getEditor', + }); + res.render('post/editor'); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getEditor', + message: error.message, + data: { error }, + }); + return next(error); + } } async getComposer (req, res, next) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.post = await postService.createPlaceholder(req.user); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getComposer', + }); + res.redirect(`/post/${res.locals.post._id}/edit`); } catch (error) { - this.log.error('failed to render post composer', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getComposer', + message: error.message, + data: { error }, + }); return next(error); } } async getIndex (req, res, next) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 20); res.locals.posts = await postService.getPosts(res.locals.pagination); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getIndex', + }); + res.render('post/index'); } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getIndex', + message: error.message, + data: { error }, + }); return next(error); } } async getAuthorView (req, res, next) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 20); const {posts, totalPostCount} = await postService.getForAuthor(res.locals.author, ['published'], res.locals.pagination); res.locals.posts = posts; res.locals.totalPostCount = totalPostCount; + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getAuthorView', + }); + res.render('post/author/view'); } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getAuthorView', + message: error.message, + data: { error }, + }); return next(error); } } async getAllAuthorsView (req, res, next) { - const { user: userService } = this.dtp.services; + const { + logan: loganService, + user: userService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 20); const {authors , totalAuthorCount } = await userService.getAuthors(res.locals.pagination); res.locals.authors = authors; res.locals.totalAuthorCount = totalAuthorCount; + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getAllAuthorsView', + }); + res.render('post/author/all'); } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getAllAuthorsView', + message: error.message, + data: { error }, + }); return next(error); } } async deletePost (req, res) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { // only give admins and the author permission to delete if (!req.user.flags.isAdmin) { @@ -438,9 +731,29 @@ class PostController extends SiteController { const displayList = this.createDisplayList('add-recipient'); displayList.navigateTo('/'); + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'deletePost', + data: { + post: { + _id: res.locals.post._id, + title: res.locals.post.title, + author: { + _id: res.locals.post.author._id, + username: res.locals.post.author.username, + }, + }, + }, + }); + res.status(200).json({ success: true, displayList }); } catch (error) { - this.log.error('failed to remove post', { newletterId: res.locals.post._id, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'deletePost', + message: error.message, + data: { error }, + }); return res.status(error.statusCode || 500).json({ success: false, message: error.message, @@ -448,36 +761,16 @@ class PostController extends SiteController { } } - async populateTagSlug (req, res, next, tagSlug) { - const { post: postService } = this.dtp.services; - try { - var allPosts = false; - var statusArray = ['published']; - if (req.user) { - if (req.user.flags.isAdmin) { - statusArray.push('draft'); - allPosts = true; - } - } - res.locals.allPosts = allPosts; - res.locals.tagSlug = tagSlug; - res.locals.tag = tagSlug.replace("_", " "); - res.locals.pagination = this.getPaginationParameters(req, 12); - const {posts, totalPosts} = await postService.getByTags(res.locals.tag, res.locals.pagination, statusArray); - res.locals.posts = posts; - res.locals.totalPosts = totalPosts; - return next(); - - } catch (error) { - this.log.error('failed to populate tagSlug', { tagSlug, error }); - return next(error); - } - } - async getTagSearchView (req, res) { + const { logan: loganService } = this.dtp.services; try { res.locals.pageTitle = `Tag ${res.locals.tag} on ${this.dtp.config.site.name}`; + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getTagSearchView', + }); + res.render('post/tag/view'); } catch (error) { this.log.error('failed to service post view', { postId: res.locals.post._id, error }); @@ -487,16 +780,24 @@ class PostController extends SiteController { async getTagIndex (req, res, next) { - const { post: postService } = this.dtp.services; + const { + logan: loganService, + post: postService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 20); res.locals.posts = await postService.getPosts(res.locals.pagination); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getTagIndex', + }); + res.render('post/tag/index'); } catch (error) { return next(error); } } - } module.exports = { diff --git a/app/controllers/venue.js b/app/controllers/venue.js index a414431..e5c7b42 100644 --- a/app/controllers/venue.js +++ b/app/controllers/venue.js @@ -40,7 +40,10 @@ class VenueController extends SiteController { } async populateChannelSlug (req, res, next, channelSlug) { - const { venue: venueService } = this.dtp.services; + const { + logan: loganService, + venue: venueService, + } = this.dtp.services; try { res.locals.channel = await venueService.getChannelBySlug(channelSlug, { withCredentials: true }); if (!res.locals.channel) { @@ -53,22 +56,51 @@ class VenueController extends SiteController { return next(); } catch (error) { this.log.error('failed to populate Venue channel by slug', { channelSlug, error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'populateChannelSlug', + message: error.message, + data: { channelSlug, error }, + }); return next(error); } } - async getVenueEmbed (req, res) { - res.render('venue/embed'); + async getVenueEmbed (req, res, next) { + const { logan: loganService } = this.dtp.services; + try { + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getVenueEmbed', + }); + res.render('venue/embed'); + } catch (error) { + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getView', + message: error.message, + data: { error }, + }); + return next(error); + } } async getHome (req, res, next) { - const { venue: venueService} = this.dtp.services; + const { + logan: loganService, + venue: venueService, + } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 10); res.locals.channels = await venueService.getChannels(res.locals.pagination); res.render('venue/index'); } catch (error) { - this.log.error('failed to present the Venue home', { error }); + loganService.sendRequestEvent(module.exports, req, { + level: 'error', + event: 'getHome', + message: error.message, + data: { error }, + }); return next(error); } } From 68eb28250824dd910b76f655ea22cbbb8831ce73 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 19:02:47 -0400 Subject: [PATCH 11/76] added Logan defaults --- .env.default | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.env.default b/.env.default index 186c596..913117f 100644 --- a/.env.default +++ b/.env.default @@ -114,4 +114,13 @@ DTP_LOG_DEBUG=enabled DTP_LOG_INFO=enabled DTP_LOG_WARN=enabled -DTP_LOG_HTTP_FORMAT=combined \ No newline at end of file +DTP_LOG_HTTP_FORMAT=combined + +# +# DTP Logan Integration +# + +DTP_LOGAN=disabled +DTP_LOGAN_SCHEME=http +DTP_LOGAN_HOST= +DTP_LOGAN_API_KEY= \ No newline at end of file From d1574e519a63db74a83605ca520daa9edf5fc6a7 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 19:32:46 -0400 Subject: [PATCH 12/76] better error handling and more Logan logging --- app/controllers/admin.js | 54 +++++++++++-------- app/services/venue.js | 44 +++++++++------ .../venue/components/channel-list-item.pug | 9 ++-- 3 files changed, 65 insertions(+), 42 deletions(-) diff --git a/app/controllers/admin.js b/app/controllers/admin.js index fccd174..d3d9eb7 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -78,7 +78,7 @@ class AdminController extends SiteController { }); } - async getHomeView (req, res) { + async getHomeView (req, res, next) { const { chat: chatService, coreNode: coreNodeService, @@ -87,28 +87,36 @@ class AdminController extends SiteController { logan: loganService, user: userService, } = this.dtp.services; - - res.locals.stats = { - userSignupHourly: await dashboardService.getUserSignupsPerHour(), - memberCount: await User.estimatedDocumentCount(), - constellation: await coreNodeService.getConstellationStats(), - }; - - res.locals.channels = await venueService.getChannels(); - res.locals.pageTitle = `Admin Dashbord for ${this.dtp.config.site.name}`; - - res.locals.recentMembers = await userService.getRecent(10); - res.locals.admins = await userService.getAdmins(); - res.locals.moderators = await userService.getModerators(); - - res.locals.recentChat = await chatService.getRecent(10); - - loganService.sendRequestEvent(module.exports, req, { - level: 'info', - event: 'getHomeView', - }); - - res.render('admin/index'); + try { + res.locals.pageTitle = `Admin Dashbord for ${this.dtp.config.site.name}`; + res.locals.stats = { + userSignupHourly: await dashboardService.getUserSignupsPerHour(), + memberCount: await User.estimatedDocumentCount(), + constellation: await coreNodeService.getConstellationStats(), + }; + + try { + res.locals.channels = await venueService.getChannels(); + } catch (error) { + // fall through + res.locals.channels = [ ]; + } + + res.locals.recentMembers = await userService.getRecent(10); + res.locals.admins = await userService.getAdmins(); + res.locals.moderators = await userService.getModerators(); + + res.locals.recentChat = await chatService.getRecent(10); + + loganService.sendRequestEvent(module.exports, req, { + level: 'info', + event: 'getHomeView', + }); + + res.render('admin/index'); + } catch (error) { + return next(error); + } } } diff --git a/app/services/venue.js b/app/services/venue.js index bbc4cd9..695e88e 100644 --- a/app/services/venue.js +++ b/app/services/venue.js @@ -92,12 +92,12 @@ class VenueService extends SiteService { widgetKey: channelDefinition['credentials.widgetKey'].trim(), }; - const status = await this.updateChannelStatus(channel); channel.name = status.name; channel.description = status.description; await channel.save(); - await this.updateChannelStatus(channel); + + channel.currentStatus = await this.updateChannelStatus(channel); return channel.toObject(); } @@ -111,7 +111,6 @@ class VenueService extends SiteService { updateOp.$set.slug = this.getChannelSlug(channelDefinition.url); updateOp.$set.sortOrder = parseInt(channelDefinition.sortOrder || '0', 10); - const status = await this.updateChannelStatus(channel); updateOp.$set.name = status.name; updateOp.$set.description = status.description; @@ -126,7 +125,9 @@ class VenueService extends SiteService { updateOp.$set['credentials.widgetKey'] = channelDefinition['credentials.widgetKey'].trim(); channel = await VenueChannel.findOneAndUpdate({ _id: channel._id }, updateOp, { new: true }); - await this.updateChannelStatus(channel); + channel.currentStatus = await this.updateChannelStatus(channel); + + return channel; } async getChannels (pagination, options) { @@ -146,7 +147,7 @@ class VenueService extends SiteService { } const channels = await q.populate(this.populateVenueChannel).lean(); - for await (const channel of channels) { + for (const channel of channels) { channel.currentStatus = await this.updateChannelStatus(channel); } return channels; @@ -202,20 +203,31 @@ class VenueService extends SiteService { } async updateChannelStatus (channel) { - const requestUrl = `https://${this.soapboxDomain}/channel/${channel.slug}/status`; - this.log.info('fetching Shing channel status', { slug: channel.slug, requestUrl }); + const { logan: loganService } = this.dtp.services; + try { + const requestUrl = `https://${this.soapboxDomain}/channel/${channel.slug}/status`; + this.log.info('fetching Shing channel status', { slug: channel.slug, requestUrl }); + + const response = await fetch(requestUrl, { agent: this.httpsAgent }); + if (!response.ok) { + throw new SiteError(500, `Failed to fetch channel status: ${response.statusText}`); + } - const response = await fetch(requestUrl, { agent: this.httpsAgent }); - if (!response.ok) { - throw new SiteError(500, `Failed to fetch channel status: ${response.statusText}`); - } + const json = await response.json(); + if (!json.success) { + throw new Error(`failed to fetch channel status: ${json.message}`); + } - const json = await response.json(); - if (!json.success) { - throw new Error(`failed to fetch channel status: ${json.message}`); + return json.channel; + } catch (error) { + loganService.sendEvent(module.exports, { + level: 'error', + event: 'updateChannelStatus', + message: error.message, + data: { error }, + }); + return; // undefined } - - return json.channel; } getChannelSlug (channelUrl) { diff --git a/app/views/venue/components/channel-list-item.pug b/app/views/venue/components/channel-list-item.pug index 4284180..6be6de6 100644 --- a/app/views/venue/components/channel-list-item.pug +++ b/app/views/venue/components/channel-list-item.pug @@ -15,7 +15,10 @@ mixin renderVenueChannelListItem (channel, options) .uk-width-expand.uk-text-truncate +renderUserLink(channel.owner) .uk-width-auto - if channel.currentStatus.status === 'live' - span.uk-text-success LIVE + if channel.currentStatus && channel.currentStatus.success + if channel.currentStatus.status === 'live' + span.uk-text-success LIVE + else + span= moment(channel.currentStatus.lastLive).fromNow() else - span= moment(channel.currentStatus.lastLive).fromNow() \ No newline at end of file + span --- \ No newline at end of file From 2a37444b14dfa2bf66b4967d3286c39a17eb557f Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 19:59:47 -0400 Subject: [PATCH 13/76] remove all attachments for user when banning user --- app/services/attachment.js | 14 ++++++++++++++ app/services/user.js | 2 ++ 2 files changed, 16 insertions(+) diff --git a/app/services/attachment.js b/app/services/attachment.js index 4d9f1f9..e8369c5 100644 --- a/app/services/attachment.js +++ b/app/services/attachment.js @@ -183,6 +183,20 @@ class AttachmentService extends SiteService { return this.attachmentTemplate({ attachment, attachmentOptions }); } + /** + * Removes all attachments and everything on storage about them for a + * specified User. + * @param {User} owner the owner of the attachments to be removed + */ + async removeForOwner (owner) { + const handler = this.remove.bind(this); + await Attachment + .find({ owner: owner._id }) + .lean() + .cursor() + .eachAsync(handler); + } + /** * Creates a Bull Queue job to delete an Attachment including it's processed * and original media files. diff --git a/app/services/user.js b/app/services/user.js index f8d0555..28d3a6f 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -821,6 +821,7 @@ class UserService extends SiteService { async ban (user) { const { + attachment: attachmentService, chat: chatService, comment: commentService, contentReport: contentReportService, @@ -855,6 +856,7 @@ class UserService extends SiteService { await otpAuthService.removeForUser(user); await stickerService.removeForUser(user); await userNotificationService.removeForUser(user); + await attachmentService.removeForOwner(user); } checkRestrictedKeys (method, definition) { From c9d96df7770a1913af48cbcd779732f4aa9ee9a6 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 19:59:53 -0400 Subject: [PATCH 14/76] v0.8.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7507c2e..f01c468 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.7", + "version": "0.8.8", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 42292b96da9a17293dee3331bc3f77be787be479 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 20:00:58 -0400 Subject: [PATCH 15/76] archive/remove user's posts when banning user --- app/services/user.js | 2 ++ app/workers/reeeper/job/archive-user-local.js | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/app/services/user.js b/app/services/user.js index b64dcc7..d1d6575 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -925,6 +925,7 @@ class UserService extends SiteService { csrfToken: csrfTokenService, otpAuth: otpAuthService, page: pageService, + post: postService, sticker: stickerService, userNotification: userNotificationService, } = this.dtp.services; @@ -952,6 +953,7 @@ class UserService extends SiteService { ); await pageService.removeForAuthor(user); + await postService.removeForAuthor(user); await chatService.removeForUser(user); await commentService.removeForAuthor(user); diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js index 42a967c..6f92f66 100644 --- a/app/workers/reeeper/job/archive-user-local.js +++ b/app/workers/reeeper/job/archive-user-local.js @@ -97,6 +97,11 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { await this.archiveUserStickers(job); await this.archiveUserImages(job); + /* + * Archive DTP Sites specific content + */ + await this.archiveUserPosts(job); + /* * Create the .zip file archive, upload it to storage, and create the * UserArchive record. @@ -309,6 +314,33 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { }); } + async archiveUserPosts (job) { + const Post = mongoose.model('Post'); + + job.data.postPath = path.join(job.data.workPath, 'posts'); + await fs.promises.mkdir(job.data.postPath, { recursive: true }); + + this.log.info('archiving user blog posts', { + user: { + _id: job.data.user._id, + username: job.data.user.username, + }, + }); + + await Post + .find({ author: job.data.user._id }) + .cursor() + .eachAsync(async (post) => { + const postFilename = path.join(job.data.postPath, `post-${post._id}.json`); + try { + await fs.promises.writeFile(postFilename, JSON.stringify(post, null, 2)); + } catch (error) { + this.log.error('failed to write user blog post file', { postFilename, error }); + // fall through + } + }); + } + async createArchiveFile (job) { const { minio: minioService } = this.dtp.services; try { From 572f99413543b0799be89ab3155bb31b9e953b57 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 20:01:11 -0400 Subject: [PATCH 16/76] supply empty optIn if undefined --- app/views/admin/user/form.pug | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/admin/user/form.pug b/app/views/admin/user/form.pug index 9182898..e334d56 100644 --- a/app/views/admin/user/form.pug +++ b/app/views/admin/user/form.pug @@ -75,6 +75,7 @@ block content | Can Publish Posts .uk-margin + - userAccount.optIn = userAccount.optIn || { }; label.uk-form-label Opt-Ins div(uk-grid).uk-grid-small label From 942e61043e6fa63985367652f63ecd6369173f04 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 20:27:30 -0400 Subject: [PATCH 17/76] archive user attachments --- app/workers/reeeper/job/archive-user-local.js | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js index 42a967c..a2a4148 100644 --- a/app/workers/reeeper/job/archive-user-local.js +++ b/app/workers/reeeper/job/archive-user-local.js @@ -96,6 +96,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { await this.archiveUserComments(job); await this.archiveUserStickers(job); await this.archiveUserImages(job); + await this.archiveUserAttachments(job); /* * Create the .zip file archive, upload it to storage, and create the @@ -119,7 +120,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { }); // await User.deleteOne({ _id: job.data.userId }); } catch (error) { - this.log.error('failed to delete attachment', { attachmentId: job.data.attachmentId, error }); + this.log.error('failed to archive user', { userId: job.data.userId, error }); throw error; } finally { if (job.data.workPath) { @@ -309,6 +310,71 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { }); } + async archiveUserAttachments (job) { + const Attachment = mongoose.model('Attachment'); + const { minio: minioService } = this.dtp.services; + + job.data.attachmentPath = path.join(job.data.workPath, 'attachments'); + await fs.promises.mkdir(job.data.attachmentPath, { recursive: true }); + + job.data.originalAttachmentPath = path.join(job.data.attachmentPath, 'original'); + await fs.promises.mkdir(job.data.originalAttachmentPath, { recursive: true }); + + job.data.encodedAttachmentPath = path.join(job.data.attachmentPath, 'encoded'); + await fs.promises.mkdir(job.data.encodedAttachmentPath, { recursive: true }); + + this.log.info('archiving user attachments', { + user: { + _id: job.data.user._id, + username: job.data.user.username, + }, + }); + + await Attachment + .find({ owner: job.data.user._id }) + .cursor() + .eachAsync(async (attachment) => { + try { + /* + * Write the JSON record archive + */ + const metadataFilename = path.join(job.data.attachmentPath, `attachment-${attachment._id}.metadata.json`); + await fs.promises.writeFile(metadataFilename, JSON.stringify(attachment, null, 2)); + + /* + * Download and save the original file (if present) + */ + if (attachment.original && attachment.original.bucket && attachment.original.key) { + let originalExt = mime.getExtension(attachment.original.mime); + const originalFilename = path.join(job.data.originalAttachmentPath, `attachment-${attachment._id}.${originalExt}`); + await minioService.downloadFile({ + bucket: attachment.original.bucket, + key: attachment.original.key, + filePath: originalFilename, + }); + } + + /* + * Download and save the encoded file (if present) + */ + if (attachment.encoded && attachment.encoded.bucket && attachment.encoded.key) { + let encodedExt = mime.getExtension(attachment.encoded.mime); + const encodedFilename = path.join(job.data.encodedAttachmentPath, `attachment-${attachment._id}.${encodedExt}`); + await minioService.downloadFile({ + bucket: attachment.encoded.bucket, + key: attachment.encoded.key, + filePath: encodedFilename, + }); + } + } catch (error) { + this.log.error('failed to archive attachment', { + attachment: { _id: attachment._id }, + error, + }); + } + }); + } + async createArchiveFile (job) { const { minio: minioService } = this.dtp.services; try { From d59a951df77882e7459dc0dfad94a5b61b2ab33a Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 20:27:44 -0400 Subject: [PATCH 18/76] v0.8.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f01c468..e2c2d2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.8", + "version": "0.8.9", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From b44eca417be0129fc82490a6e42e819db8f50c39 Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 20:37:24 -0400 Subject: [PATCH 19/76] corrected a file path --- app/workers/reeeper/job/archive-user-local.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js index a2a4148..54074a0 100644 --- a/app/workers/reeeper/job/archive-user-local.js +++ b/app/workers/reeeper/job/archive-user-local.js @@ -224,7 +224,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { .find({ author: job.data.userId }) .cursor() .eachAsync(async (comment) => { - const commentFilename = path.join(job.data.imagePath, `comment-${comment._id}.json`); + const commentFilename = path.join(job.data.commentPath, `comment-${comment._id}.json`); await fs.promises.writeFile(commentFilename, JSON.stringify(comment, null, 2)); }); } From 4d308dee56d33b686d8a4847707bb5cfa7795fdd Mon Sep 17 00:00:00 2001 From: rob Date: Sun, 18 Jun 2023 20:37:31 -0400 Subject: [PATCH 20/76] v0.8.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2c2d2f..b54d061 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.9", + "version": "0.8.10", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 23a2a5c7065536175202d497578e4dfcd20816d7 Mon Sep 17 00:00:00 2001 From: CyberShell Date: Mon, 19 Jun 2023 01:45:12 +0000 Subject: [PATCH 21/76] Admin banning/update logic - Deny admin ability to ban himself - Deny admin ability to remove his own admin privileges - Deny admin ability to archive himself --- app/controllers/admin/user.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index dd1cf2d..8687940 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -100,10 +100,14 @@ class UserAdminController extends SiteController { user: userService, } = this.dtp.services; try { + const user = await userService.getLocalUserAccount(req.body.userId); if (!user) { throw new SiteError(404, 'User not found'); } + if (req.user && req.user._id.equals(user._id)) { + throw new SiteError(400, "You can't archive yourself"); + } res.locals.job = await userService.archiveLocalUser(user); loganService.sendRequestEvent(module.exports, req, { level: 'info', @@ -138,6 +142,11 @@ class UserAdminController extends SiteController { this.log.debug('local user update', { action: req.body.action }); switch (req.body.action) { case 'update': + if (req.user._id.equals(res.locals.userAccount._id)) { + if (req.user.flags.isAdmin && !(userDefinition.isAdmin === 'on')) { + throw new SiteError(400, "You can't remove your own admin privileges"); + } + } await userService.updateLocalForAdmin(res.locals.userAccount, req.body); loganService.sendRequestEvent(module.exports, req, { level: 'info', @@ -153,6 +162,9 @@ class UserAdminController extends SiteController { break; case 'ban': + if (req.user._id.equals(res.locals.userAccount._id)) { + throw new SiteError(400, "You can't ban yourself"); + } await userService.ban(res.locals.userAccount); loganService.sendRequestEvent(module.exports, req, { level: 'info', From 3811fbfb83bf271ef8c7fa73375adff8b1b85897 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:20:38 -0400 Subject: [PATCH 22/76] add check to make sure image has an owner before rendering the owner --- app/views/admin/image/index.pug | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/views/admin/image/index.pug b/app/views/admin/image/index.pug index 81f40d7..03823ad 100644 --- a/app/views/admin/image/index.pug +++ b/app/views/admin/image/index.pug @@ -33,11 +33,12 @@ block content span i.fas.fa-trash span.uk-margin-small-left Delete image - li - a(href=`/admin/image/${image._id}/archive-user`).uk-text-truncate - span - i.fas.fa-file-archive - span.uk-margin-small-left Archive and ban #[span.uk-text-bold= image.owner.username] + if image.owner + li + a(href=`/admin/image/${image._id}/archive-user`).uk-text-truncate + span + i.fas.fa-file-archive + span.uk-margin-small-left Archive and ban #[span.uk-text-bold= image.owner.username] +renderPaginationBar('/admin/image', images.totalImageCount) From 108c8421383393659e8a7397c18772e5601e43fd Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:20:46 -0400 Subject: [PATCH 23/76] v0.8.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b54d061..cbf4375 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.10", + "version": "0.8.11", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 40e5b7863317e80b09ba60bf64425d1c506ac0c3 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:23:12 -0400 Subject: [PATCH 24/76] v0.8.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbf4375..c27efce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.11", + "version": "0.8.12", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 32f325e20ceb61130d658c953d6daced9115e4a4 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:24:14 -0400 Subject: [PATCH 25/76] v0.7.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1975bc..862fa90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.1", + "version": "0.7.2", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From f4e645578c7ee4fcd14f6a9430e79ea7720fc223 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:28:21 -0400 Subject: [PATCH 26/76] correcting use of incorrect variables and unclear Boolean logic --- app/controllers/admin/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index 8687940..e80949d 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -143,7 +143,7 @@ class UserAdminController extends SiteController { switch (req.body.action) { case 'update': if (req.user._id.equals(res.locals.userAccount._id)) { - if (req.user.flags.isAdmin && !(userDefinition.isAdmin === 'on')) { + if (req.user.flags.isAdmin && (req.body.isAdmin !== 'on')) { throw new SiteError(400, "You can't remove your own admin privileges"); } } From 3a383c5c2cda61976b570aa5aa4c66364eff711f Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:28:31 -0400 Subject: [PATCH 27/76] v0.8.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c27efce..fbdbd11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.12", + "version": "0.8.13", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 43fdc359ff0a72ab36cc55397c3375732f88325b Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:30:41 -0400 Subject: [PATCH 28/76] v0.7.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 862fa90..b4ec4e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.2", + "version": "0.7.3", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 96bebe8bdb753ff25231df20b4fca90cb034d57f Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:40:57 -0400 Subject: [PATCH 29/76] v0.8.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbdbd11..cd36740 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.13", + "version": "0.8.14", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From d9361d48a02b8611f3904d96ba7f068400cb1a2c Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:41:29 -0400 Subject: [PATCH 30/76] v0.7.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4ec4e3..9a214de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.3", + "version": "0.7.4", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From c30574324bfd355f891616c253fcaa1db38f8ad2 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:44:59 -0400 Subject: [PATCH 31/76] actually ban and remove archived users --- app/workers/reeeper/job/archive-user-local.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js index 54074a0..85b7c85 100644 --- a/app/workers/reeeper/job/archive-user-local.js +++ b/app/workers/reeeper/job/archive-user-local.js @@ -87,7 +87,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { /* * Disable the User account (which destroys their session and cookie(s)) */ - // await this.disableUser(job); + await this.disableUser(job); /* * Archive the User's content to the workPath on the local file system. @@ -110,7 +110,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { username: job.data.user.username, }, }); - // await userService.ban(job.data.user); + await userService.ban(job.data.user); this.log.info('removing user', { user: { @@ -118,7 +118,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { username: job.data.user.username, }, }); - // await User.deleteOne({ _id: job.data.userId }); + await User.deleteOne({ _id: job.data.userId }); } catch (error) { this.log.error('failed to archive user', { userId: job.data.userId, error }); throw error; From e5a9940506b21004614a86d3d75579205d62b4f3 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:45:07 -0400 Subject: [PATCH 32/76] v0.8.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cd36740..ae66df3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.14", + "version": "0.8.15", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 1cdb51ce4a37a98541d04e94225b40bbfb90230e Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 00:46:58 -0400 Subject: [PATCH 33/76] v0.7.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9a214de..0907f3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.4", + "version": "0.7.5", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 67e5ac3c37432addcaa6f32667d204f3a4fa89f0 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 02:27:00 -0400 Subject: [PATCH 34/76] added update-page-cache action to CLI --- app/services/page.js | 180 +++++++++++++++++++++++-------------------- dtp-sites-cli.js | 22 ++++++ 2 files changed, 119 insertions(+), 83 deletions(-) diff --git a/app/services/page.js b/app/services/page.js index a12cf35..abec211 100644 --- a/app/services/page.js +++ b/app/services/page.js @@ -159,7 +159,6 @@ class PageService extends SiteService { return this.getById(pageId); } - async isParentPage (page) { if (page) { page = [page]; @@ -183,24 +182,37 @@ class PageService extends SiteService { return pages; } - async deletePage (page) { - this.log.info('deleting page', { pageId: page._id }); + async deletePage (page, options) { + options = Object.assign({ updateCache: true }, options); + + this.log.info('deleting page', { pageId: page._id, options }); await Page.deleteOne({ _id: page._id }); - await this.cacheMainMenuPages(); + + if (options.updateCache) { + await this.cacheMainMenuPages(); + } } async removeForAuthor (author) { + /* + * Execute the updates without page cache updates + */ await Page .find({ author: author._id }) .cursor() .eachAsync(async (page) => { try { - await this.deletePage(page); + await this.deletePage(page, { updateCache: false }); } catch (error) { this.log.error('failed to remove page for author', { error }); // fall through } }); + + /* + * and update the page cache once, instead. + */ + await this.cacheMainMenuPages(); } createPageSlug (pageId, pageTitle) { @@ -212,89 +224,91 @@ class PageService extends SiteService { } async cacheMainMenuPages ( ) { - try { - const pages = await Page - .find({ status: 'published' }) - .select('slug menu') - .populate({path: 'menu.parent'}) - .lean(); - let mainMenu = []; - await SiteAsync.each(pages, async (page) => { - if (page.menu.parent) { - let parent = page.menu.parent; - if (parent.status === 'published') { - let parentPage = mainMenu.find(item => item.slug === parent.slug); - if (parentPage) { - let childPage = { - url: `/page/${page.slug}`, - slug: page.slug, - icon: page.menu.icon, - label: page.menu.label, - order: page.menu.order, - }; - parentPage.children.splice(childPage.order, 0, childPage); - } - else { - let parentPage = { - url: `/page/${parent.slug}`, - slug: parent.slug, - icon: parent.menu.icon, - label: parent.menu.label, - order: parent.menu.order, - children: [], - }; - let childPage = { - url: `/page/${page.slug}`, - slug: page.slug, - icon: page.menu.icon, - label: page.menu.label, - order: page.menu.order, - }; - parentPage.children.splice(childPage.order, 0, childPage); - mainMenu.splice(parentPage.order, 0, parentPage); + + try { + await Page + .find({ status: 'published' }) + .select('slug menu') + .populate({path: 'menu.parent'}) + .lean() + .cursor() + .eachAsync(async (page) => { + if (page.menu.parent) { + let parent = page.menu.parent; + if (parent.status === 'published') { + let parentPage = mainMenu.find(item => item.slug === parent.slug); + if (parentPage) { + let childPage = { + url: `/page/${page.slug}`, + slug: page.slug, + icon: page.menu.icon, + label: page.menu.label, + order: page.menu.order, + }; + parentPage.children.splice(childPage.order, 0, childPage); + } + else { + let parentPage = { + url: `/page/${parent.slug}`, + slug: parent.slug, + icon: parent.menu.icon, + label: parent.menu.label, + order: parent.menu.order, + children: [], + }; + let childPage = { + url: `/page/${page.slug}`, + slug: page.slug, + icon: page.menu.icon, + label: page.menu.label, + order: page.menu.order, + }; + parentPage.children.splice(childPage.order, 0, childPage); + mainMenu.splice(parentPage.order, 0, parentPage); + } + } else { + let menuPage = { + url: `/page/${page.slug}`, + slug: page.slug, + icon: page.menu.icon, + label: page.menu.label, + order: page.menu.order, + children: [], + }; + mainMenu.splice(menuPage.order, 0, menuPage); + } + } else { + let isPageInMenu = mainMenu.find(item => item.slug === page.slug); + + if (!isPageInMenu) { + let menuPage = { + url: `/page/${page.slug}`, + slug: page.slug, + icon: page.menu.icon, + label: page.menu.label, + order: page.menu.order, + children: [], + }; + mainMenu.push(menuPage); + } } - } else { - let menuPage = { - url: `/page/${page.slug}`, - slug: page.slug, - icon: page.menu.icon, - label: page.menu.label, - order: page.menu.order, - children: [], - }; - mainMenu.splice(menuPage.order, 0, menuPage); - } - } else { - let isPageInMenu = mainMenu.find(item => item.slug === page.slug); - - if (!isPageInMenu) { - let menuPage = { - url: `/page/${page.slug}`, - slug: page.slug, - icon: page.menu.icon, - label: page.menu.label, - order: page.menu.order, - children: [], - }; - mainMenu.push(menuPage); + }); + + /* + * Sort the menu data + */ + mainMenu.sort((a, b) => a.order - b.order); + for (const menu of mainMenu) { + if (menu.children) { + menu.children.sort((a, b) => a.order - b.order); } } - }); - - mainMenu.sort((a, b) => a.order - b.order); - - await SiteAsync.each(mainMenu, async (menu) => { - if (menu.children) { - menu.children.sort((a, b) => a.order - b.order); - } - }); - const deleteResponse = await this.dtp.services.cache.del("mainMenu"); - this.dtp.log.info(deleteResponse); - const storeResponse = await this.dtp.services.cache.setObject("mainMenu", mainMenu); - this.dtp.log.info(storeResponse); - // const getresp = await this.dtp.services.cache.getObject("mainMenu"); + /* + * Update the cache + */ + await this.dtp.services.cache.setObject("mainMenu", mainMenu); } catch (error) { this.dtp.log.error('failed to build page menu', { error }); } diff --git a/dtp-sites-cli.js b/dtp-sites-cli.js index 116f423..ac9537f 100644 --- a/dtp-sites-cli.js +++ b/dtp-sites-cli.js @@ -197,6 +197,17 @@ module.requestCoreConnect = async (host) => { module.log.info('connect tranaction', { txConnect }); }; +module.updatePageCache = async ( ) => { + const { page: pageService } = module.services; + try { + module.log.info('rebulding Page cache'); + await pageService.cacheMainMenuPages(); + } catch (error) { + module.log.error('failed to update page cache', { error }); + // fall through + } +}; + /* * SERVER INIT */ @@ -270,7 +281,18 @@ module.requestCoreConnect = async (host) => { case 'welcome-email': await module.sendWelcomeEmail(target); break; + + /* + * Sites commands + */ + + case 'update-page-cache': + await module.updatePageCache(target); + break; + /* + * Error + */ default: throw new Error(`invalid action: ${module.app.options.action}`); } From e677bf57594c99780ff4c4608f24c783704901c5 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 02:27:07 -0400 Subject: [PATCH 35/76] v0.7.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0907f3d..ff9e5e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.5", + "version": "0.7.6", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 7fa757139ee87e008d839c2680945eb942d4be75 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 02:27:57 -0400 Subject: [PATCH 36/76] remove SiteAsync dep --- app/services/page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/page.js b/app/services/page.js index abec211..b465865 100644 --- a/app/services/page.js +++ b/app/services/page.js @@ -7,7 +7,7 @@ const striptags = require('striptags'); const slug = require('slug'); -const { SiteService, SiteError, SiteAsync } = require('../../lib/site-lib'); +const { SiteService, SiteError } = require('../../lib/site-lib'); const mongoose = require('mongoose'); const ObjectId = mongoose.Types.ObjectId; From 1a769b799de1e414b568fc021aaca5cdc8dce408 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 02:28:02 -0400 Subject: [PATCH 37/76] v0.7.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff9e5e0..d11c03b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.6", + "version": "0.7.7", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 147791ec8a6620bd85290fbe24c9da0aa8954ce9 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:00:34 -0400 Subject: [PATCH 38/76] add recent comments to Admin dashboard display --- app/controllers/admin.js | 2 ++ app/services/comment.js | 15 +++++++++++++++ app/views/admin/index.pug | 26 +++++++++++++++++++++----- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/app/controllers/admin.js b/app/controllers/admin.js index ee0d400..1397570 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -77,6 +77,7 @@ class AdminController extends SiteController { async getHomeView (req, res) { const { chat: chatService, + comment: commentService, coreNode: coreNodeService, dashboard: dashboardService, logan: loganService, @@ -95,6 +96,7 @@ class AdminController extends SiteController { res.locals.admins = await userService.getAdmins(); res.locals.moderators = await userService.getModerators(); + res.locals.recentComments = await commentService.getRecent(10); res.locals.recentChat = await chatService.getRecent(10); loganService.sendRequestEvent(module.exports, req, { diff --git a/app/services/comment.js b/app/services/comment.js index 8a3f115..5bd3614 100644 --- a/app/services/comment.js +++ b/app/services/comment.js @@ -251,6 +251,21 @@ class CommentService extends SiteService { return comments; } + /** + * Meant for use in admin tools. + */ + async getRecent (pagination) { + const comments = await Comment + .find() + .sort({ created: -1 }) + .skip(pagination.skip) + .limit(pagination.cpp) + .populate(this.populateComment) + .lean(); + const totalCommentCount = await Comment.estimatedDocumentCount(); + return { comments, totalCommentCount }; + } + async getForAuthor (author, pagination) { const comments = await Comment .find({ // index: 'comment_author_by_type' diff --git a/app/views/admin/index.pug b/app/views/admin/index.pug index 86ff8f1..7d55400 100644 --- a/app/views/admin/index.pug +++ b/app/views/admin/index.pug @@ -3,6 +3,7 @@ block content include user/components/list-item include ../chat/components/message + include ../comment/components/comment div(uk-grid) div(class="uk-width-1-1 uk-width-auto@m") @@ -49,6 +50,15 @@ block content else div There are no system-level moderators. + h3 Recent Members + if Array.isArray(recentMembers) && (recentMembers.length > 0) + ul.uk-list.uk-list-divider + each member in recentMembers + li + +renderUserListItem(member) + else + div There are no recent members. + div(class="uk-width-1-1 uk-width-1-3@l") h3 Recent Chat if Array.isArray(recentChat) && (recentChat.length > 0) @@ -66,14 +76,20 @@ block content div There is no recent chat. div(class="uk-width-1-1 uk-width-1-3@l") - h3 Recent Members - if Array.isArray(recentMembers) && (recentMembers.length > 0) + h3 Recent Comments + if Array.isArray(recentComments.comments) && (recentComments.comments.length > 0) ul.uk-list.uk-list-divider - each member in recentMembers + each comment in recentComments.comments li - +renderUserListItem(member) + div(uk-grid).uk-grid-small + .uk-width-expand + +renderComment(comment) + .uk-width-auto + a(href=`/admin/user/local/${comment.author._id}`, uk-tooltip={ title: 'Manage user account' }).uk-button.uk-button-default.uk-button-small.uk-border-rounded + span + i.fas.fa-wrench else - div There are no recent members. + div There are no recent comments. block viewjs script(src="/chart.js/chart.min.js") From 304564f102400f3c6bdfc46889631b6faccabc55 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:00:42 -0400 Subject: [PATCH 39/76] v0.8.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae66df3..063fcc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.15", + "version": "0.8.16", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 0006ce794a04039407bd5820b908e511f3450026 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:14:51 -0400 Subject: [PATCH 40/76] created admin comment render component --- .../admin/comment/components/comment.pug | 50 +++++++++++++++++++ app/views/admin/index.pug | 3 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 app/views/admin/comment/components/comment.pug diff --git a/app/views/admin/comment/components/comment.pug b/app/views/admin/comment/components/comment.pug new file mode 100644 index 0000000..2b34262 --- /dev/null +++ b/app/views/admin/comment/components/comment.pug @@ -0,0 +1,50 @@ +mixin renderComment (comment) + article(data-comment-id= comment._id).uk-comment.dtp-site-comment + header.uk-comment-header + div(uk-grid).uk-grid-medium.uk-flex-middle + .uk-width-auto + if comment.author.picture && comment.author.picture.small + img(src= `/image/${comment.author.picture.small._id}`).site-profile-picture.sb-small.uk-comment-avatar + else + img(src="/img/default-member.png").site-profile-picture.sb-small.uk-comment-avatar + + .uk-width-expand + h4.uk-comment-title.uk-margin-remove= comment.author.displayName || comment.author.username + .uk-comment-meta= moment(comment.created).fromNow() + + .uk-comment-body + case comment.status + when 'published' + if comment.flags && comment.flags.isNSFW + div.uk-alert.uk-alert-info.uk-border-rounded + div(uk-grid).uk-grid-small.uk-text-small.uk-flex-middle + .uk-width-expand NSFW comment hidden by default. Use the eye to show/hide. + .uk-width-auto + button( + type="button", + uk-toggle={ target: `.comment-content[data-comment-id="${comment._id}"]` }, + title="Show/hide the comment text", + ).uk-button.uk-button-link + span + i.fas.fa-eye + .comment-content(data-comment-id= comment._id, hidden= comment.flags ? comment.flags.isNSFW : false)!= marked.parse(comment.content) + when 'removed' + .comment-content.uk-text-muted [comment removed] + when 'mod-warn' + alert + span A warning has been added to this comment. + button(type="button", uk-toggle={ target: `.comment-content[data-comment-id="${comment._id}"]` }) + .comment-content(data-comment-id= comment._id, hidden)!= marked.parse(comment.content) + when 'mod-removed' + .comment-content.uk-text-muted [comment removed] + + //- Comment meta bar + div(uk-grid).uk-grid-small + .uk-width-auto + +renderLabeledIcon('fa-chevron-up', formatCount(comment.resourceStats.upvoteCount)) + .uk-width-auto + +renderLabeledIcon('fa-chevron-down', formatCount(comment.resourceStats.downvoteCount)) + .uk-width-auto + +renderLabeledIcon('fa-comment', formatCount(comment.commentStats.replyCount)) + .uk-width-auto + +renderLabeledIcon('fa-reply', 'reply') \ No newline at end of file diff --git a/app/views/admin/index.pug b/app/views/admin/index.pug index 7d55400..1197b54 100644 --- a/app/views/admin/index.pug +++ b/app/views/admin/index.pug @@ -2,8 +2,9 @@ extends layouts/main block content include user/components/list-item + include comment/components/comment + include ../chat/components/message - include ../comment/components/comment div(uk-grid) div(class="uk-width-1-1 uk-width-auto@m") From 6a47a1c06ec408bbfce2d5f6eb7ce91f68404b28 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:15:00 -0400 Subject: [PATCH 41/76] v0.8.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 063fcc3..09b75d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.16", + "version": "0.8.17", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From d342b8508dc84c72546bc652f300a980dd1a6cf8 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:24:55 -0400 Subject: [PATCH 42/76] comment admin touch-ups --- .../admin/comment/components/comment.pug | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/app/views/admin/comment/components/comment.pug b/app/views/admin/comment/components/comment.pug index 2b34262..d480496 100644 --- a/app/views/admin/comment/components/comment.pug +++ b/app/views/admin/comment/components/comment.pug @@ -1,6 +1,6 @@ mixin renderComment (comment) - article(data-comment-id= comment._id).uk-comment.dtp-site-comment - header.uk-comment-header + div(data-comment-id= comment._id).uk-card.uk-card-default.uk-card-small.dtp-site-comment.uk-border-rounded + .uk-card-header div(uk-grid).uk-grid-medium.uk-flex-middle .uk-width-auto if comment.author.picture && comment.author.picture.small @@ -12,7 +12,7 @@ mixin renderComment (comment) h4.uk-comment-title.uk-margin-remove= comment.author.displayName || comment.author.username .uk-comment-meta= moment(comment.created).fromNow() - .uk-comment-body + .uk-card-body case comment.status when 'published' if comment.flags && comment.flags.isNSFW @@ -39,12 +39,11 @@ mixin renderComment (comment) .comment-content.uk-text-muted [comment removed] //- Comment meta bar - div(uk-grid).uk-grid-small - .uk-width-auto - +renderLabeledIcon('fa-chevron-up', formatCount(comment.resourceStats.upvoteCount)) - .uk-width-auto - +renderLabeledIcon('fa-chevron-down', formatCount(comment.resourceStats.downvoteCount)) - .uk-width-auto - +renderLabeledIcon('fa-comment', formatCount(comment.commentStats.replyCount)) - .uk-width-auto - +renderLabeledIcon('fa-reply', 'reply') \ No newline at end of file + .uk-card-footer + div(uk-grid).uk-grid-small.uk-text-small.uk-text-muted + .uk-width-auto + +renderLabeledIcon('fa-chevron-up', formatCount(comment.resourceStats.upvoteCount)) + .uk-width-auto + +renderLabeledIcon('fa-chevron-down', formatCount(comment.resourceStats.downvoteCount)) + .uk-width-auto + +renderLabeledIcon('fa-comment', formatCount(comment.commentStats.replyCount)) \ No newline at end of file From de01209fe94e4fdce10125860c4ed2d2b9355e28 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:25:01 -0400 Subject: [PATCH 43/76] v0.8.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09b75d4..e5ae23e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.17", + "version": "0.8.18", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From b1c66a5dec1921d899839304c2178328eaf3cb68 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 03:25:47 -0400 Subject: [PATCH 44/76] v0.7.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d11c03b..b44c3b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.7", + "version": "0.7.8", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 2ab9ece8610112405e6de8710120e414c587d3a4 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 16:29:45 -0400 Subject: [PATCH 45/76] refactored `updateTimestamps` out of Chat into the base App Moved the definition of updateTimestamps from Chat into the library base App along with the call to update on-page timestamps during the creation of the App as a convenience. Any element following the `data-dtp-timestamp` and `data-dtp-timestamp-format` conventions will have its `textContent` set to a client-local representation of that date/time. --- app/views/chat/components/message.pug | 2 +- client/js/site-chat.js | 15 ++--------- lib/client/js/dtp-app.js | 36 +++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/app/views/chat/components/message.pug b/app/views/chat/components/message.pug index 017c94a..793800a 100644 --- a/app/views/chat/components/message.pug +++ b/app/views/chat/components/message.pug @@ -36,7 +36,7 @@ mixin renderChatMessage (message, options = { }) //- "time" is filled in by the JavaScript client using the browser's locale //- information so that "time" is always in the user's display timezone. - .chat-timestamp(data-dtp-timestamp= message.created).uk-text-small.uk-text-muted + .chat-timestamp(data-dtp-timestamp= message.created, data-dtp-timestamp-format= 'datetime').uk-text-small.uk-text-muted if Array.isArray(message.stickers) && (message.stickers.length > 0) each sticker in message.stickers diff --git a/client/js/site-chat.js b/client/js/site-chat.js index 226dd9f..23af616 100644 --- a/client/js/site-chat.js +++ b/client/js/site-chat.js @@ -61,8 +61,6 @@ export default class SiteChat { this.mutedUsers = window.localStorage.mutedUsers ? JSON.parse(window.localStorage.mutedUsers) : [ ]; this.filterChatView(); } - - this.updateTimestamps(); } async filterChatView ( ) { @@ -183,7 +181,7 @@ export default class SiteChat { this.ui.isModifying = true; this.ui.messageList.insertAdjacentHTML('beforeend', message.html); this.trimMessages(); - this.updateTimestamps(); + this.app.updateTimestamps(); if (isAtBottom) { /* @@ -224,7 +222,7 @@ export default class SiteChat { this.ui.messageList.appendChild(systemMessage); this.trimMessages(); - this.updateTimestamps(); + this.app.updateTimestamps(); if (this.ui.isAtBottom) { this.ui.messageList.scrollTo(0, this.ui.messageList.scrollHeight); @@ -237,15 +235,6 @@ export default class SiteChat { } } - updateTimestamps ( ) { - const timestamps = document.querySelectorAll('[data-dtp-timestamp]'); - timestamps.forEach((timestamp) => { - const created = timestamp.getAttribute('data-dtp-timestamp'); - const format = timestamp.getAttribute('data-dtp-time-format'); - timestamp.textContent = moment(created).format(format || 'MMM DD, YYYY, [at] hh:mm:ss a'); - }); - } - createEmojiReact (message) { this.ui.reactions.create(message.reaction); } diff --git a/lib/client/js/dtp-app.js b/lib/client/js/dtp-app.js index 6689f6b..6621d86 100644 --- a/lib/client/js/dtp-app.js +++ b/lib/client/js/dtp-app.js @@ -18,6 +18,8 @@ export default class DtpApp { this.log.debug('constructor', 'creating DisplayEngine instance'); this.displayEngine = new DtpDisplayEngine(); + + this.updateTimestamps(); } async connect (options) { @@ -203,4 +205,38 @@ export default class DtpApp { return isValid; } + + /** + * Finds every element with the `data-dtp-timestamp` attribute, and sets the + * text content of that element to the client-local representation of that + * timestamp using the formatting provided by the `data-dtp-timestamp-format` + * attribute. + */ + updateTimestamps ( ) { + const nodeList = document.querySelectorAll("[data-dtp-timestamp]"); + for (const ts of nodeList) { + const date = ts.getAttribute('data-dtp-timestamp'); + if (!date) { + continue; + } + + const format = ts.getAttribute('data-dtp-timestamp-format'); + switch (format) { + case 'date': + ts.textContent = moment(date).format('MMM DD, YYYY'); + break; + case 'datetime': + ts.textContent = moment(date).format('MMMM D, h:mm a'); + break; + case 'fuzzy': + ts.textContent = moment(date).fromNow(); + break; + + case 'timestamp': + default: + ts.textContent = moment(date).format('hh:mm:ss a'); + break; + } + } + } } \ No newline at end of file From 9c405c2b926377d296e4518cbb1973c76dec99f8 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 19 Jun 2023 16:30:08 -0400 Subject: [PATCH 46/76] v0.8.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e5ae23e..74ab28c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.18", + "version": "0.8.19", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 25ccd3f8a61d0ab310d2e29dc6996190aef9d9e7 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 01:41:58 -0400 Subject: [PATCH 47/76] service call fixes --- app/controllers/hive/user.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/hive/user.js b/app/controllers/hive/user.js index 4b7ab59..ec6e7a6 100644 --- a/app/controllers/hive/user.js +++ b/app/controllers/hive/user.js @@ -55,7 +55,7 @@ class HiveUserController extends SiteController { const { user: userService } = this.dtp.services; try { userId = mongoose.Types.ObjectId(userId); - res.locals.userProfile = await userService.getUserProfile(userId); + res.locals.userProfile = await userService.getLocalUserProfile(userId); if (!res.locals.userProfile) { throw new SiteError(404, 'User profile not found'); } @@ -80,7 +80,7 @@ class HiveUserController extends SiteController { res.locals.q = userService.filterUsername(req.query.q); res.locals.pagination = this.getPaginationParameters(req, 20); - res.locals.userProfiles = await userService.getUserAccounts(res.locals.pagination, res.locals.q); + res.locals.userProfiles = await userService.searchLocalUserAccounts(res.locals.pagination, res.locals.q); res.locals.userProfiles = res.locals.userProfiles.map((user) => { const apiUser = userService.filterUserObject(user); apiUser.picture.large = `/image/${user.picture.large}`; From 960a91287f60e00ae0ef063a9310f2e1a9764002 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 01:42:15 -0400 Subject: [PATCH 48/76] v0.8.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 74ab28c..186689b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.19", + "version": "0.8.20", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 50ac1ff8bbc38bdfa9d9014ea66382ebfed28c2b Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 01:43:39 -0400 Subject: [PATCH 49/76] v0.7.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b44c3b4..7a70e54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.8", + "version": "0.7.9", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 26df84d0c84b21c3d24d06a14f5724b90678331e Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 03:11:12 -0400 Subject: [PATCH 50/76] migrate to the use of dtp-logan-api - convert LoganService to use the API module - add logan worker to transmit Logan events from job queue - added logan worker config to supervisord directory - updated the other configs --- .env.default | 10 +++ .jshintrc | 2 +- app/services/logan.js | 92 ++++++++++++------------- app/workers/logan.js | 92 +++++++++++++++++++++++++ package.json | 1 + supervisord/dtp-base-host-services.conf | 4 +- supervisord/dtp-base-logan.conf | 13 ++++ supervisord/dtp-base-newsletter.conf | 4 +- supervisord/dtp-base-newsroom.conf | 4 +- supervisord/dtp-base.conf | 2 +- yarn.lock | 42 +++++++++++ 11 files changed, 211 insertions(+), 55 deletions(-) create mode 100644 app/workers/logan.js create mode 100644 supervisord/dtp-base-logan.conf diff --git a/.env.default b/.env.default index d789b37..2d47149 100644 --- a/.env.default +++ b/.env.default @@ -116,3 +116,13 @@ DTP_LOG_INFO=enabled DTP_LOG_WARN=enabled DTP_LOG_HTTP_FORMAT=combined + +# +# DTP Logan Integration +# + +DTP_LOGAN=disabled +DTP_LOGAN_API_KEY=########-####-####-####-############ +DTP_LOGAN_SCHEME=https +DTP_LOGAN_HOST=logan.digitaltelepresence.com +DTP_LOGAN_QUEUE_NAME=logan \ No newline at end of file diff --git a/.jshintrc b/.jshintrc index 6dd1a7e..c3942c1 100644 --- a/.jshintrc +++ b/.jshintrc @@ -10,7 +10,7 @@ "undef": true, "unused": true, "futurehostile": true, - "esversion": 9, + "esversion": 11, "mocha": true, "globals": { "markdown": true, diff --git a/app/services/logan.js b/app/services/logan.js index 8b22ef0..10243a0 100644 --- a/app/services/logan.js +++ b/app/services/logan.js @@ -4,9 +4,7 @@ 'use strict'; -const os = require('os'); - -const { SiteService, SiteError } = require('../../lib/site-lib'); +const { SiteService } = require('../../lib/site-lib'); class LoganService extends SiteService { @@ -16,56 +14,56 @@ class LoganService extends SiteService { async start ( ) { await super.start(); - } - - async sendRequestEvent (component, req, event) { - if (req.user) { - event.data = event.data || { }; - event.data.user = { - _id: req.user._id, - username: req.user.username, - }; - } - event.ip = req.ip; - return this.sendEvent(component, event); - } - - async sendEvent (component, event) { - try { - event.host = os.hostname(); - event['component.slug'] = component.slug; - event['component.name'] = component.className || component.name; - this.log[event.level]('application event', { event }); + const { LoganClient } = await import('dtp-logan-api'); - if (process.env.DTP_LOGAN !== 'enabled') { - return; - } + this.log.info('creating Logan client'); + this.logan = new LoganClient(); - const loganScheme = process.env.DTP_LOGAN_SCHEME || 'http'; - const loganUrl = `${loganScheme}://${process.env.DTP_LOGAN_HOST}/api/event`; - const payload = JSON.stringify(event); - - const response = await fetch(loganUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Content-Length': payload.length, - 'X-LogAn-Auth': process.env.DTP_LOGAN_API_KEY, + this.log.info('initializing Logan client'); + await this.logan.initialize({ + log: this.log, + api: { + enabled: process.env.DTP_LOGAN === 'enabled', + key: process.env.DTP_LOGAN_API_KEY, + scheme: process.env.DTP_LOGAN_SCHEME, + host: process.env.DTP_LOGAN_HOST, + }, + request: { + userField: 'user', + userIdField: '_id', + usernameField: 'username', + }, + flags: { + includeHostname: true, + includeClientIpAddress: true, + includeUser: true, + }, + queue: { + enabled: true, + name: process.env.DTP_LOGAN_QUEUE_NAME || 'logan', + redis: { + host: process.env.REDIS_HOST, + port: process.env.REDIS_PORT, + username: process.env.REDIS_USERNAME, // requires Redis >= 6 + password: process.env.REDIS_PASSWORD, + keyPrefix: process.env.REDIS_PREFIX, + }, + defaultJobOptions: { + attempts: 3, + removeOnComplete: true, + removeOnFail: true, }, - body: payload, - }); + }, + }); + } - const json = await response.json(); - if (!json.success) { - throw new SiteError(500, json.message); - } + async sendRequestEvent (component, req, event) { + return this.logan.sendRequestEvent(component, req, event); + } - return json; - } catch (error) { - this.log.error('failed to send LOGAN event', { event, error }); - // fall through - } + async sendEvent (component, event) { + return this.logan.sendEvent(component, event); } } diff --git a/app/workers/logan.js b/app/workers/logan.js new file mode 100644 index 0000000..79de615 --- /dev/null +++ b/app/workers/logan.js @@ -0,0 +1,92 @@ +'use strict'; + +require('dotenv').config(); + +const path = require('path'); + +const { + SiteLog, + SiteWorker, +} = require(path.join(__dirname, '..', '..', 'lib', 'site-lib')); + +module.rootPath = path.resolve(__dirname, '..', '..'); +module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); + +module.config = { + environment: process.env.NODE_ENV, + root: module.rootPath, + component: { name: 'LoganSiteWorker', slug: 'logan-site-worker' }, + site: require(path.join(module.rootPath, 'config', 'site')), +}; + +class LoganSiteWorker extends SiteWorker { + + constructor (dtp) { + super(dtp, dtp.config.component); + } + + async start ( ) { + await super.start(); + + const { LoganWorker } = await import('dtp-logan-api'); + + this.log.info('creating Logan worker'); + this.loganWorker = new LoganWorker(); + + this.log.info('initializing Logan worker'); + await this.loganWorker.initialize({ + api: { + enabled: process.env.DTP_LOGAN === 'enabled', + key: process.env.DTP_LOGAN_API_KEY, + scheme: process.env.DTP_LOGAN_SCHEME, + host: process.env.DTP_LOGAN_HOST, + }, + queue: { + enabled: true, + name: 'logan', + redis: { + host: process.env.REDIS_HOST, + port: process.env.REDIS_PORT, + username: process.env.REDIS_USERNAME, // requires Redis >= 6 + password: process.env.REDIS_PASSWORD, + keyPrefix: process.env.REDIS_PREFIX, + }, + defaultJobOptions: { + attempts: 3, + priority: 10, + removeOnComplete: true, + removeOnFail: true, + }, + }, + }); + } + + async stop ( ) { + if (this.loganWorker) { + await this.loganWorker.close(); + delete this.loganWorker; + } + await super.stop(); + } +} + +(async ( ) => { + + module.log = new SiteLog(module, module.config.component); + + if (!process.env.DTP_LOGAN_API_KEY) { + console.log('Must define DTP_LOGAN_API_KEY environment variable to run test'); + process.exit(-1); + } + + try { + module.worker = new LoganSiteWorker(module); + await module.worker.start(); + + module.log.info(`${module.pkg.name} v${module.pkg.version} ${module.config.component.name} started`); + } catch (error) { + module.log.error('failed to start worker', { component: module.config.component, error }); + process.exit(-1); + } + +})(); \ No newline at end of file diff --git a/package.json b/package.json index 186689b..aecb003 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "disposable-email-provider-domains": "^1.0.9", "dotenv": "^16.0.0", "dtp-jshint-reporter": "git+https://git.digitaltelepresence.com/digital-telepresence/dtp-jshint-reporter.git#master", + "dtp-logan-api": "^0.3.2", "ein-validator": "^1.0.1", "email-domain-check": "^1.1.4", "email-validator": "^2.0.4", diff --git a/supervisord/dtp-base-host-services.conf b/supervisord/dtp-base-host-services.conf index c4754cb..14d11f7 100644 --- a/supervisord/dtp-base-host-services.conf +++ b/supervisord/dtp-base-host-services.conf @@ -1,7 +1,7 @@ [program:dtp-base:host-services] numprocs=1 process_name=%(program_name)s_%(process_num)02d -command=/home/dtp/.nvm/versions/node/v16.13.0/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/host-services.js +command=/home/dtp/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/host-services.js directory=/home/dtp/live/dtp-base autostart=true autorestart=true @@ -10,4 +10,4 @@ stopsignal=INT stderr_logfile=/var/log/dtp-base/host-services.err.log stdout_logfile=/var/log/dtp-base/host-services.out.log user=dtp -environment=HOME='/home/dtp/live/dtp-base',HTTP_BIND_PORT=30%(process_num)02d,NODE_ENV=production,LOGNAME=host-services \ No newline at end of file +environment=HOME='/home/dtp/live/dtp-base',NODE_ENV=production,LOGNAME=host-services \ No newline at end of file diff --git a/supervisord/dtp-base-logan.conf b/supervisord/dtp-base-logan.conf new file mode 100644 index 0000000..3eae4cb --- /dev/null +++ b/supervisord/dtp-base-logan.conf @@ -0,0 +1,13 @@ +[program:dtp-base:logan] +numprocs=1 +process_name=%(program_name)s_%(process_num)02d +command=/home/dtp/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/logan.js +directory=/home/dtp/live/dtp-base +autostart=true +autorestart=true +startretries=3 +stopsignal=INT +stdout_logfile=/var/log/dtp-base/logan.out.log +stderr_logfile=/var/log/dtp-base/logan.err.log +user=dtp +environment=HOME='/home/dtp/live/dtp-base',NODE_ENV=production,LOGNAME=logan \ No newline at end of file diff --git a/supervisord/dtp-base-newsletter.conf b/supervisord/dtp-base-newsletter.conf index 7a710b8..f194a4a 100644 --- a/supervisord/dtp-base-newsletter.conf +++ b/supervisord/dtp-base-newsletter.conf @@ -1,7 +1,7 @@ [program:dtp-base:newsletter] numprocs=1 process_name=%(program_name)s_%(process_num)02d -command=/home/dtp/.nvm/versions/node/v16.13.0/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/newsletter.js +command=/home/dtp/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/newsletter.js directory=/home/dtp/live/dtp-base autostart=true autorestart=true @@ -10,4 +10,4 @@ stopsignal=INT stderr_logfile=/var/log/dtp-base/newsletter.err.log stdout_logfile=/var/log/dtp-base/newsletter.out.log user=dtp -environment=HOME='/home/dtp/live/dtp-base',HTTP_BIND_PORT=30%(process_num)02d,NODE_ENV=production,LOGNAME=newsletter \ No newline at end of file +environment=HOME='/home/dtp/live/dtp-base',NODE_ENV=production,LOGNAME=newsletter \ No newline at end of file diff --git a/supervisord/dtp-base-newsroom.conf b/supervisord/dtp-base-newsroom.conf index 50b4b8c..a41051e 100644 --- a/supervisord/dtp-base-newsroom.conf +++ b/supervisord/dtp-base-newsroom.conf @@ -1,7 +1,7 @@ [program:dtp-base:newsroom] numprocs=1 process_name=%(program_name)s_%(process_num)02d -command=/home/dtp/.nvm/versions/node/v16.13.0/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/newsroom.js +command=/home/dtp/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/newsroom.js directory=/home/dtp/live/dtp-base autostart=true autorestart=true @@ -10,4 +10,4 @@ stopsignal=INT stderr_logfile=/var/log/dtp-base/newsroom.err.log stdout_logfile=/var/log/dtp-base/newsroom.out.log user=dtp -environment=HOME='/home/dtp/live/dtp-base',HTTP_BIND_PORT=30%(process_num)02d,NODE_ENV=production,LOGNAME=newsroom \ No newline at end of file +environment=HOME='/home/dtp/live/dtp-base',NODE_ENV=production,LOGNAME=newsroom \ No newline at end of file diff --git a/supervisord/dtp-base.conf b/supervisord/dtp-base.conf index cea7c16..f834d38 100644 --- a/supervisord/dtp-base.conf +++ b/supervisord/dtp-base.conf @@ -1,7 +1,7 @@ [program:dtp-base] numprocs=1 process_name=%(program_name)s_%(process_num)02d -command=/home/dtp/.nvm/versions/node/v16.13.0/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 dtp-webapp.js +command=/home/dtp/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 dtp-webapp.js directory=/home/dtp/live/dtp-base autostart=true autorestart=true diff --git a/yarn.lock b/yarn.lock index dd5d577..2d05fad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2076,6 +2076,20 @@ builtin-modules@^3.1.0: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== +bull@^4.10.4: + version "4.10.4" + resolved "https://registry.yarnpkg.com/bull/-/bull-4.10.4.tgz#db39ee0c3bfbe3b76f1f35db800501de5bba4f84" + integrity sha512-o9m/7HjS/Or3vqRd59evBlWCXd9Lp+ALppKseoSKHaykK46SmRjAilX98PgmOz1yeVaurt8D5UtvEt4bUjM3eA== + dependencies: + cron-parser "^4.2.1" + debuglog "^1.0.0" + get-port "^5.1.1" + ioredis "^5.0.0" + lodash "^4.17.21" + msgpackr "^1.5.2" + semver "^7.3.2" + uuid "^8.3.0" + bull@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/bull/-/bull-4.7.0.tgz#89442d4676117edd9f9a1359bb0edfb489595e70" @@ -2940,6 +2954,11 @@ denque@^2.0.1: resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a" integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ== +denque@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -3106,6 +3125,14 @@ drange@^1.0.2: dependencies: chalk "^4.1.1" +dtp-logan-api@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/dtp-logan-api/-/dtp-logan-api-0.3.2.tgz#354c184ce9ea8a31c57bf0592278f5861fe672d2" + integrity sha512-7mORjmktZY0xpUNecXVLiHvRkBbJxQkjRom2QFzb+5NLQxml2u28cPegINNIlnFKjduXme7a+MQm0msuCmHYtA== + dependencies: + bull "^4.10.4" + ioredis "^5.3.2" + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -4627,6 +4654,21 @@ ioredis@^4.28.5: redis-parser "^3.0.0" standard-as-callback "^2.1.0" +ioredis@^5.0.0, ioredis@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7" + integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA== + dependencies: + "@ioredis/commands" "^1.1.1" + cluster-key-slot "^1.1.0" + debug "^4.3.4" + denque "^2.1.0" + lodash.defaults "^4.2.0" + lodash.isarguments "^3.1.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + ioredis@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.2.2.tgz#212467e04f6779b4e0e800cece7bb7d3d7b546d2" From 73843095f5c5b3cd16232c09d62e471bd6558dea Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 03:11:55 -0400 Subject: [PATCH 51/76] v0.8.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aecb003..1d82d5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.20", + "version": "0.8.21", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From 4f23371be5099141d8be949fcb49f1c3873ffc23 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 03:18:49 -0400 Subject: [PATCH 52/76] added Logan worker to start-local --- start-local | 2 ++ 1 file changed, 2 insertions(+) diff --git a/start-local b/start-local index 7a87f10..cce2711 100755 --- a/start-local +++ b/start-local @@ -9,6 +9,7 @@ export MINIO_ROOT_USER MINIO_ROOT_PASSWORD MINIO_CI_CD forever start --killSignal=SIGINT app/workers/host-services.js forever start --killSignal=SIGINT app/workers/reeeper.js +forever start --killSignal=SIGINT app/workers/logan.js forever start --killSignal=SIGINT app/workers/newsletter.js forever start --killSignal=SIGINT app/workers/newsroom.js @@ -24,5 +25,6 @@ forever stop app/workers/media.js forever stop app/workers/newsroom.js forever stop app/workers/newsletter.js +forever stop app/workers/logan.js forever stop app/workers/reeeper.js forever stop app/workers/host-services.js \ No newline at end of file From a8de1e15652f10e1c8c217bbb4c92b680ecd9c75 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 03:19:41 -0400 Subject: [PATCH 53/76] added Logan worker to start-/stop-production --- start-production | 1 + stop-production | 1 + 2 files changed, 2 insertions(+) diff --git a/start-production b/start-production index e876e83..78322ae 100755 --- a/start-production +++ b/start-production @@ -3,6 +3,7 @@ sudo supervisorctl start \ base-host-services:* \ base-reeeper:* \ + base-logan:* \ base-newsletter:* \ base-newsroom:* \ base-media:* \ diff --git a/stop-production b/stop-production index 12b4516..e7152e0 100755 --- a/stop-production +++ b/stop-production @@ -6,5 +6,6 @@ sudo supervisorctl stop \ base-media:* \ base-newsroom:* \ base-newsletter:* \ + base-logan:* \ base-reeeper:* \ base-host-services:* \ \ No newline at end of file From 3a37d94e5d98e38b0679b102b2b003c89c9d58d8 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 03:19:51 -0400 Subject: [PATCH 54/76] v0.8.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d82d5a..b1bd5ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.21", + "version": "0.8.22", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From c8df274a82898b8f9a7fa78ad5aad9b691dcb7e7 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 18:31:47 -0400 Subject: [PATCH 55/76] component management Finally standardizing on the DTP Component definition: { logId: 'my-service', index: 'myService', className: 'MyService', } And I'm not too far from using UUIDs in there, too, so I have one (1) standard way of referencing them. --- app/controllers/admin.js | 4 ++-- app/controllers/admin/announcement.js | 4 ++-- app/controllers/admin/attachment.js | 4 ++-- app/controllers/admin/content-report.js | 4 ++-- app/controllers/admin/core-node.js | 4 ++-- app/controllers/admin/core-user.js | 4 ++-- app/controllers/admin/host.js | 4 ++-- app/controllers/admin/image.js | 4 ++-- app/controllers/admin/job-queue.js | 4 ++-- app/controllers/admin/log.js | 6 ++--- app/controllers/admin/newsletter.js | 4 ++-- app/controllers/admin/newsroom.js | 4 ++-- app/controllers/admin/otp.js | 6 ++--- app/controllers/admin/service-node.js | 4 ++-- app/controllers/admin/settings.js | 4 ++-- app/controllers/admin/user.js | 4 ++-- app/controllers/announcement.js | 4 ++-- app/controllers/auth.js | 4 ++-- app/controllers/chat.js | 4 ++-- app/controllers/comment.js | 6 ++--- app/controllers/email.js | 4 ++-- app/controllers/form.js | 6 ++--- app/controllers/hive.js | 6 ++--- app/controllers/hive/kaleidoscope.js | 4 ++-- app/controllers/hive/user.js | 4 ++-- app/controllers/home.js | 7 +++--- app/controllers/image.js | 6 ++--- app/controllers/manifest.js | 8 +++---- app/controllers/newsletter.js | 8 +++---- app/controllers/newsroom.js | 6 ++--- app/controllers/notification.js | 4 ++-- app/controllers/user.js | 6 ++--- app/controllers/welcome.js | 8 +++---- app/models/log.js | 5 ++-- app/services/announcement.js | 4 ++-- app/services/attachment.js | 4 ++-- app/services/cache.js | 4 ++-- app/services/chat.js | 4 ++-- app/services/comment.js | 4 ++-- app/services/content-report.js | 4 ++-- app/services/content-vote.js | 4 ++-- app/services/core-node.js | 4 ++-- app/services/crypto.js | 4 ++-- app/services/csrf-token.js | 4 ++-- app/services/dashboard.js | 4 ++-- app/services/display-engine.js | 4 ++-- app/services/email.js | 4 ++-- app/services/feed.js | 4 ++-- app/services/hive.js | 4 ++-- app/services/host-cache.js | 4 ++-- app/services/image.js | 4 ++-- app/services/job-queue.js | 4 ++-- app/services/limiter.js | 4 ++-- app/services/log.js | 8 +++---- app/services/logan.js | 4 ++-- app/services/markdown.js | 4 ++-- app/services/media.js | 4 ++-- app/services/minio.js | 6 ++--- app/services/newsletter.js | 6 ++--- app/services/oauth2.js | 4 ++-- app/services/otp-auth.js | 6 ++--- app/services/phone.js | 4 ++-- app/services/resource.js | 6 ++--- app/services/session.js | 4 ++-- app/services/sms.js | 4 ++-- app/services/sticker.js | 4 ++-- app/services/user-notification.js | 4 ++-- app/services/user.js | 4 ++-- app/views/admin/log/index.pug | 2 +- app/workers/chat.js | 2 +- app/workers/chat/job/chat-room-clear.js | 5 ++-- app/workers/chat/job/chat-room-delete.js | 5 ++-- app/workers/host-services.js | 8 +++++-- app/workers/logan.js | 2 +- app/workers/media.js | 2 +- app/workers/media/job/attachment-delete.js | 5 ++-- app/workers/media/job/attachment-ingest.js | 7 +++--- app/workers/media/job/sticker-delete.js | 5 ++-- app/workers/media/job/sticker-ingest.js | 7 +++--- app/workers/media/job/webpage-screenshot.js | 5 ++-- app/workers/newsletter.js | 2 +- app/workers/newsletter/job/email-send.js | 5 ++-- app/workers/newsletter/job/transmit.js | 5 ++-- app/workers/newsroom.js | 2 +- app/workers/newsroom/cron/update-feeds.js | 5 ++-- app/workers/newsroom/job/update-feed.js | 5 ++-- app/workers/reeeper.js | 2 +- .../reeeper/cron/expire-announcements.js | 5 ++-- .../reeeper/cron/expire-crashed-hosts.js | 5 ++-- app/workers/reeeper/job/archive-user-local.js | 16 ++++++------- dtp-media-engine.js | 2 +- dtp-webapp-cli.js | 2 +- dtp-webapp.js | 6 ++++- lib/client/js/dtp-log.js | 4 ++-- lib/site-common.js | 9 ++++++-- lib/site-controller.js | 6 ++--- lib/site-ioserver.js | 5 +--- lib/site-log.js | 18 +++++++++++---- lib/site-platform.js | 23 +++++++++++-------- lib/site-worker.js | 2 +- 100 files changed, 267 insertions(+), 233 deletions(-) diff --git a/app/controllers/admin.js b/app/controllers/admin.js index 1397570..56ee142 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -109,8 +109,8 @@ class AdminController extends SiteController { } module.exports = { - slug: 'admin', - name: 'admin', + logId: 'admin', + index: 'admin', className: 'AdminController', create: async (dtp) => { return new AdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/announcement.js b/app/controllers/admin/announcement.js index 5edb1d3..a292d88 100644 --- a/app/controllers/admin/announcement.js +++ b/app/controllers/admin/announcement.js @@ -158,8 +158,8 @@ class AnnouncementAdminController extends SiteController { } module.exports = { - name: 'announcement', - slug: 'announcement', + logId: 'announcement', + index: 'announcement', className: 'AnnouncementAdminController', create: async (dtp) => { return new AnnouncementAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/attachment.js b/app/controllers/admin/attachment.js index a521f30..61f71db 100644 --- a/app/controllers/admin/attachment.js +++ b/app/controllers/admin/attachment.js @@ -130,8 +130,8 @@ class AttachmentAdminController extends SiteController { } module.exports = { - name: 'adminAttachment', - slug: 'adminAttachment', + logId: 'admin-attachment', + index: 'adminAttachment', className: 'AttachmentAdminController', create: async (dtp) => { return new AttachmentAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/content-report.js b/app/controllers/admin/content-report.js index e7d0f2f..23496e7 100644 --- a/app/controllers/admin/content-report.js +++ b/app/controllers/admin/content-report.js @@ -87,8 +87,8 @@ class ContentReportAdminController extends SiteController { } module.exports = { - name: 'adminContentReport', - slug: 'admin-content-report', + logId: 'admin-content-report', + index: 'adminContentReport', className: 'ContentReportAdminController', create: async (dtp) => { return new ContentReportAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/core-node.js b/app/controllers/admin/core-node.js index 345be1b..eac1bd5 100644 --- a/app/controllers/admin/core-node.js +++ b/app/controllers/admin/core-node.js @@ -159,8 +159,8 @@ class CoreNodeAdminController extends SiteController { } module.exports = { - name: 'adminCoreNode', - slug: 'admin-core-node', + logId: 'admin-core-node', + index: 'adminCoreNode', className: 'CoreNodeAdminController', create: async (dtp) => { return new CoreNodeAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/core-user.js b/app/controllers/admin/core-user.js index 28d0366..9ccbaa6 100644 --- a/app/controllers/admin/core-user.js +++ b/app/controllers/admin/core-user.js @@ -88,8 +88,8 @@ class CoreUserAdminController extends SiteController { } module.exports = { - name: 'adminCoreUser', - slug: 'admin-core-user', + logId: 'admin-core-user', + index: 'adminCoreUser', className: 'CoreUserAdminController', create: async (dtp) => { return new CoreUserAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/host.js b/app/controllers/admin/host.js index 979a6d5..0261666 100644 --- a/app/controllers/admin/host.js +++ b/app/controllers/admin/host.js @@ -116,8 +116,8 @@ class HostAdminController extends SiteController { } module.exports = { - name: 'adminHost', - slug: 'admin-host', + logId: 'admin-host', + index: 'adminHost', className: 'HostAdminController', create: async (dtp) => { return new HostAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/image.js b/app/controllers/admin/image.js index af3c2c0..1bf628b 100644 --- a/app/controllers/admin/image.js +++ b/app/controllers/admin/image.js @@ -114,8 +114,8 @@ class ImageAdminController extends SiteController { } module.exports = { - name: 'adminImage', - slug: 'adminImage', + logId: 'admin-image', + index: 'adminImage', className: 'ImageAdminController', create: async (dtp) => { return new ImageAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/job-queue.js b/app/controllers/admin/job-queue.js index 9f16c47..63d5a3a 100644 --- a/app/controllers/admin/job-queue.js +++ b/app/controllers/admin/job-queue.js @@ -119,8 +119,8 @@ class JobQueueAdminController extends SiteController { } module.exports = { - name: 'adminJobQueue', - slug: 'admin-job-queue', + logId: 'admin-job-queue', + index: 'adminJobQueue', className: 'JobQueueAdminController', create: async (dtp) => { return new JobQueueAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/log.js b/app/controllers/admin/log.js index a29a82e..48263f9 100644 --- a/app/controllers/admin/log.js +++ b/app/controllers/admin/log.js @@ -32,7 +32,7 @@ class LogAdminController extends SiteController { try { res.locals.query = req.query; - res.locals.components = await logService.getComponentSlugs(); + res.locals.components = await logService.getComponentIds(); res.locals.pagination = this.getPaginationParameters(req, 25); const search = { }; @@ -51,8 +51,8 @@ class LogAdminController extends SiteController { } module.exports = { - name: 'adminLog', - slug: 'admin-log', + logId: 'admin-log', + index: 'adminLog', className: 'LogAdminController', create: async (dtp) => { return new LogAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/newsletter.js b/app/controllers/admin/newsletter.js index a875661..201c095 100644 --- a/app/controllers/admin/newsletter.js +++ b/app/controllers/admin/newsletter.js @@ -167,8 +167,8 @@ class NewsletterAdminController extends SiteController { } module.exports = { - name: 'adminNewsletter', - slug: 'admin-newsletter', + logId: 'admin-newsletter', + index: 'adminNewsletter', className: 'NewsletterAdminController', create: async (dtp) => { return new NewsletterAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/newsroom.js b/app/controllers/admin/newsroom.js index d014460..5c0a943 100644 --- a/app/controllers/admin/newsroom.js +++ b/app/controllers/admin/newsroom.js @@ -158,8 +158,8 @@ class NewsroomAdminController extends SiteController { } module.exports = { - name: 'newsroomAdmin', - slug: 'newsroom-admin', + logId: 'newsroom-admin', + index: 'newsroomAdmin', className: 'NewsroomAdminController', create: async (dtp) => { return new NewsroomAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/otp.js b/app/controllers/admin/otp.js index 9bdbd15..8ac2232 100644 --- a/app/controllers/admin/otp.js +++ b/app/controllers/admin/otp.js @@ -16,7 +16,7 @@ class OtpAdminController extends SiteController { } async start ( ) { - // const upload = multer({ dest: `/tmp/${this.dtp.config.site.domainKey}/uploads/${module.exports.slug}` }); + // const upload = multer({ dest: `/tmp/${this.dtp.config.site.domainKey}/uploads/${this.component.logId}` }); const router = express.Router(); router.use(async (req, res, next) => { @@ -49,8 +49,8 @@ class OtpAdminController extends SiteController { } module.exports = { - name: 'adminOtp', - slug: 'admin-opt', + logId: 'admin-otp', + index: 'adminOtp', className: 'OtpAdminController', create: async (dtp) => { return new OtpAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/service-node.js b/app/controllers/admin/service-node.js index 5519b44..f1bf683 100644 --- a/app/controllers/admin/service-node.js +++ b/app/controllers/admin/service-node.js @@ -128,8 +128,8 @@ class ServiceNodeAdminController extends SiteController { } module.exports = { - name: 'adminServiceNode', - slug: 'admin-service-node', + logId: 'admin-service-node', + index: 'adminServiceNode', className: 'ServiceNodeAdminController', create: async (dtp) => { return new ServiceNodeAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/settings.js b/app/controllers/admin/settings.js index 57ea30f..bc9eac1 100644 --- a/app/controllers/admin/settings.js +++ b/app/controllers/admin/settings.js @@ -98,8 +98,8 @@ class SettingsAdminController extends SiteController { } module.exports = { - name: 'adminSettings', - slug: 'admin-settings', + logId: 'admin-settings', + index: 'adminSettings', className: 'SettingsAdminController', create: async (dtp) => { return new SettingsAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index e80949d..56efc81 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -338,8 +338,8 @@ class UserAdminController extends SiteController { } module.exports = { - name: 'adminUser', - slug: 'admin-user', + logId: 'admin-user', + index: 'adminUser', className: 'UserAdminController', create: async (dtp) => { return new UserAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/announcement.js b/app/controllers/announcement.js index c07ebbc..ff0f17f 100644 --- a/app/controllers/announcement.js +++ b/app/controllers/announcement.js @@ -76,8 +76,8 @@ class AnnouncementController extends SiteController { } module.exports = { - slug: 'announcement', - name: 'announcement', + logId: 'announcement', + index: 'announcement', className: 'AnnouncementController', create: async (dtp) => { return new AnnouncementController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/auth.js b/app/controllers/auth.js index 57e80d0..61429c6 100644 --- a/app/controllers/auth.js +++ b/app/controllers/auth.js @@ -339,8 +339,8 @@ class AuthController extends SiteController { } module.exports = { - slug: 'auth', - name: 'auth', + logId: 'auth', + index: 'auth', className: 'AuthController', create: async (dtp) => { return new AuthController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/chat.js b/app/controllers/chat.js index d3518b9..982b33a 100644 --- a/app/controllers/chat.js +++ b/app/controllers/chat.js @@ -648,8 +648,8 @@ class ChatController extends SiteController { } module.exports = { - slug: 'chat', - name: 'chat', + logId: 'chat', + index: 'chat', className: 'ChatController', create: async (dtp) => { return new ChatController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/comment.js b/app/controllers/comment.js index 17d8005..e87db14 100644 --- a/app/controllers/comment.js +++ b/app/controllers/comment.js @@ -25,7 +25,7 @@ class CommentController extends SiteController { dtp.app.use('/comment', router); router.use(async (req, res, next) => { - res.locals.currentView = module.exports.slug; + res.locals.currentView = module.exports.logId; return next(); }); @@ -151,8 +151,8 @@ class CommentController extends SiteController { } module.exports = { - slug: 'comment', - name: 'comment', + logId: 'comment', + index: 'comment', className: 'CommentController', create: async (dtp) => { return new CommentController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/email.js b/app/controllers/email.js index b70d6b1..45bb185 100644 --- a/app/controllers/email.js +++ b/app/controllers/email.js @@ -81,8 +81,8 @@ class EmailController extends SiteController { } module.exports = { - slug: 'email', - name: 'email', + logId: 'email', + index: 'email', className: 'EmailController', create: async (dtp) => { return new EmailController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/form.js b/app/controllers/form.js index f4b8c31..b44371a 100644 --- a/app/controllers/form.js +++ b/app/controllers/form.js @@ -41,7 +41,7 @@ class FormController extends SiteController { sessionService.authCheckMiddleware({ requireLogin: true }), chatService.middleware({ maxOwnedRooms: 25, maxJoinedRooms: 50 }), async (req, res, next) => { - res.locals.currentView = module.exports.slug; + res.locals.currentView = module.exports.logId; return next(); }, ); @@ -64,8 +64,8 @@ class FormController extends SiteController { } module.exports = { - slug: 'form', - name: 'form', + logId: 'form', + index: 'form', className: 'FormController', create: async (dtp) => { return new FormController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/hive.js b/app/controllers/hive.js index b02891e..2b7b7c1 100644 --- a/app/controllers/hive.js +++ b/app/controllers/hive.js @@ -47,7 +47,7 @@ class HiveController extends SiteController { res.locals.hiveView = 'home'; res.status(200).json({ pkg: { name: this.dtp.pkg.name, version: this.dtp.pkg.version }, - component: { name: this.component.name, slug: this.component.slug }, + component: this.component, host: this.dtp.pkg.name, description: this.dtp.pkg.description, version: this.dtp.pkg.version, @@ -57,8 +57,8 @@ class HiveController extends SiteController { } module.exports = { - slug: 'hive', - name: 'hive', + logId: 'hive', + index: 'hive', className: 'HiveController', create: async (dtp) => { return new HiveController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/hive/kaleidoscope.js b/app/controllers/hive/kaleidoscope.js index 3dcd8dd..5bc86f9 100644 --- a/app/controllers/hive/kaleidoscope.js +++ b/app/controllers/hive/kaleidoscope.js @@ -93,8 +93,8 @@ class HiveKaleidoscopeController extends SiteController { } module.exports = { - name: 'hiveKaleidoscope', - slug: 'hive-kaleidoscope', + logId: 'hive-kaleidoscope', + index: 'hiveKaleidoscope', className: 'HiveKaleidoscopeController', create: async (dtp) => { return new HiveKaleidoscopeController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/hive/user.js b/app/controllers/hive/user.js index ec6e7a6..b21dd19 100644 --- a/app/controllers/hive/user.js +++ b/app/controllers/hive/user.js @@ -149,8 +149,8 @@ class HiveUserController extends SiteController { } module.exports = { - name: 'hiveUser', - slug: 'hive-user', + logId: 'hive-user', + index: 'hiveUser', className: 'HiveUserController', create: async (dtp) => { return new HiveUserController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/home.js b/app/controllers/home.js index dee0497..8d032b5 100644 --- a/app/controllers/home.js +++ b/app/controllers/home.js @@ -93,9 +93,10 @@ class HomeController extends SiteController { } module.exports = { - isHome: true, - slug: 'home', - name: 'home', + logId: 'home', + index: 'home', className: 'HomeController', create: async (dtp) => { return new HomeController(dtp); }, + + isHome: true, }; \ No newline at end of file diff --git a/app/controllers/image.js b/app/controllers/image.js index c8bb9ce..4d2b703 100644 --- a/app/controllers/image.js +++ b/app/controllers/image.js @@ -135,8 +135,8 @@ class ImageController extends SiteController { } module.exports = { - slug: 'image', - name: 'image', + logId: 'image', + index: 'image', className: 'ImageController', create: async (dtp) => { return new ImageController(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/controllers/manifest.js b/app/controllers/manifest.js index d64b28d..a7a3880 100644 --- a/app/controllers/manifest.js +++ b/app/controllers/manifest.js @@ -22,7 +22,7 @@ class ManifestController extends SiteController { dtp.app.use('/manifest.json', router); router.use(async (req, res, next) => { - res.locals.currentView = this.component.slug; + res.locals.currentView = this.component.logId; return next(); }); @@ -64,8 +64,8 @@ class ManifestController extends SiteController { } module.exports = { - slug: 'manifest', - name: 'manifest', + logId: 'manifest', + index: 'manifest', className: 'ManifestController', create: async (dtp) => { return new ManifestController(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/controllers/newsletter.js b/app/controllers/newsletter.js index 112d5b9..c45f32e 100644 --- a/app/controllers/newsletter.js +++ b/app/controllers/newsletter.js @@ -24,7 +24,7 @@ class NewsletterController extends SiteController { dtp.app.use('/newsletter', router); router.use(async (req, res, next) => { - res.locals.currentView = module.exports.slug; + res.locals.currentView = module.exports.logId; return next(); }); @@ -92,8 +92,8 @@ class NewsletterController extends SiteController { } module.exports = { - slug: 'newsletter', - name: 'newsletter', + logId: 'newsletter', + index: 'newsletter', className: 'NewsletterController', create: async (dtp) => { return new NewsletterController(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/controllers/newsroom.js b/app/controllers/newsroom.js index d766809..a1b05dc 100644 --- a/app/controllers/newsroom.js +++ b/app/controllers/newsroom.js @@ -23,7 +23,7 @@ class NewsroomController extends SiteController { dtp.app.use('/newsroom', router); router.use(async (req, res, next) => { - res.locals.currentView = module.exports.slug; + res.locals.currentView = module.exports.logId; return next(); }); @@ -165,8 +165,8 @@ class NewsroomController extends SiteController { } module.exports = { - slug: 'newsroom', - name: 'newsroom', + logId: 'newsroom', + index: 'newsroom', className: 'NewsroomController', create: (dtp) => { return new NewsroomController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/notification.js b/app/controllers/notification.js index ae89916..3614c38 100644 --- a/app/controllers/notification.js +++ b/app/controllers/notification.js @@ -72,8 +72,8 @@ class NotificationController extends SiteController { } module.exports = { - slug: 'notification', - name: 'notification', + logId: 'notification', + index: 'notification', className: 'NotificationController', create: async (dtp) => { return new NotificationController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/user.js b/app/controllers/user.js index e6a9fea..cb450b4 100644 --- a/app/controllers/user.js +++ b/app/controllers/user.js @@ -644,8 +644,8 @@ class UserController extends SiteController { } module.exports = { - slug: 'user', - name: 'user', + logId: 'user', + index: 'user', className: 'UserController', create: async (dtp) => { return new UserController(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/controllers/welcome.js b/app/controllers/welcome.js index d2d7cec..4a9499e 100644 --- a/app/controllers/welcome.js +++ b/app/controllers/welcome.js @@ -9,7 +9,7 @@ const path = require('path'); const express = require('express'); const captcha = require('svg-captcha'); -const { SiteController/*, SiteError */ } = require('../../lib/site-lib'); +const { SiteController } = require('../../lib/site-lib'); class WelcomeController extends SiteController { @@ -120,8 +120,8 @@ class WelcomeController extends SiteController { } module.exports = { - slug: 'welcome', - name: 'welcome', + logId: 'welcome', + index: 'welcome', className: 'WelcomeController', create: async (dtp) => { return new WelcomeController(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/models/log.js b/app/models/log.js index b74d682..e7a77f2 100644 --- a/app/models/log.js +++ b/app/models/log.js @@ -21,8 +21,9 @@ const LOG_LEVEL_LIST = [ const LogSchema = new Schema({ created: { type: Date, default: Date.now, required: true, index: -1, expires: '7d' }, component: { - name: { type: String, required: true }, - slug: { type: String, required: true, index: 1 }, + logId: { type: String, required: true, index: 1 }, + index: { type: String, required: true }, + className: { type: String, required: true, index: 1 }, }, level: { type: String, enum: LOG_LEVEL_LIST, required: true, index: true }, message: { type: String }, diff --git a/app/services/announcement.js b/app/services/announcement.js index 5e7969e..aa7aee6 100644 --- a/app/services/announcement.js +++ b/app/services/announcement.js @@ -116,8 +116,8 @@ class AnnouncementService extends SiteService { } module.exports = { - slug: 'announcement', - name: 'announcement', + logId: 'announcement', + index: 'announcement', className: 'AnnouncementService', create: (dtp) => { return new AnnouncementService(dtp); }, }; \ No newline at end of file diff --git a/app/services/attachment.js b/app/services/attachment.js index e8369c5..a4c407c 100644 --- a/app/services/attachment.js +++ b/app/services/attachment.js @@ -211,8 +211,8 @@ class AttachmentService extends SiteService { } module.exports = { - slug: 'attachment', - name: 'attachment', + logId: 'attachment', + index: 'attachment', className: 'AttachmentService', create: (dtp) => { return new AttachmentService(dtp); }, }; \ No newline at end of file diff --git a/app/services/cache.js b/app/services/cache.js index 418752c..9827291 100644 --- a/app/services/cache.js +++ b/app/services/cache.js @@ -57,8 +57,8 @@ class CacheService extends SiteService { } module.exports = { - slug: 'cache', - name: 'cache', + logId: 'cache', + index: 'cache', className: 'CacheService', create: (dtp) => { return new CacheService(dtp); }, }; \ No newline at end of file diff --git a/app/services/chat.js b/app/services/chat.js index cc1da01..77a7e7e 100644 --- a/app/services/chat.js +++ b/app/services/chat.js @@ -862,8 +862,8 @@ class ChatService extends SiteService { } module.exports = { - slug: 'chat', - name: 'chat', + logId: 'chat', + index: 'chat', className: 'ChatService', create: (dtp) => { return new ChatService(dtp); }, }; \ No newline at end of file diff --git a/app/services/comment.js b/app/services/comment.js index 5bd3614..aff2c11 100644 --- a/app/services/comment.js +++ b/app/services/comment.js @@ -350,8 +350,8 @@ class CommentService extends SiteService { } module.exports = { - slug: 'comment', - name: 'comment', + logId: 'comment', + index: 'comment', className: 'CommentService', create: (dtp) => { return new CommentService(dtp); }, }; \ No newline at end of file diff --git a/app/services/content-report.js b/app/services/content-report.js index 3d2d8dc..e239a76 100644 --- a/app/services/content-report.js +++ b/app/services/content-report.js @@ -127,8 +127,8 @@ class ContentReportService extends SiteService { } module.exports = { - slug: 'content-report', - name: 'contentReport', + logId: 'content-report', + index: 'contentReport', className: 'ContentReportService', create: (dtp) => { return new ContentReportService(dtp); }, }; \ No newline at end of file diff --git a/app/services/content-vote.js b/app/services/content-vote.js index c2cdc04..bf65984 100644 --- a/app/services/content-vote.js +++ b/app/services/content-vote.js @@ -117,8 +117,8 @@ class ContentVoteService extends SiteService { } module.exports = { - slug: 'content-vote', - name: 'contentVote', + logId: 'content-vote', + index: 'contentVote', className: 'ContentVoteService', create: (dtp) => { return new ContentVoteService(dtp); }, }; \ No newline at end of file diff --git a/app/services/core-node.js b/app/services/core-node.js index a4b5776..a543eac 100644 --- a/app/services/core-node.js +++ b/app/services/core-node.js @@ -803,8 +803,8 @@ class CoreNodeService extends SiteService { } module.exports = { - slug: 'core-node', - name: 'coreNode', + logId: 'core-node', + index: 'coreNode', className: 'CoreNodeService', create: (dtp) => { return new CoreNodeService(dtp); }, }; \ No newline at end of file diff --git a/app/services/crypto.js b/app/services/crypto.js index d65f3bc..b95f001 100644 --- a/app/services/crypto.js +++ b/app/services/crypto.js @@ -58,8 +58,8 @@ class CryptoService extends SiteService { } module.exports = { - slug: 'crypto', - name: 'crypto', + logId: 'crypto', + index: 'crypto', className: 'CryptoService', create: (dtp) => { return new CryptoService(dtp); }, }; \ No newline at end of file diff --git a/app/services/csrf-token.js b/app/services/csrf-token.js index 764a50b..b253704 100644 --- a/app/services/csrf-token.js +++ b/app/services/csrf-token.js @@ -76,8 +76,8 @@ class CsrfTokenService extends SiteService { } module.exports = { - slug: 'csrf-token', - name: 'csrfToken', + logId: 'csrf-token', + index: 'csrfToken', className: 'CsrfTokenService', create: (dtp) => { return new CsrfTokenService(dtp); }, }; \ No newline at end of file diff --git a/app/services/dashboard.js b/app/services/dashboard.js index 738df0a..cdf4507 100644 --- a/app/services/dashboard.js +++ b/app/services/dashboard.js @@ -270,8 +270,8 @@ class DashboardService extends SiteService { } module.exports = { - slug: 'dashboard', - name: 'dashboard', + logId: 'dashboard', + index: 'dashboard', className: 'DashboardService', create: (dtp) => { return new DashboardService(dtp); }, }; \ No newline at end of file diff --git a/app/services/display-engine.js b/app/services/display-engine.js index 66ba9b4..17feb93 100644 --- a/app/services/display-engine.js +++ b/app/services/display-engine.js @@ -150,8 +150,8 @@ class DisplayEngineService extends SiteService { } module.exports = { - slug: 'display-engine', - name: 'displayEngine', + logId: 'display-engine', + index: 'displayEngine', className: 'DisplayEngineService', create: (dtp) => { return new DisplayEngineService(dtp); }, }; \ No newline at end of file diff --git a/app/services/email.js b/app/services/email.js index 19aef2f..3ca513a 100644 --- a/app/services/email.js +++ b/app/services/email.js @@ -171,8 +171,8 @@ class EmailService extends SiteService { } module.exports = { - slug: 'email', - name: 'email', + logId: 'email', + index: 'email', className: 'EmailService', create: (dtp) => { return new EmailService(dtp); }, }; \ No newline at end of file diff --git a/app/services/feed.js b/app/services/feed.js index 9123673..2ca64e9 100644 --- a/app/services/feed.js +++ b/app/services/feed.js @@ -176,8 +176,8 @@ class FeedService extends SiteService { } module.exports = { - slug: 'feed', - name: 'feed', + logId: 'feed', + index: 'feed', className: 'FeedService', create: (dtp) => { return new FeedService(dtp); }, }; \ No newline at end of file diff --git a/app/services/hive.js b/app/services/hive.js index 993899b..509f464 100644 --- a/app/services/hive.js +++ b/app/services/hive.js @@ -330,8 +330,8 @@ class HiveService extends SiteService { } module.exports = { - slug: 'hive', - name: 'hive', + logId: 'hive', + index: 'hive', className: 'HiveService', create: (dtp) => { return new HiveService(dtp); }, }; \ No newline at end of file diff --git a/app/services/host-cache.js b/app/services/host-cache.js index 08339f5..6b02438 100644 --- a/app/services/host-cache.js +++ b/app/services/host-cache.js @@ -97,8 +97,8 @@ class HostCacheService extends SiteService { } module.exports = { - slug: 'host-cache', - name: 'hostCache', + logId: 'host-cache', + index: 'hostCache', className: 'HostCacheService', create: (dtp) => { return new HostCacheService(dtp); }, }; \ No newline at end of file diff --git a/app/services/image.js b/app/services/image.js index f7f6068..1321f9f 100644 --- a/app/services/image.js +++ b/app/services/image.js @@ -320,8 +320,8 @@ class ImageService extends SiteService { } module.exports = { - slug: 'image', - name: 'image', + logId: 'image', + index: 'image', className: 'ImageService', create: (dtp) => { return new ImageService(dtp); }, }; \ No newline at end of file diff --git a/app/services/job-queue.js b/app/services/job-queue.js index b710bff..e825ba9 100644 --- a/app/services/job-queue.js +++ b/app/services/job-queue.js @@ -62,8 +62,8 @@ class JobQueueService extends SiteService { } module.exports = { - slug: 'job-queue', - name: 'jobQueue', + logId: 'job-queue', + index: 'jobQueue', className: 'JobQueueService', create: (dtp) => { return new JobQueueService(dtp); }, }; \ No newline at end of file diff --git a/app/services/limiter.js b/app/services/limiter.js index 8b79db8..6a88ed1 100644 --- a/app/services/limiter.js +++ b/app/services/limiter.js @@ -69,8 +69,8 @@ class LimiterService extends SiteService { } module.exports = { - slug: 'limiter', - name: 'limiter', + logId: 'limiter', + index: 'limiter', className: 'LimiterService', create: (dtp) => { return new LimiterService(dtp); }, }; \ No newline at end of file diff --git a/app/services/log.js b/app/services/log.js index e03c501..75286b6 100644 --- a/app/services/log.js +++ b/app/services/log.js @@ -26,8 +26,8 @@ class SystemLogService extends SiteService { return logs; } - async getComponentSlugs ( ) { - return await Log.distinct('component.slug'); + async getComponentIds ( ) { + return await Log.distinct('component.logId'); } async getTotalCount ( ) { @@ -38,8 +38,8 @@ class SystemLogService extends SiteService { } module.exports = { - slug: 'log', - name: 'log', + logId: 'log', + index: 'log', className: 'SystemLogService', create: (dtp) => { return new SystemLogService(dtp); }, }; \ No newline at end of file diff --git a/app/services/logan.js b/app/services/logan.js index 10243a0..338dad0 100644 --- a/app/services/logan.js +++ b/app/services/logan.js @@ -68,8 +68,8 @@ class LoganService extends SiteService { } module.exports = { - slug: 'logan', - name: 'logan', + logId: 'logan', + index: 'logan', className: 'LoganService', create: (dtp) => { return new LoganService(dtp); }, }; \ No newline at end of file diff --git a/app/services/markdown.js b/app/services/markdown.js index ee80cbf..d70f570 100644 --- a/app/services/markdown.js +++ b/app/services/markdown.js @@ -32,8 +32,8 @@ class MarkdownService extends SiteService { } module.exports = { - slug: 'markdown', - name: 'markdown', + logId: 'markdown', + index: 'markdown', className: 'MarkdownService', create: (dtp) => { return new MarkdownService(dtp); }, }; \ No newline at end of file diff --git a/app/services/media.js b/app/services/media.js index 24cd7e1..6306618 100644 --- a/app/services/media.js +++ b/app/services/media.js @@ -94,8 +94,8 @@ class MediaService extends SiteService { } module.exports = { - slug: 'media', - name: 'media', + logId: 'media', + index: 'media', className: 'MediaService', create: (dtp) => { return new MediaService(dtp); }, }; \ No newline at end of file diff --git a/app/services/minio.js b/app/services/minio.js index 60057ca..bbaf5e9 100644 --- a/app/services/minio.js +++ b/app/services/minio.js @@ -97,8 +97,8 @@ class MinioService extends SiteService { } module.exports = { - slug: 'minio', - name: 'minio', + logId: 'minio', + index: 'minio', className: 'MinioService', create: (dtp) => { return new MinioService(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/services/newsletter.js b/app/services/newsletter.js index 1010718..5c3647a 100644 --- a/app/services/newsletter.js +++ b/app/services/newsletter.js @@ -117,8 +117,8 @@ class NewsletterService extends SiteService { } module.exports = { - slug: 'newsletter', - name: 'newsletter', + logId: 'newsletter', + index: 'newsletter', className: 'NewsletterService', create: (dtp) => { return new NewsletterService(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/services/oauth2.js b/app/services/oauth2.js index ae68dde..b557df7 100644 --- a/app/services/oauth2.js +++ b/app/services/oauth2.js @@ -474,8 +474,8 @@ class OAuth2Service extends SiteService { } module.exports = { - slug: 'oauth2', - name: 'oauth2', + logId: 'oauth2', + index: 'oauth2', className: 'OAuth2Service', create: (dtp) => { return new OAuth2Service(dtp); }, }; \ No newline at end of file diff --git a/app/services/otp-auth.js b/app/services/otp-auth.js index 3369ceb..8afaff5 100644 --- a/app/services/otp-auth.js +++ b/app/services/otp-auth.js @@ -238,8 +238,8 @@ class OtpAuthService extends SiteService { } module.exports = { - slug: 'otp-auth', - name: 'otpAuth', + logId: 'otp-auth', + index: 'otpAuth', className: 'OtpAuthService', create: (dtp) => { return new OtpAuthService(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/services/phone.js b/app/services/phone.js index 923c1c1..c6b91bf 100644 --- a/app/services/phone.js +++ b/app/services/phone.js @@ -55,8 +55,8 @@ class PhoneService extends SiteService { } module.exports = { - slug: 'phone', - name: 'phone', + logId: 'phone', + index: 'phone', className: 'PhoneService', create: (dtp) => { return new PhoneService(dtp); }, }; \ No newline at end of file diff --git a/app/services/resource.js b/app/services/resource.js index 80ce1e0..95704c0 100644 --- a/app/services/resource.js +++ b/app/services/resource.js @@ -118,8 +118,8 @@ class ResourceService extends SiteService { } module.exports = { - slug: 'resource', - name: 'resource', + logId: 'resource', + index: 'resource', className: 'ResourceService', create: (dtp) => { return new ResourceService(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/services/session.js b/app/services/session.js index 747f6a8..18545f2 100644 --- a/app/services/session.js +++ b/app/services/session.js @@ -110,8 +110,8 @@ class SessionService extends SiteService { } module.exports = { - slug: 'session', - name: 'session', + logId: 'session', + index: 'session', className: 'SessionService', create: (dtp) => { return new SessionService(dtp); }, }; \ No newline at end of file diff --git a/app/services/sms.js b/app/services/sms.js index fa110e6..6a15fd1 100644 --- a/app/services/sms.js +++ b/app/services/sms.js @@ -47,8 +47,8 @@ class SmsService extends SiteService { } module.exports = { - slug: 'sms', - name: 'sms', + logId: 'sms', + index: 'sms', className: 'SmsService', create: (dtp) => { return new SmsService(dtp); }, }; \ No newline at end of file diff --git a/app/services/sticker.js b/app/services/sticker.js index 581bb58..713b105 100644 --- a/app/services/sticker.js +++ b/app/services/sticker.js @@ -208,8 +208,8 @@ class StickerService extends SiteService { } module.exports = { - slug: 'sticker', - name: 'sticker', + logId: 'sticker', + index: 'sticker', className: 'StickerService', create: (dtp) => { return new StickerService(dtp); }, }; \ No newline at end of file diff --git a/app/services/user-notification.js b/app/services/user-notification.js index 3b7c100..733dee7 100644 --- a/app/services/user-notification.js +++ b/app/services/user-notification.js @@ -135,8 +135,8 @@ class UserNotificationService extends SiteService { } module.exports = { - name: 'userNotification', - slug: 'user-notification', + logId: 'user-notification', + index: 'userNotification', className: 'UserNotificationService', create: (dtp) => { return new UserNotificationService(dtp); }, }; \ No newline at end of file diff --git a/app/services/user.js b/app/services/user.js index 28d3a6f..62b976b 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -972,8 +972,8 @@ class UserService extends SiteService { } module.exports = { - slug: 'user', - name: 'user', + logId: 'user', + index: 'user', className: 'UserService', create: (dtp) => { return new UserService(dtp); }, }; \ No newline at end of file diff --git a/app/views/admin/log/index.pug b/app/views/admin/log/index.pug index 9f11170..cb81254 100644 --- a/app/views/admin/log/index.pug +++ b/app/views/admin/log/index.pug @@ -37,7 +37,7 @@ block content tr td= moment(log.created).format('YYYY-MM-DD hh:mm:ss.SSS') td= log.level - td= log.component.slug + td= log.component.logId td div= log.message if log.metadata diff --git a/app/workers/chat.js b/app/workers/chat.js index 0b5a2e7..dba6236 100644 --- a/app/workers/chat.js +++ b/app/workers/chat.js @@ -17,7 +17,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { name: 'chatWorker', slug: 'chat-worker' }, + component: { logId: 'chat-worker', index: 'chatWorker', className: 'ChatWorker' }, }; module.config.site = require(path.join(module.rootPath, 'config', 'site')); diff --git a/app/workers/chat/job/chat-room-clear.js b/app/workers/chat/job/chat-room-clear.js index 922deaf..ec6e56e 100644 --- a/app/workers/chat/job/chat-room-clear.js +++ b/app/workers/chat/job/chat-room-clear.js @@ -16,8 +16,9 @@ class ChatRoomClearJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'charRoomClearJob', - slug: 'chat-room-clear-job', + logId: 'chat-room-clear-job', + index: 'charRoomClearJob', + className: 'ChatRoomClearJob', }; } diff --git a/app/workers/chat/job/chat-room-delete.js b/app/workers/chat/job/chat-room-delete.js index 77998a2..225761d 100644 --- a/app/workers/chat/job/chat-room-delete.js +++ b/app/workers/chat/job/chat-room-delete.js @@ -25,8 +25,9 @@ class ChatRoomDeleteJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'chatRoomProcessor', - slug: 'chat-room-processor', + logId: 'chat-room-processor', + index: 'chatRoomProcessor', + className: 'ChatRoomDeleteJob', }; } diff --git a/app/workers/host-services.js b/app/workers/host-services.js index 8b2f9ab..a7de97d 100644 --- a/app/workers/host-services.js +++ b/app/workers/host-services.js @@ -32,9 +32,9 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { name: 'hostServicesWorker', slug: 'host-services-worker' }, site: require(path.join(module.rootPath, 'config', 'site')), http: require(path.join(module.rootPath, 'config', 'http')), + component: { logId: 'host-services-worker', index: 'hostServicesWorker', className: 'HostServicesWorker' }, }; module.log = new SiteLog(module, module.config.component); @@ -238,7 +238,11 @@ class HostCacheTransaction { class TransactionManager { constructor (dtp) { this.dtp = dtp; - this.component = { name: 'Transaction Manager', slug: 'transaction-manager' }; + this.component = { + logId: 'transaction-manager', + index: 'transactionManager', + className: 'TransactionManager', + }; this.log = new SiteLog(dtp, this.component); this.transactions = { }; } diff --git a/app/workers/logan.js b/app/workers/logan.js index 79de615..5173da7 100644 --- a/app/workers/logan.js +++ b/app/workers/logan.js @@ -15,8 +15,8 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { name: 'LoganSiteWorker', slug: 'logan-site-worker' }, site: require(path.join(module.rootPath, 'config', 'site')), + component: { logId: 'logan-site-worker', index: 'LoganSiteWorker', className: 'LoganSiteWorker' }, }; class LoganSiteWorker extends SiteWorker { diff --git a/app/workers/media.js b/app/workers/media.js index 9906719..e9382d3 100644 --- a/app/workers/media.js +++ b/app/workers/media.js @@ -15,7 +15,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: path.resolve(__dirname, '..', '..'), - component: { name: 'mediaWorker', slug: 'media-worker' }, + component: { logId: 'media-worker', index: 'mediaWorker', className: 'MediaWorker' }, }; /** diff --git a/app/workers/media/job/attachment-delete.js b/app/workers/media/job/attachment-delete.js index 50e52e8..931355a 100644 --- a/app/workers/media/job/attachment-delete.js +++ b/app/workers/media/job/attachment-delete.js @@ -15,8 +15,9 @@ class AttachmentDeleteJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'attachmentDeleteJob', - slug: 'attachment-delete-job', + logId: 'attachment-delete-job', + index: 'attachmentDeleteJob', + className: 'AttachmentDeleteJob', }; } diff --git a/app/workers/media/job/attachment-ingest.js b/app/workers/media/job/attachment-ingest.js index 00d0aa6..ab77163 100644 --- a/app/workers/media/job/attachment-ingest.js +++ b/app/workers/media/job/attachment-ingest.js @@ -19,8 +19,9 @@ class AttachmentIngestJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'attachmentIngestJob', - slug: 'attachment-ingest-job', + logId: 'attachment-ingest-job', + index: 'attachmentIngestJob', + className: 'AttachmentIngestJob', }; } @@ -80,7 +81,7 @@ class AttachmentIngestJob extends SiteWorkerProcess { job.data.workPath = path.join( process.env.DTP_ATTACHMENT_WORK_PATH, - AttachmentIngestJob.COMPONENT.slug, + AttachmentIngestJob.COMPONENT.logId, attachment._id.toString(), ); diff --git a/app/workers/media/job/sticker-delete.js b/app/workers/media/job/sticker-delete.js index b4c642b..d9b5461 100644 --- a/app/workers/media/job/sticker-delete.js +++ b/app/workers/media/job/sticker-delete.js @@ -15,8 +15,9 @@ class StickerDeleteJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'stickerDeleteJob', - slug: 'sticker-delete-job', + logId: 'sticker-delete-job', + index: 'stickerDeleteJob', + className: 'StickerDeleteJob', }; } diff --git a/app/workers/media/job/sticker-ingest.js b/app/workers/media/job/sticker-ingest.js index 599f8c1..6ec4ddd 100644 --- a/app/workers/media/job/sticker-ingest.js +++ b/app/workers/media/job/sticker-ingest.js @@ -20,8 +20,9 @@ class StickerIngestJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'stickerIngestJob', - slug: 'sticker-ingest-job', + logId: 'sticker-ingest-job', + index: 'stickerIngestJob', + className: 'StickerIngestJob', }; } @@ -74,7 +75,7 @@ class StickerIngestJob extends SiteWorkerProcess { job.data.workPath = path.join( process.env.DTP_STICKER_WORK_PATH, - this.dtp.config.component.slug, + this.dtp.config.component.logId, job.data.sticker._id.toString(), ); diff --git a/app/workers/media/job/webpage-screenshot.js b/app/workers/media/job/webpage-screenshot.js index a4a0bcd..7c18cb0 100644 --- a/app/workers/media/job/webpage-screenshot.js +++ b/app/workers/media/job/webpage-screenshot.js @@ -17,8 +17,9 @@ class WebpageScreenshotJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'webpageScreenshotJob', - slug: 'webpage-screenshot-job', + logId: 'webpage-screenshot-job', + index: 'webpageScreenshotJob', + className: 'WebpageScreenshotJob', }; } diff --git a/app/workers/newsletter.js b/app/workers/newsletter.js index 25b201a..a004a22 100644 --- a/app/workers/newsletter.js +++ b/app/workers/newsletter.js @@ -11,8 +11,8 @@ const { SiteWorker, SiteLog } = require(path.join(__dirname, '..', '..', 'lib', module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { - component: { name: 'newsletterWorker', slug: 'newsletter-worker' }, root: path.resolve(__dirname, '..', '..'), + component: { logId: 'newsletter-worker', index: 'newsletterWorker', className: 'NewsletterWorker' }, }; class NewsletterWorker extends SiteWorker { diff --git a/app/workers/newsletter/job/email-send.js b/app/workers/newsletter/job/email-send.js index d3f4072..04d24d6 100644 --- a/app/workers/newsletter/job/email-send.js +++ b/app/workers/newsletter/job/email-send.js @@ -12,8 +12,9 @@ class NewsletterEmailSendJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'newsletterEmailSendJob', - slug: 'newsletter-email-send-job', + logId: 'newsletter-email-send-job', + index: 'newsletterEmailSendJob', + className: 'NewsletterEmailSendJob', }; } diff --git a/app/workers/newsletter/job/transmit.js b/app/workers/newsletter/job/transmit.js index 4990127..f4acc08 100644 --- a/app/workers/newsletter/job/transmit.js +++ b/app/workers/newsletter/job/transmit.js @@ -17,8 +17,9 @@ class NewsletterTransmitJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'newsletterTransmitJob', - slug: 'newsletter-transmit-job', + logId: 'newsletter-transmit-job', + index: 'newsletterTransmitJob', + className: 'NewsletterTransmitJob', }; } diff --git a/app/workers/newsroom.js b/app/workers/newsroom.js index 6ca4fdc..6fa69e2 100644 --- a/app/workers/newsroom.js +++ b/app/workers/newsroom.js @@ -23,7 +23,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { name: 'newsroom', slug: 'newsroom' }, + component: { logId: 'newsroom', index: 'newsroom', className: 'NewsroomWorker' }, }; module.config.site = require(path.join(module.rootPath, 'config', 'site')); diff --git a/app/workers/newsroom/cron/update-feeds.js b/app/workers/newsroom/cron/update-feeds.js index b4d6b5e..3cb03b3 100644 --- a/app/workers/newsroom/cron/update-feeds.js +++ b/app/workers/newsroom/cron/update-feeds.js @@ -17,8 +17,9 @@ class UpdateFeedsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'updateFeeds', - slug: 'update-feeds-cron', + logId: 'update-feeds-cron', + index: 'updateFeeds', + className: 'UpdateFeedsCron', }; } diff --git a/app/workers/newsroom/job/update-feed.js b/app/workers/newsroom/job/update-feed.js index 6c96106..4e0dcbb 100644 --- a/app/workers/newsroom/job/update-feed.js +++ b/app/workers/newsroom/job/update-feed.js @@ -12,8 +12,9 @@ class UpdateFeedJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'newsroomUpdateFeedJob', - slug: 'newsroom-update-feed-job', + logId: 'newsroom-update-feed-job', + index: 'newsroomUpdateFeedJob', + className: 'UpdateFeedJob', }; } diff --git a/app/workers/reeeper.js b/app/workers/reeeper.js index a3de7d7..18d6dfd 100644 --- a/app/workers/reeeper.js +++ b/app/workers/reeeper.js @@ -19,7 +19,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { name: 'reeeper', slug: 'reeeper' }, + component: { logId: 'reeeper', index: 'reeeper', className: 'ReeeperWorker' }, }; module.config.site = require(path.join(module.rootPath, 'config', 'site')); diff --git a/app/workers/reeeper/cron/expire-announcements.js b/app/workers/reeeper/cron/expire-announcements.js index 648dec2..144302a 100644 --- a/app/workers/reeeper/cron/expire-announcements.js +++ b/app/workers/reeeper/cron/expire-announcements.js @@ -29,8 +29,9 @@ class ExpiredAnnouncementsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'expiredAnnouncementsCron', - slug: 'expired-announcements-cron', + logId: 'expired-announcements-cron', + index: 'expiredAnnouncementsCron', + className: 'ExpiredAnnouncementsCron', }; } diff --git a/app/workers/reeeper/cron/expire-crashed-hosts.js b/app/workers/reeeper/cron/expire-crashed-hosts.js index 2662fb2..3edb617 100644 --- a/app/workers/reeeper/cron/expire-crashed-hosts.js +++ b/app/workers/reeeper/cron/expire-crashed-hosts.js @@ -28,8 +28,9 @@ class CrashedHostsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'crashedHostsCron', - slug: 'crashed-hosts-cron', + logId: 'crashed-hosts-cron', + index: 'crashedHostsCron', + className: 'CrashedHostsCron', }; } diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js index 85b7c85..073c8cc 100644 --- a/app/workers/reeeper/job/archive-user-local.js +++ b/app/workers/reeeper/job/archive-user-local.js @@ -30,14 +30,12 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - name: 'archiveUserLocalJob', - slug: 'archive-user-local-job', + logId: 'archive-user-local-job', + index: 'archiveUserLocalJob', + className: 'ArchiveUserLocalJob', }; } - static get JOB_NAME ( ) { return 'Local User Archive'; } - static get JOB_SLUG ( ) { return 'archive-user-local'; } - constructor (worker) { super(worker, ArchiveUserLocalJob.COMPONENT); this.jobs = new Set(); @@ -48,8 +46,8 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { this.queue = await this.getJobQueue('reeeper', this.dtp.config.jobQueues.reeeper); - this.log.info('registering job processor', { queue: this.queue.name, job: ArchiveUserLocalJob.JOB_SLUG }); - this.queue.process(ArchiveUserLocalJob.JOB_SLUG, 1, this.processArchiveUserLocal.bind(this)); + this.log.info('registering job processor', { queue: this.queue.name }); + this.queue.process('archive-user-local', 1, this.processArchiveUserLocal.bind(this)); } async stop ( ) { @@ -70,7 +68,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { async processArchiveUserLocal (job) { const { user: userService } = this.dtp.services; try { - job.data.archivePath = path.join('/tmp', this.dtp.pkg.name, ArchiveUserLocalJob.JOB_SLUG); + job.data.archivePath = path.join('/tmp', this.dtp.pkg.name, 'archive-user-local'); this.jobs.add(job); job.data.userId = mongoose.Types.ObjectId(job.data.userId); @@ -130,7 +128,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { delete job.data.workPath; } this.jobs.delete(job); - this.log.info('job complete', { job: job.id, name: ArchiveUserLocalJob.JOB_NAME }); + this.log.info('job complete', { job: job.id }); } } diff --git a/dtp-media-engine.js b/dtp-media-engine.js index 8e891ba..5df4e97 100644 --- a/dtp-media-engine.js +++ b/dtp-media-engine.js @@ -154,7 +154,7 @@ module.shutdown = async ( ) => { try { await SitePlatform.startPlatform(module); } catch (error) { - module.log.error(`failed to start DTP ${module.config.component.slug} process`, { error }); + module.log.error(`failed to start DTP ${module.config.component.className} process`, { error }); return; } diff --git a/dtp-webapp-cli.js b/dtp-webapp-cli.js index 99983a4..74ef621 100644 --- a/dtp-webapp-cli.js +++ b/dtp-webapp-cli.js @@ -225,7 +225,7 @@ module.requestCoreConnect = async (host) => { try { await SitePlatform.startPlatform(module); } catch (error) { - module.log.error(`failed to start DTP ${module.config.component.slug} platform`, { error }); + module.log.error(`failed to start DTP ${module.config.component.className} platform`, { error }); return; } diff --git a/dtp-webapp.js b/dtp-webapp.js index 3787943..8f64977 100644 --- a/dtp-webapp.js +++ b/dtp-webapp.js @@ -4,7 +4,11 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Sample App', slug: 'webapp' }; +const DTP_COMPONENT = { + logId: 'webapp', + index: 'webApp', + className: 'BaseSampleApp', +}; require('dotenv').config(); diff --git a/lib/client/js/dtp-log.js b/lib/client/js/dtp-log.js index 1746cc6..17dc94d 100644 --- a/lib/client/js/dtp-log.js +++ b/lib/client/js/dtp-log.js @@ -113,13 +113,13 @@ export default class DtpWebLog { if (!this.enabled) { return; } if (data) { console[method]('%c%s%c: %s', - css.label, `${this.component.slug}.${event}`, + css.label, `${this.component.logId}.${event}`, css.message, msg, data, ); } else { console[method]('%c%s%c: %s', - css.label, `${this.component.slug}.${event}`, + css.label, `${this.component.logId}.${event}`, css.message, msg, ); } diff --git a/lib/site-common.js b/lib/site-common.js index 3732ce3..864df63 100644 --- a/lib/site-common.js +++ b/lib/site-common.js @@ -37,7 +37,12 @@ class SiteCommon extends EventEmitter2 { this.options = options; this.dtp = dtp; - this.component = component; + + this.component = { + logId: component.logId, + index: component.index, + className: component.className, + }; this.log = new SiteLog(dtp, component); this.appTemplateRoot = path.join(this.dtp.config.root, 'app', 'templates'); @@ -62,7 +67,7 @@ class SiteCommon extends EventEmitter2 { } getEventName (name) { - return `dtp.${this.component.slug}.${name}`; + return `dtp.${this.component.logId}.${name}`; } async emitDtpEvent (name, params) { diff --git a/lib/site-controller.js b/lib/site-controller.js index 217792f..bf3a866 100644 --- a/lib/site-controller.js +++ b/lib/site-controller.js @@ -39,12 +39,12 @@ class SiteController extends SiteCommon { createMulter (slug, options) { if (!!slug && (typeof slug === 'object')) { options = slug; - slug = this.component.slug; + slug = this.component.logId; } else { - slug = slug || this.component.slug; + slug = slug || this.component.logId; } options = Object.assign({ - dest: `/tmp/${this.dtp.config.site.domainKey}/${slug}/${this.component.slug}` + dest: `/tmp/${this.dtp.config.site.domainKey}/${slug}`, }, options || { }); return multer(options); diff --git a/lib/site-ioserver.js b/lib/site-ioserver.js index bfcbae1..7774b81 100644 --- a/lib/site-ioserver.js +++ b/lib/site-ioserver.js @@ -4,7 +4,6 @@ 'use strict'; -const DTP_COMPONENT = { name: 'I/O Server', slug: 'ioserver', prefix: 'srv' }; const path = require('path'); const Redis = require('ioredis'); @@ -14,15 +13,13 @@ const ConnectToken = mongoose.model('ConnectToken'); const marked = require('marked'); -const { SiteLog } = require(path.join(__dirname, 'site-log')); const { SiteCommon } = require(path.join(__dirname, 'site-common')); class SiteIoServer extends SiteCommon { constructor (dtp) { - super(dtp, { name: 'ioServer', slug: 'io-server' }); + super(dtp, { logId: 'io-server', index: 'ioServer', className: 'SiteIoServer' }); this.dtp = dtp; - this.log = new SiteLog(dtp, DTP_COMPONENT); } async start (httpServer) { diff --git a/lib/site-log.js b/lib/site-log.js index 89810f9..649e3ed 100644 --- a/lib/site-log.js +++ b/lib/site-log.js @@ -37,7 +37,10 @@ class SiteLog { } this.dtp = dtp; - if (!component || !component.slug || !component.name) { + if (!component || + !component.logId || + !component.index || + !component.className) { throw new Error('Must specify DTP component'); } this.component = component; @@ -83,7 +86,7 @@ class SiteLog { async writeLog (level, message, metadata) { const NOW = new Date(); const ctimestamp = color.black(moment(NOW).format('YYYY-MM-DD HH:mm:ss.SSS')); - const ccomponentSlug = color.cyan(this.component.slug); + const ccomponentSlug = color.cyan(this.component.logId); const cmessage = color.darkGray(message); let clevel = level.padEnd(5); @@ -121,8 +124,13 @@ class SiteLog { if (LogModel && (process.env.DTP_LOG_MONGODB === 'enabled')) { try { - const component = { name: this.component.name, slug: this.component.slug }; - await LogModel.create({ created: NOW, level, component, message, metadata }); + await LogModel.create({ + created: NOW, + component: this.component, + level, + message, + metadata, + }); } catch (error) { console.log( 'failed to write log entry to MongoDB', @@ -135,7 +143,7 @@ class SiteLog { if (LogStream && (process.env.DTP_LOG_FILE === 'enabled')) { const logEntry = { - t: NOW, c: this.component.slug, l: level, m: message, d: metadata, + t: NOW, c: this.component.logId, l: level, m: message, d: metadata, }; LogStream.write(`${JSON.stringify(logEntry)}\n`); } diff --git a/lib/site-platform.js b/lib/site-platform.js index 07a9073..c8ccce9 100644 --- a/lib/site-platform.js +++ b/lib/site-platform.js @@ -123,14 +123,13 @@ module.getRedisKeys = (pattern) => { }; module.loadServices = async (dtp) => { - dtp.services = module.services = { }; + dtp.services = { }; const scripts = glob.sync(path.join(dtp.config.root, 'app', 'services', '*.js')); const inits = [ ]; await SiteAsync.each(scripts, async (script) => { const service = await require(script); - module.services[service.name] = service.create(dtp); - module.services[service.name].__dtp_service_name = service.name; - inits.push(module.services[service.name]); + dtp.services[service.index] = service.create(dtp); + inits.push(dtp.services[service.index]); }); await SiteAsync.each(inits, async (service) => { await service.start(); @@ -146,8 +145,12 @@ module.loadControllers = async (dtp) => { await SiteAsync.each(scripts, async (script) => { const controller = await require(script); controller.instance = await controller.create(dtp); - module.log.info('controller loaded', { name: controller.name, slug: controller.slug }); - dtp.controllers[controller.name] = controller; + module.log.info('controller loaded', { + logId: controller.logId, + index: controller.index, + className: controller.className, + }); + dtp.controllers[controller.index] = controller; inits.push(controller); }); @@ -342,9 +345,9 @@ module.exports.startWebServer = async (dtp) => { module.app.use(passport.initialize()); module.app.use(passport.session()); - module.services.oauth2.registerPassport(); - module.app.use(module.services.session.middleware()); - module.app.use(module.services.userNotification.middleware({ withNotifications: false })); + dtp.services.oauth2.registerPassport(); + module.app.use(dtp.services.session.middleware()); + module.app.use(dtp.services.userNotification.middleware({ withNotifications: false })); /* * Application logic middleware @@ -421,7 +424,7 @@ module.exports.startWebServer = async (dtp) => { await module.startHttpServer(dtp, module.https, dtp.config.https); } - module.log.info(`${dtp.config.component.name} platform online`, { + module.log.info(`${dtp.config.component.className} platform online`, { http: dtp.config.http.port, https: dtp.config.https.port, }); diff --git a/lib/site-worker.js b/lib/site-worker.js index 3ad0cce..5f7e88f 100644 --- a/lib/site-worker.js +++ b/lib/site-worker.js @@ -70,7 +70,7 @@ class SiteWorker extends SiteCommon { const processor = new ProcessorClass(this); const { COMPONENT } = ProcessorClass; - this.log.info('loading worker processor', { component: COMPONENT.name }); + this.log.info('loading worker processor', { component: COMPONENT.logId }); this.processors[COMPONENT.name] = processor; return processor; From e4b896e993e379419e97a41c016f50b2fb79fb16 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 18:57:37 -0400 Subject: [PATCH 56/76] update component definition --- dtp-webapp-cli.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dtp-webapp-cli.js b/dtp-webapp-cli.js index 74ef621..34a6377 100644 --- a/dtp-webapp-cli.js +++ b/dtp-webapp-cli.js @@ -4,8 +4,6 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Sample App CLI', slug: 'webapp-cli' }; - require('dotenv').config(); const path = require('path'); @@ -22,10 +20,10 @@ const { module.rootPath = __dirname; module.pkg = require(path.join(module.rootPath, 'package.json')); module.config = { - component: DTP_COMPONENT, root: module.rootPath, site: require(path.join(module.rootPath, 'config', 'site')), http: require(path.join(module.rootPath, 'config', 'http')), + component: { logId: 'webapp-cli', index: 'webappCli', className: 'SampleAppCli' }, }; module.log = new SiteLog(module, module.config.component); From c49160d51764eb680220c0e4b6e6355457752047 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 19:01:19 -0400 Subject: [PATCH 57/76] rename SitePlatform.startPlatform to SitePlatform.start --- app/workers/media.js | 2 +- dtp-media-engine.js | 2 +- dtp-webapp-cli.js | 2 +- dtp-webapp.js | 2 +- lib/site-platform.js | 2 +- lib/site-worker.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/workers/media.js b/app/workers/media.js index e9382d3..06e12e6 100644 --- a/app/workers/media.js +++ b/app/workers/media.js @@ -71,7 +71,7 @@ class MediaWorker extends SiteWorker { (async ( ) => { try { module.log = new SiteLog(module, module.config.component); - await SitePlatform.startPlatform(module, module.config.component); + await SitePlatform.start(module, module.config.component); module.worker = new MediaWorker(module); await module.worker.start(); diff --git a/dtp-media-engine.js b/dtp-media-engine.js index 5df4e97..4b0bad8 100644 --- a/dtp-media-engine.js +++ b/dtp-media-engine.js @@ -152,7 +152,7 @@ module.shutdown = async ( ) => { }); try { - await SitePlatform.startPlatform(module); + await SitePlatform.start(module); } catch (error) { module.log.error(`failed to start DTP ${module.config.component.className} process`, { error }); return; diff --git a/dtp-webapp-cli.js b/dtp-webapp-cli.js index 34a6377..92215b5 100644 --- a/dtp-webapp-cli.js +++ b/dtp-webapp-cli.js @@ -221,7 +221,7 @@ module.requestCoreConnect = async (host) => { ]); try { - await SitePlatform.startPlatform(module); + await SitePlatform.start(module); } catch (error) { module.log.error(`failed to start DTP ${module.config.component.className} platform`, { error }); return; diff --git a/dtp-webapp.js b/dtp-webapp.js index 8f64977..e6ddb70 100644 --- a/dtp-webapp.js +++ b/dtp-webapp.js @@ -67,7 +67,7 @@ module.shutdown = async ( ) => { }); try { - await SitePlatform.startPlatform(module); + await SitePlatform.start(module); await SitePlatform.startWebServer(module); } catch (error) { module.log.error(`failed to start DTP ${module.config.component.name}`, { error }); diff --git a/lib/site-platform.js b/lib/site-platform.js index c8ccce9..aeaf55e 100644 --- a/lib/site-platform.js +++ b/lib/site-platform.js @@ -183,7 +183,7 @@ module.loadControllers = async (dtp) => { }); }; -module.exports.startPlatform = async (dtp) => { +module.exports.start = async (dtp) => { try { module.log = new SiteLog(module, dtp.config.component); diff --git a/lib/site-worker.js b/lib/site-worker.js index 5f7e88f..30a3b88 100644 --- a/lib/site-worker.js +++ b/lib/site-worker.js @@ -48,7 +48,7 @@ class SiteWorker extends SiteCommon { /* * Site Platform startup */ - await SitePlatform.startPlatform(this.dtp); + await SitePlatform.start(this.dtp); } catch (error) { this.log.error('failed to start worker', { component: this.dtp.config.component, From 5a3313ad03798b13b77d021f2fb56dafd7c6d013 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Jun 2023 19:13:27 -0400 Subject: [PATCH 58/76] start ioserver on HTTP and HTTPS servers (both) --- lib/site-platform.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/site-platform.js b/lib/site-platform.js index aeaf55e..1848f45 100644 --- a/lib/site-platform.js +++ b/lib/site-platform.js @@ -414,13 +414,12 @@ module.exports.startWebServer = async (dtp) => { await module.createHttpsServer(dtp, module.app); } - // prefer to attach Socket.io to the HTTPS server and fall back to HTTP - await module.createSocketServer(dtp, module.https || module.http); - if (module.http) { + await module.createSocketServer(dtp, module.http); await module.startHttpServer(dtp, module.http, dtp.config.http); } if (module.https) { + await module.createSocketServer(dtp, module.https); await module.startHttpServer(dtp, module.https, dtp.config.https); } From c1e69d165b223a949eec66339f52aff4658d7479 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 04:07:18 -0400 Subject: [PATCH 59/76] component definition update --- app/workers/host-services.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/host-services.js b/app/workers/host-services.js index a7de97d..664386b 100644 --- a/app/workers/host-services.js +++ b/app/workers/host-services.js @@ -125,7 +125,7 @@ class HostCacheTransaction { constructor (dtp, message, rinfo) { this.dtp = dtp; this.created = Date.now(); // timestamp, not Date instance - this.component = { name: 'Host Cache Transaction', slug: 'host-cache-transaction' }; + this.component = { logId: 'host-cache-transaction', index: 'hostCacheTransaction', className: 'HostCacheTransaction' }; this.log = new SiteLog(dtp, this.component); this.message = message; From d78bbb3180c911965fab738df5190a33f5738200 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 05:45:57 -0400 Subject: [PATCH 60/76] more component definition updates --- app/controllers/admin.js | 2 +- app/controllers/admin/announcement.js | 2 +- app/controllers/admin/attachment.js | 2 +- app/controllers/admin/content-report.js | 2 +- app/controllers/admin/core-node.js | 2 +- app/controllers/admin/core-user.js | 2 +- app/controllers/admin/host.js | 2 +- app/controllers/admin/image.js | 2 +- app/controllers/admin/job-queue.js | 2 +- app/controllers/admin/log.js | 4 +- app/controllers/admin/newsletter.js | 2 +- app/controllers/admin/newsroom.js | 4 +- app/controllers/admin/otp.js | 2 +- app/controllers/admin/service-node.js | 2 +- app/controllers/admin/settings.js | 2 +- app/controllers/admin/user.js | 2 +- app/controllers/announcement.js | 2 +- app/controllers/auth.js | 2 +- app/controllers/chat.js | 2 +- app/controllers/comment.js | 2 +- app/controllers/email.js | 2 +- app/controllers/form.js | 2 +- app/controllers/hive.js | 2 +- app/controllers/hive/kaleidoscope.js | 2 +- app/controllers/hive/user.js | 2 +- app/controllers/home.js | 2 +- app/controllers/image.js | 2 +- app/controllers/manifest.js | 2 +- app/controllers/newsletter.js | 2 +- app/controllers/newsroom.js | 2 +- app/controllers/notification.js | 2 +- app/controllers/user.js | 2 +- app/controllers/welcome.js | 2 +- app/services/announcement.js | 2 +- app/services/attachment.js | 2 +- app/services/cache.js | 2 +- app/services/chat.js | 2 +- app/services/comment.js | 2 +- app/services/content-report.js | 2 +- app/services/content-vote.js | 2 +- app/services/core-node.js | 2 +- app/services/crypto.js | 2 +- app/services/csrf-token.js | 2 +- app/services/dashboard.js | 2 +- app/services/display-engine.js | 2 +- app/services/email.js | 2 +- app/services/feed.js | 2 +- app/services/hive.js | 2 +- app/services/host-cache.js | 2 +- app/services/image.js | 2 +- app/services/job-queue.js | 2 +- app/services/limiter.js | 2 +- app/services/log.js | 2 +- app/services/logan.js | 2 +- app/services/markdown.js | 2 +- app/services/media.js | 2 +- app/services/minio.js | 2 +- app/services/newsletter.js | 2 +- app/services/oauth2.js | 2 +- app/services/otp-auth.js | 2 +- app/services/phone.js | 2 +- app/services/resource.js | 2 +- app/services/session.js | 2 +- app/services/sms.js | 2 +- app/services/sticker.js | 44 ++++++++++++++----- app/services/user-notification.js | 2 +- app/services/user.js | 2 +- app/workers/chat.js | 2 +- app/workers/chat/job/chat-room-clear.js | 2 +- app/workers/chat/job/chat-room-delete.js | 10 +---- app/workers/host-services.js | 2 +- app/workers/logan.js | 2 +- app/workers/media.js | 2 +- app/workers/media/job/attachment-delete.js | 2 +- app/workers/media/job/attachment-ingest.js | 2 +- app/workers/media/job/sticker-delete.js | 2 +- app/workers/media/job/sticker-ingest.js | 2 +- app/workers/media/job/webpage-screenshot.js | 2 +- app/workers/newsletter.js | 2 +- app/workers/newsletter/job/email-send.js | 2 +- app/workers/newsletter/job/transmit.js | 2 +- app/workers/newsroom.js | 2 +- app/workers/newsroom/cron/update-feeds.js | 2 +- app/workers/newsroom/job/update-feed.js | 2 +- app/workers/reeeper.js | 2 +- .../reeeper/cron/expire-announcements.js | 2 +- .../reeeper/cron/expire-crashed-hosts.js | 2 +- app/workers/reeeper/job/archive-user-local.js | 2 +- client/js/index-admin.js | 6 +-- client/js/index.js | 3 +- client/js/site-admin-app.js | 6 +-- client/js/site-app.js | 2 +- client/js/site-chat.js | 2 +- client/js/site-comments.js | 2 +- client/js/site-reactions.js | 2 +- docs/samples/controller.js | 13 ++++-- docs/samples/service.js | 3 +- docs/samples/worker.js | 2 +- docs/services.md | 5 ++- dtp-media-engine.js | 4 +- lib/client/js/dtp-display-engine.js | 6 +-- lib/client/js/dtp-socket.js | 6 +-- lib/site-worker-process.js | 2 +- update-deps.js | 2 +- 104 files changed, 160 insertions(+), 136 deletions(-) diff --git a/app/controllers/admin.js b/app/controllers/admin.js index 56ee142..3ed5939 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -109,7 +109,7 @@ class AdminController extends SiteController { } module.exports = { - logId: 'admin', + logId: 'ctl:admin', index: 'admin', className: 'AdminController', create: async (dtp) => { return new AdminController(dtp); }, diff --git a/app/controllers/admin/announcement.js b/app/controllers/admin/announcement.js index a292d88..3c0c1d6 100644 --- a/app/controllers/admin/announcement.js +++ b/app/controllers/admin/announcement.js @@ -158,7 +158,7 @@ class AnnouncementAdminController extends SiteController { } module.exports = { - logId: 'announcement', + logId: 'admin:announcement', index: 'announcement', className: 'AnnouncementAdminController', create: async (dtp) => { return new AnnouncementAdminController(dtp); }, diff --git a/app/controllers/admin/attachment.js b/app/controllers/admin/attachment.js index 61f71db..8268f37 100644 --- a/app/controllers/admin/attachment.js +++ b/app/controllers/admin/attachment.js @@ -130,7 +130,7 @@ class AttachmentAdminController extends SiteController { } module.exports = { - logId: 'admin-attachment', + logId: 'admin:admin-attachment', index: 'adminAttachment', className: 'AttachmentAdminController', create: async (dtp) => { return new AttachmentAdminController(dtp); }, diff --git a/app/controllers/admin/content-report.js b/app/controllers/admin/content-report.js index 23496e7..9205988 100644 --- a/app/controllers/admin/content-report.js +++ b/app/controllers/admin/content-report.js @@ -87,7 +87,7 @@ class ContentReportAdminController extends SiteController { } module.exports = { - logId: 'admin-content-report', + logId: 'admin:content-report', index: 'adminContentReport', className: 'ContentReportAdminController', create: async (dtp) => { return new ContentReportAdminController(dtp); }, diff --git a/app/controllers/admin/core-node.js b/app/controllers/admin/core-node.js index eac1bd5..519ed63 100644 --- a/app/controllers/admin/core-node.js +++ b/app/controllers/admin/core-node.js @@ -159,7 +159,7 @@ class CoreNodeAdminController extends SiteController { } module.exports = { - logId: 'admin-core-node', + logId: 'admin:core-node', index: 'adminCoreNode', className: 'CoreNodeAdminController', create: async (dtp) => { return new CoreNodeAdminController(dtp); }, diff --git a/app/controllers/admin/core-user.js b/app/controllers/admin/core-user.js index 9ccbaa6..51b131d 100644 --- a/app/controllers/admin/core-user.js +++ b/app/controllers/admin/core-user.js @@ -88,7 +88,7 @@ class CoreUserAdminController extends SiteController { } module.exports = { - logId: 'admin-core-user', + logId: 'admin:core-user', index: 'adminCoreUser', className: 'CoreUserAdminController', create: async (dtp) => { return new CoreUserAdminController(dtp); }, diff --git a/app/controllers/admin/host.js b/app/controllers/admin/host.js index 0261666..01638ee 100644 --- a/app/controllers/admin/host.js +++ b/app/controllers/admin/host.js @@ -116,7 +116,7 @@ class HostAdminController extends SiteController { } module.exports = { - logId: 'admin-host', + logId: 'admin:host', index: 'adminHost', className: 'HostAdminController', create: async (dtp) => { return new HostAdminController(dtp); }, diff --git a/app/controllers/admin/image.js b/app/controllers/admin/image.js index 1bf628b..4420c1a 100644 --- a/app/controllers/admin/image.js +++ b/app/controllers/admin/image.js @@ -114,7 +114,7 @@ class ImageAdminController extends SiteController { } module.exports = { - logId: 'admin-image', + logId: 'admin:image', index: 'adminImage', className: 'ImageAdminController', create: async (dtp) => { return new ImageAdminController(dtp); }, diff --git a/app/controllers/admin/job-queue.js b/app/controllers/admin/job-queue.js index 63d5a3a..eeba454 100644 --- a/app/controllers/admin/job-queue.js +++ b/app/controllers/admin/job-queue.js @@ -119,7 +119,7 @@ class JobQueueAdminController extends SiteController { } module.exports = { - logId: 'admin-job-queue', + logId: 'admin:job-queue', index: 'adminJobQueue', className: 'JobQueueAdminController', create: async (dtp) => { return new JobQueueAdminController(dtp); }, diff --git a/app/controllers/admin/log.js b/app/controllers/admin/log.js index 48263f9..21a7547 100644 --- a/app/controllers/admin/log.js +++ b/app/controllers/admin/log.js @@ -37,7 +37,7 @@ class LogAdminController extends SiteController { const search = { }; if (req.query.component) { - search.component = { slug: req.query.component }; + search.component = { logId: req.query.component }; } res.locals.logs = await logService.getRecords(search, res.locals.pagination); @@ -51,7 +51,7 @@ class LogAdminController extends SiteController { } module.exports = { - logId: 'admin-log', + logId: 'admin:log', index: 'adminLog', className: 'LogAdminController', create: async (dtp) => { return new LogAdminController(dtp); }, diff --git a/app/controllers/admin/newsletter.js b/app/controllers/admin/newsletter.js index 201c095..fcad904 100644 --- a/app/controllers/admin/newsletter.js +++ b/app/controllers/admin/newsletter.js @@ -167,7 +167,7 @@ class NewsletterAdminController extends SiteController { } module.exports = { - logId: 'admin-newsletter', + logId: 'admin:newsletter', index: 'adminNewsletter', className: 'NewsletterAdminController', create: async (dtp) => { return new NewsletterAdminController(dtp); }, diff --git a/app/controllers/admin/newsroom.js b/app/controllers/admin/newsroom.js index 5c0a943..f88c885 100644 --- a/app/controllers/admin/newsroom.js +++ b/app/controllers/admin/newsroom.js @@ -158,8 +158,8 @@ class NewsroomAdminController extends SiteController { } module.exports = { - logId: 'newsroom-admin', - index: 'newsroomAdmin', + logId: 'admin:newsroom-admin', + index: 'adminNewsroomAdmin', className: 'NewsroomAdminController', create: async (dtp) => { return new NewsroomAdminController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/otp.js b/app/controllers/admin/otp.js index 8ac2232..0868fbb 100644 --- a/app/controllers/admin/otp.js +++ b/app/controllers/admin/otp.js @@ -49,7 +49,7 @@ class OtpAdminController extends SiteController { } module.exports = { - logId: 'admin-otp', + logId: 'admin:otp', index: 'adminOtp', className: 'OtpAdminController', create: async (dtp) => { return new OtpAdminController(dtp); }, diff --git a/app/controllers/admin/service-node.js b/app/controllers/admin/service-node.js index f1bf683..a277f72 100644 --- a/app/controllers/admin/service-node.js +++ b/app/controllers/admin/service-node.js @@ -128,7 +128,7 @@ class ServiceNodeAdminController extends SiteController { } module.exports = { - logId: 'admin-service-node', + logId: 'admin:service-node', index: 'adminServiceNode', className: 'ServiceNodeAdminController', create: async (dtp) => { return new ServiceNodeAdminController(dtp); }, diff --git a/app/controllers/admin/settings.js b/app/controllers/admin/settings.js index bc9eac1..24b5e35 100644 --- a/app/controllers/admin/settings.js +++ b/app/controllers/admin/settings.js @@ -98,7 +98,7 @@ class SettingsAdminController extends SiteController { } module.exports = { - logId: 'admin-settings', + logId: 'admin:settings', index: 'adminSettings', className: 'SettingsAdminController', create: async (dtp) => { return new SettingsAdminController(dtp); }, diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index 56efc81..80fb357 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -338,7 +338,7 @@ class UserAdminController extends SiteController { } module.exports = { - logId: 'admin-user', + logId: 'admin:user', index: 'adminUser', className: 'UserAdminController', create: async (dtp) => { return new UserAdminController(dtp); }, diff --git a/app/controllers/announcement.js b/app/controllers/announcement.js index ff0f17f..fcc0869 100644 --- a/app/controllers/announcement.js +++ b/app/controllers/announcement.js @@ -76,7 +76,7 @@ class AnnouncementController extends SiteController { } module.exports = { - logId: 'announcement', + logId: 'ctl:announcement', index: 'announcement', className: 'AnnouncementController', create: async (dtp) => { return new AnnouncementController(dtp); }, diff --git a/app/controllers/auth.js b/app/controllers/auth.js index 61429c6..9722902 100644 --- a/app/controllers/auth.js +++ b/app/controllers/auth.js @@ -339,7 +339,7 @@ class AuthController extends SiteController { } module.exports = { - logId: 'auth', + logId: 'ctl:auth', index: 'auth', className: 'AuthController', create: async (dtp) => { return new AuthController(dtp); }, diff --git a/app/controllers/chat.js b/app/controllers/chat.js index 982b33a..11c3943 100644 --- a/app/controllers/chat.js +++ b/app/controllers/chat.js @@ -648,7 +648,7 @@ class ChatController extends SiteController { } module.exports = { - logId: 'chat', + logId: 'ctl:chat', index: 'chat', className: 'ChatController', create: async (dtp) => { return new ChatController(dtp); }, diff --git a/app/controllers/comment.js b/app/controllers/comment.js index e87db14..3b5f18a 100644 --- a/app/controllers/comment.js +++ b/app/controllers/comment.js @@ -151,7 +151,7 @@ class CommentController extends SiteController { } module.exports = { - logId: 'comment', + logId: 'ctl:comment', index: 'comment', className: 'CommentController', create: async (dtp) => { return new CommentController(dtp); }, diff --git a/app/controllers/email.js b/app/controllers/email.js index 45bb185..27b0fd4 100644 --- a/app/controllers/email.js +++ b/app/controllers/email.js @@ -81,7 +81,7 @@ class EmailController extends SiteController { } module.exports = { - logId: 'email', + logId: 'ctl:email', index: 'email', className: 'EmailController', create: async (dtp) => { return new EmailController(dtp); }, diff --git a/app/controllers/form.js b/app/controllers/form.js index b44371a..7b5736c 100644 --- a/app/controllers/form.js +++ b/app/controllers/form.js @@ -64,7 +64,7 @@ class FormController extends SiteController { } module.exports = { - logId: 'form', + logId: 'ctl:form', index: 'form', className: 'FormController', create: async (dtp) => { return new FormController(dtp); }, diff --git a/app/controllers/hive.js b/app/controllers/hive.js index 2b7b7c1..fb9be44 100644 --- a/app/controllers/hive.js +++ b/app/controllers/hive.js @@ -57,7 +57,7 @@ class HiveController extends SiteController { } module.exports = { - logId: 'hive', + logId: 'ctl:hive', index: 'hive', className: 'HiveController', create: async (dtp) => { return new HiveController(dtp); }, diff --git a/app/controllers/hive/kaleidoscope.js b/app/controllers/hive/kaleidoscope.js index 5bc86f9..33a826f 100644 --- a/app/controllers/hive/kaleidoscope.js +++ b/app/controllers/hive/kaleidoscope.js @@ -93,7 +93,7 @@ class HiveKaleidoscopeController extends SiteController { } module.exports = { - logId: 'hive-kaleidoscope', + logId: 'ctl:hive-kaleidoscope', index: 'hiveKaleidoscope', className: 'HiveKaleidoscopeController', create: async (dtp) => { return new HiveKaleidoscopeController(dtp); }, diff --git a/app/controllers/hive/user.js b/app/controllers/hive/user.js index b21dd19..bbbe862 100644 --- a/app/controllers/hive/user.js +++ b/app/controllers/hive/user.js @@ -149,7 +149,7 @@ class HiveUserController extends SiteController { } module.exports = { - logId: 'hive-user', + logId: 'ctl:hive-user', index: 'hiveUser', className: 'HiveUserController', create: async (dtp) => { return new HiveUserController(dtp); }, diff --git a/app/controllers/home.js b/app/controllers/home.js index 8d032b5..cd0951f 100644 --- a/app/controllers/home.js +++ b/app/controllers/home.js @@ -93,7 +93,7 @@ class HomeController extends SiteController { } module.exports = { - logId: 'home', + logId: 'ctl:home', index: 'home', className: 'HomeController', create: async (dtp) => { return new HomeController(dtp); }, diff --git a/app/controllers/image.js b/app/controllers/image.js index 4d2b703..543f33f 100644 --- a/app/controllers/image.js +++ b/app/controllers/image.js @@ -135,7 +135,7 @@ class ImageController extends SiteController { } module.exports = { - logId: 'image', + logId: 'ctl:image', index: 'image', className: 'ImageController', create: async (dtp) => { return new ImageController(dtp); }, diff --git a/app/controllers/manifest.js b/app/controllers/manifest.js index a7a3880..51c2cad 100644 --- a/app/controllers/manifest.js +++ b/app/controllers/manifest.js @@ -64,7 +64,7 @@ class ManifestController extends SiteController { } module.exports = { - logId: 'manifest', + logId: 'ctl:manifest', index: 'manifest', className: 'ManifestController', create: async (dtp) => { return new ManifestController(dtp); }, diff --git a/app/controllers/newsletter.js b/app/controllers/newsletter.js index c45f32e..419eff6 100644 --- a/app/controllers/newsletter.js +++ b/app/controllers/newsletter.js @@ -92,7 +92,7 @@ class NewsletterController extends SiteController { } module.exports = { - logId: 'newsletter', + logId: 'ctl:newsletter', index: 'newsletter', className: 'NewsletterController', create: async (dtp) => { return new NewsletterController(dtp); }, diff --git a/app/controllers/newsroom.js b/app/controllers/newsroom.js index a1b05dc..ad62f65 100644 --- a/app/controllers/newsroom.js +++ b/app/controllers/newsroom.js @@ -165,7 +165,7 @@ class NewsroomController extends SiteController { } module.exports = { - logId: 'newsroom', + logId: 'ctl:newsroom', index: 'newsroom', className: 'NewsroomController', create: (dtp) => { return new NewsroomController(dtp); }, diff --git a/app/controllers/notification.js b/app/controllers/notification.js index 3614c38..fbca3d0 100644 --- a/app/controllers/notification.js +++ b/app/controllers/notification.js @@ -72,7 +72,7 @@ class NotificationController extends SiteController { } module.exports = { - logId: 'notification', + logId: 'ctl:notification', index: 'notification', className: 'NotificationController', create: async (dtp) => { return new NotificationController(dtp); }, diff --git a/app/controllers/user.js b/app/controllers/user.js index cb450b4..4e54dba 100644 --- a/app/controllers/user.js +++ b/app/controllers/user.js @@ -644,7 +644,7 @@ class UserController extends SiteController { } module.exports = { - logId: 'user', + logId: 'ctl:user', index: 'user', className: 'UserController', create: async (dtp) => { return new UserController(dtp); }, diff --git a/app/controllers/welcome.js b/app/controllers/welcome.js index 4a9499e..3b0b401 100644 --- a/app/controllers/welcome.js +++ b/app/controllers/welcome.js @@ -120,7 +120,7 @@ class WelcomeController extends SiteController { } module.exports = { - logId: 'welcome', + logId: 'ctl:welcome', index: 'welcome', className: 'WelcomeController', create: async (dtp) => { return new WelcomeController(dtp); }, diff --git a/app/services/announcement.js b/app/services/announcement.js index aa7aee6..02e8277 100644 --- a/app/services/announcement.js +++ b/app/services/announcement.js @@ -116,7 +116,7 @@ class AnnouncementService extends SiteService { } module.exports = { - logId: 'announcement', + logId: 'svc:announcement', index: 'announcement', className: 'AnnouncementService', create: (dtp) => { return new AnnouncementService(dtp); }, diff --git a/app/services/attachment.js b/app/services/attachment.js index a4c407c..309e00f 100644 --- a/app/services/attachment.js +++ b/app/services/attachment.js @@ -211,7 +211,7 @@ class AttachmentService extends SiteService { } module.exports = { - logId: 'attachment', + logId: 'svc:attachment', index: 'attachment', className: 'AttachmentService', create: (dtp) => { return new AttachmentService(dtp); }, diff --git a/app/services/cache.js b/app/services/cache.js index 9827291..8da2605 100644 --- a/app/services/cache.js +++ b/app/services/cache.js @@ -57,7 +57,7 @@ class CacheService extends SiteService { } module.exports = { - logId: 'cache', + logId: 'svc:cache', index: 'cache', className: 'CacheService', create: (dtp) => { return new CacheService(dtp); }, diff --git a/app/services/chat.js b/app/services/chat.js index 77a7e7e..1c4a744 100644 --- a/app/services/chat.js +++ b/app/services/chat.js @@ -862,7 +862,7 @@ class ChatService extends SiteService { } module.exports = { - logId: 'chat', + logId: 'svc:chat', index: 'chat', className: 'ChatService', create: (dtp) => { return new ChatService(dtp); }, diff --git a/app/services/comment.js b/app/services/comment.js index aff2c11..0ea4158 100644 --- a/app/services/comment.js +++ b/app/services/comment.js @@ -350,7 +350,7 @@ class CommentService extends SiteService { } module.exports = { - logId: 'comment', + logId: 'svc:comment', index: 'comment', className: 'CommentService', create: (dtp) => { return new CommentService(dtp); }, diff --git a/app/services/content-report.js b/app/services/content-report.js index e239a76..59c2190 100644 --- a/app/services/content-report.js +++ b/app/services/content-report.js @@ -127,7 +127,7 @@ class ContentReportService extends SiteService { } module.exports = { - logId: 'content-report', + logId: 'svc:content-report', index: 'contentReport', className: 'ContentReportService', create: (dtp) => { return new ContentReportService(dtp); }, diff --git a/app/services/content-vote.js b/app/services/content-vote.js index bf65984..d5916eb 100644 --- a/app/services/content-vote.js +++ b/app/services/content-vote.js @@ -117,7 +117,7 @@ class ContentVoteService extends SiteService { } module.exports = { - logId: 'content-vote', + logId: 'svc:content-vote', index: 'contentVote', className: 'ContentVoteService', create: (dtp) => { return new ContentVoteService(dtp); }, diff --git a/app/services/core-node.js b/app/services/core-node.js index a543eac..1662673 100644 --- a/app/services/core-node.js +++ b/app/services/core-node.js @@ -803,7 +803,7 @@ class CoreNodeService extends SiteService { } module.exports = { - logId: 'core-node', + logId: 'svc:core-node', index: 'coreNode', className: 'CoreNodeService', create: (dtp) => { return new CoreNodeService(dtp); }, diff --git a/app/services/crypto.js b/app/services/crypto.js index b95f001..2325078 100644 --- a/app/services/crypto.js +++ b/app/services/crypto.js @@ -58,7 +58,7 @@ class CryptoService extends SiteService { } module.exports = { - logId: 'crypto', + logId: 'svc:crypto', index: 'crypto', className: 'CryptoService', create: (dtp) => { return new CryptoService(dtp); }, diff --git a/app/services/csrf-token.js b/app/services/csrf-token.js index b253704..3594074 100644 --- a/app/services/csrf-token.js +++ b/app/services/csrf-token.js @@ -76,7 +76,7 @@ class CsrfTokenService extends SiteService { } module.exports = { - logId: 'csrf-token', + logId: 'svc:csrf-token', index: 'csrfToken', className: 'CsrfTokenService', create: (dtp) => { return new CsrfTokenService(dtp); }, diff --git a/app/services/dashboard.js b/app/services/dashboard.js index cdf4507..7d7d6a7 100644 --- a/app/services/dashboard.js +++ b/app/services/dashboard.js @@ -270,7 +270,7 @@ class DashboardService extends SiteService { } module.exports = { - logId: 'dashboard', + logId: 'svc:dashboard', index: 'dashboard', className: 'DashboardService', create: (dtp) => { return new DashboardService(dtp); }, diff --git a/app/services/display-engine.js b/app/services/display-engine.js index 17feb93..bca2993 100644 --- a/app/services/display-engine.js +++ b/app/services/display-engine.js @@ -150,7 +150,7 @@ class DisplayEngineService extends SiteService { } module.exports = { - logId: 'display-engine', + logId: 'svc:display-engine', index: 'displayEngine', className: 'DisplayEngineService', create: (dtp) => { return new DisplayEngineService(dtp); }, diff --git a/app/services/email.js b/app/services/email.js index 3ca513a..76b6364 100644 --- a/app/services/email.js +++ b/app/services/email.js @@ -171,7 +171,7 @@ class EmailService extends SiteService { } module.exports = { - logId: 'email', + logId: 'svc:email', index: 'email', className: 'EmailService', create: (dtp) => { return new EmailService(dtp); }, diff --git a/app/services/feed.js b/app/services/feed.js index 2ca64e9..2586af4 100644 --- a/app/services/feed.js +++ b/app/services/feed.js @@ -176,7 +176,7 @@ class FeedService extends SiteService { } module.exports = { - logId: 'feed', + logId: 'svc:feed', index: 'feed', className: 'FeedService', create: (dtp) => { return new FeedService(dtp); }, diff --git a/app/services/hive.js b/app/services/hive.js index 509f464..ef49931 100644 --- a/app/services/hive.js +++ b/app/services/hive.js @@ -330,7 +330,7 @@ class HiveService extends SiteService { } module.exports = { - logId: 'hive', + logId: 'svc:hive', index: 'hive', className: 'HiveService', create: (dtp) => { return new HiveService(dtp); }, diff --git a/app/services/host-cache.js b/app/services/host-cache.js index 6b02438..d8d7d39 100644 --- a/app/services/host-cache.js +++ b/app/services/host-cache.js @@ -97,7 +97,7 @@ class HostCacheService extends SiteService { } module.exports = { - logId: 'host-cache', + logId: 'svc:host-cache', index: 'hostCache', className: 'HostCacheService', create: (dtp) => { return new HostCacheService(dtp); }, diff --git a/app/services/image.js b/app/services/image.js index 1321f9f..66686a3 100644 --- a/app/services/image.js +++ b/app/services/image.js @@ -320,7 +320,7 @@ class ImageService extends SiteService { } module.exports = { - logId: 'image', + logId: 'svc:image', index: 'image', className: 'ImageService', create: (dtp) => { return new ImageService(dtp); }, diff --git a/app/services/job-queue.js b/app/services/job-queue.js index e825ba9..7018c1a 100644 --- a/app/services/job-queue.js +++ b/app/services/job-queue.js @@ -62,7 +62,7 @@ class JobQueueService extends SiteService { } module.exports = { - logId: 'job-queue', + logId: 'svc:job-queue', index: 'jobQueue', className: 'JobQueueService', create: (dtp) => { return new JobQueueService(dtp); }, diff --git a/app/services/limiter.js b/app/services/limiter.js index 6a88ed1..80ad38b 100644 --- a/app/services/limiter.js +++ b/app/services/limiter.js @@ -69,7 +69,7 @@ class LimiterService extends SiteService { } module.exports = { - logId: 'limiter', + logId: 'svc:limiter', index: 'limiter', className: 'LimiterService', create: (dtp) => { return new LimiterService(dtp); }, diff --git a/app/services/log.js b/app/services/log.js index 75286b6..e910b6d 100644 --- a/app/services/log.js +++ b/app/services/log.js @@ -38,7 +38,7 @@ class SystemLogService extends SiteService { } module.exports = { - logId: 'log', + logId: 'svc:log', index: 'log', className: 'SystemLogService', create: (dtp) => { return new SystemLogService(dtp); }, diff --git a/app/services/logan.js b/app/services/logan.js index 338dad0..87df2d6 100644 --- a/app/services/logan.js +++ b/app/services/logan.js @@ -68,7 +68,7 @@ class LoganService extends SiteService { } module.exports = { - logId: 'logan', + logId: 'svc:logan', index: 'logan', className: 'LoganService', create: (dtp) => { return new LoganService(dtp); }, diff --git a/app/services/markdown.js b/app/services/markdown.js index d70f570..92b7aeb 100644 --- a/app/services/markdown.js +++ b/app/services/markdown.js @@ -32,7 +32,7 @@ class MarkdownService extends SiteService { } module.exports = { - logId: 'markdown', + logId: 'svc:markdown', index: 'markdown', className: 'MarkdownService', create: (dtp) => { return new MarkdownService(dtp); }, diff --git a/app/services/media.js b/app/services/media.js index 6306618..67f4daa 100644 --- a/app/services/media.js +++ b/app/services/media.js @@ -94,7 +94,7 @@ class MediaService extends SiteService { } module.exports = { - logId: 'media', + logId: 'svc:media', index: 'media', className: 'MediaService', create: (dtp) => { return new MediaService(dtp); }, diff --git a/app/services/minio.js b/app/services/minio.js index bbaf5e9..da9258d 100644 --- a/app/services/minio.js +++ b/app/services/minio.js @@ -97,7 +97,7 @@ class MinioService extends SiteService { } module.exports = { - logId: 'minio', + logId: 'svc:minio', index: 'minio', className: 'MinioService', create: (dtp) => { return new MinioService(dtp); }, diff --git a/app/services/newsletter.js b/app/services/newsletter.js index 5c3647a..d730ba3 100644 --- a/app/services/newsletter.js +++ b/app/services/newsletter.js @@ -117,7 +117,7 @@ class NewsletterService extends SiteService { } module.exports = { - logId: 'newsletter', + logId: 'svc:newsletter', index: 'newsletter', className: 'NewsletterService', create: (dtp) => { return new NewsletterService(dtp); }, diff --git a/app/services/oauth2.js b/app/services/oauth2.js index b557df7..2bdd2bd 100644 --- a/app/services/oauth2.js +++ b/app/services/oauth2.js @@ -474,7 +474,7 @@ class OAuth2Service extends SiteService { } module.exports = { - logId: 'oauth2', + logId: 'svc:oauth2', index: 'oauth2', className: 'OAuth2Service', create: (dtp) => { return new OAuth2Service(dtp); }, diff --git a/app/services/otp-auth.js b/app/services/otp-auth.js index 8afaff5..e4b5f9b 100644 --- a/app/services/otp-auth.js +++ b/app/services/otp-auth.js @@ -238,7 +238,7 @@ class OtpAuthService extends SiteService { } module.exports = { - logId: 'otp-auth', + logId: 'svc:otp-auth', index: 'otpAuth', className: 'OtpAuthService', create: (dtp) => { return new OtpAuthService(dtp); }, diff --git a/app/services/phone.js b/app/services/phone.js index c6b91bf..3ae21c0 100644 --- a/app/services/phone.js +++ b/app/services/phone.js @@ -55,7 +55,7 @@ class PhoneService extends SiteService { } module.exports = { - logId: 'phone', + logId: 'svc:phone', index: 'phone', className: 'PhoneService', create: (dtp) => { return new PhoneService(dtp); }, diff --git a/app/services/resource.js b/app/services/resource.js index 95704c0..167d8c7 100644 --- a/app/services/resource.js +++ b/app/services/resource.js @@ -118,7 +118,7 @@ class ResourceService extends SiteService { } module.exports = { - logId: 'resource', + logId: 'svc:resource', index: 'resource', className: 'ResourceService', create: (dtp) => { return new ResourceService(dtp); }, diff --git a/app/services/session.js b/app/services/session.js index 18545f2..2767dae 100644 --- a/app/services/session.js +++ b/app/services/session.js @@ -110,7 +110,7 @@ class SessionService extends SiteService { } module.exports = { - logId: 'session', + logId: 'svc:session', index: 'session', className: 'SessionService', create: (dtp) => { return new SessionService(dtp); }, diff --git a/app/services/sms.js b/app/services/sms.js index 6a15fd1..8496839 100644 --- a/app/services/sms.js +++ b/app/services/sms.js @@ -47,7 +47,7 @@ class SmsService extends SiteService { } module.exports = { - logId: 'sms', + logId: 'svc:sms', index: 'sms', className: 'SmsService', create: (dtp) => { return new SmsService(dtp); }, diff --git a/app/services/sticker.js b/app/services/sticker.js index 713b105..6d6fdd8 100644 --- a/app/services/sticker.js +++ b/app/services/sticker.js @@ -11,7 +11,7 @@ const mongoose = require('mongoose'); const Sticker = mongoose.model('Sticker'); const User = mongoose.model('User'); -const { SiteService, SiteError, SiteAsync } = require('../../lib/site-lib'); +const { SiteService, SiteError } = require('../../lib/site-lib'); const MAX_CHANNEL_STICKERS = 50; const MAX_USER_STICKERS = 10; @@ -144,18 +144,42 @@ class StickerService extends SiteService { await Sticker.updateOne({ _id: sticker._id }, { $set: { status } }); } + /** + * Fetch and populate an Array of Sticker documents matching the input slugs. + * + * The returned Array may be smaller than the input Array (or empty) if some + * or none of the stickers have been deleted or simply don't exist. + * + * @param {Array} slugs an Array of sticker slugs + * @returns Array of populated matching Sticker documents + */ async resolveStickerSlugs (slugs) { - const stickers = [ ]; - await SiteAsync.each(slugs, async (slug) => { - const sticker = await Sticker.findOne({ slug: slug }); - if (!sticker) { - return; - } - stickers.push(sticker); - }); + const stickers = await Sticker + .find({ slug: { $in: slugs } }) + .populate(this.populateSticker) + .lean(); return stickers; } + /** + * Convert an array of sticker slugs to an array of sticker _id values. This + * is used during chat message ingest where the whole populated sticker just + * isn't needed and is all discarded. + * + * The returned Array may be smaller than the input Array (or empty) if some + * or none of the stickers have been deleted or simply don't exist. + * + * @param {Array} slugs an Array of sticker slugs + * @returns an Array of sticker IDs + */ + async resolveStickerSlugIds (slugs) { + const stickers = await Sticker + .find({ slug: { $in: slugs } }) + .select('_id') + .lean(); + return stickers.map((sticker) => sticker._id); + } + async removeSticker (sticker) { const stickerId = sticker._id; this.log.info('creating sticker delete job', { stickerId }); @@ -208,7 +232,7 @@ class StickerService extends SiteService { } module.exports = { - logId: 'sticker', + logId: 'svc:sticker', index: 'sticker', className: 'StickerService', create: (dtp) => { return new StickerService(dtp); }, diff --git a/app/services/user-notification.js b/app/services/user-notification.js index 733dee7..d528137 100644 --- a/app/services/user-notification.js +++ b/app/services/user-notification.js @@ -135,7 +135,7 @@ class UserNotificationService extends SiteService { } module.exports = { - logId: 'user-notification', + logId: 'svc:user-notification', index: 'userNotification', className: 'UserNotificationService', create: (dtp) => { return new UserNotificationService(dtp); }, diff --git a/app/services/user.js b/app/services/user.js index 62b976b..fcc7af8 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -972,7 +972,7 @@ class UserService extends SiteService { } module.exports = { - logId: 'user', + logId: 'svc:user', index: 'user', className: 'UserService', create: (dtp) => { return new UserService(dtp); }, diff --git a/app/workers/chat.js b/app/workers/chat.js index dba6236..2e981ca 100644 --- a/app/workers/chat.js +++ b/app/workers/chat.js @@ -17,7 +17,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { logId: 'chat-worker', index: 'chatWorker', className: 'ChatWorker' }, + component: { logId: 'wrk:chat', index: 'chatWorker', className: 'ChatWorker' }, }; module.config.site = require(path.join(module.rootPath, 'config', 'site')); diff --git a/app/workers/chat/job/chat-room-clear.js b/app/workers/chat/job/chat-room-clear.js index ec6e56e..2c43580 100644 --- a/app/workers/chat/job/chat-room-clear.js +++ b/app/workers/chat/job/chat-room-clear.js @@ -16,7 +16,7 @@ class ChatRoomClearJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'chat-room-clear-job', + logId: 'wrk:chat:room-clear:job', index: 'charRoomClearJob', className: 'ChatRoomClearJob', }; diff --git a/app/workers/chat/job/chat-room-delete.js b/app/workers/chat/job/chat-room-delete.js index 225761d..37ca2e5 100644 --- a/app/workers/chat/job/chat-room-delete.js +++ b/app/workers/chat/job/chat-room-delete.js @@ -15,18 +15,12 @@ const EmojiReaction = mongoose.model('EmojiReaction'); const { SiteWorkerProcess } = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'site-lib')); -/** - * DTP Core Chat sticker processor can receive requests to ingest and delete - * stickers to be executed as background jobs in a queue. This processor - * attaches to the `media` queue and registers processors for `sticker-ingest` - * and `sticker-delete`. - */ class ChatRoomDeleteJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'chat-room-processor', - index: 'chatRoomProcessor', + logId: 'wrk:chat:room-delete:job', + index: 'chatRoomDeleteJob', className: 'ChatRoomDeleteJob', }; } diff --git a/app/workers/host-services.js b/app/workers/host-services.js index 664386b..d8766bd 100644 --- a/app/workers/host-services.js +++ b/app/workers/host-services.js @@ -34,7 +34,7 @@ module.config = { root: module.rootPath, site: require(path.join(module.rootPath, 'config', 'site')), http: require(path.join(module.rootPath, 'config', 'http')), - component: { logId: 'host-services-worker', index: 'hostServicesWorker', className: 'HostServicesWorker' }, + component: { logId: 'wrk:host-services', index: 'hostServicesWorker', className: 'HostServicesWorker' }, }; module.log = new SiteLog(module, module.config.component); diff --git a/app/workers/logan.js b/app/workers/logan.js index 5173da7..65980ff 100644 --- a/app/workers/logan.js +++ b/app/workers/logan.js @@ -16,7 +16,7 @@ module.config = { environment: process.env.NODE_ENV, root: module.rootPath, site: require(path.join(module.rootPath, 'config', 'site')), - component: { logId: 'logan-site-worker', index: 'LoganSiteWorker', className: 'LoganSiteWorker' }, + component: { logId: 'wrk:logan-site', index: 'loganSite', className: 'LoganSiteWorker' }, }; class LoganSiteWorker extends SiteWorker { diff --git a/app/workers/media.js b/app/workers/media.js index 06e12e6..1f768e3 100644 --- a/app/workers/media.js +++ b/app/workers/media.js @@ -15,7 +15,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: path.resolve(__dirname, '..', '..'), - component: { logId: 'media-worker', index: 'mediaWorker', className: 'MediaWorker' }, + component: { logId: 'wrk:media', index: 'media', className: 'MediaWorker' }, }; /** diff --git a/app/workers/media/job/attachment-delete.js b/app/workers/media/job/attachment-delete.js index 931355a..9985898 100644 --- a/app/workers/media/job/attachment-delete.js +++ b/app/workers/media/job/attachment-delete.js @@ -15,7 +15,7 @@ class AttachmentDeleteJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'attachment-delete-job', + logId: 'wrk:chat:attachment-delete:job', index: 'attachmentDeleteJob', className: 'AttachmentDeleteJob', }; diff --git a/app/workers/media/job/attachment-ingest.js b/app/workers/media/job/attachment-ingest.js index ab77163..1626ecf 100644 --- a/app/workers/media/job/attachment-ingest.js +++ b/app/workers/media/job/attachment-ingest.js @@ -19,7 +19,7 @@ class AttachmentIngestJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'attachment-ingest-job', + logId: 'wrk:chat:attachment-ingest:job', index: 'attachmentIngestJob', className: 'AttachmentIngestJob', }; diff --git a/app/workers/media/job/sticker-delete.js b/app/workers/media/job/sticker-delete.js index d9b5461..cb71f91 100644 --- a/app/workers/media/job/sticker-delete.js +++ b/app/workers/media/job/sticker-delete.js @@ -15,7 +15,7 @@ class StickerDeleteJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'sticker-delete-job', + logId: 'wrk:chat:sticker-delete:job', index: 'stickerDeleteJob', className: 'StickerDeleteJob', }; diff --git a/app/workers/media/job/sticker-ingest.js b/app/workers/media/job/sticker-ingest.js index 6ec4ddd..3f23473 100644 --- a/app/workers/media/job/sticker-ingest.js +++ b/app/workers/media/job/sticker-ingest.js @@ -20,7 +20,7 @@ class StickerIngestJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'sticker-ingest-job', + logId: 'wrk:chat:sticker-ingest:job', index: 'stickerIngestJob', className: 'StickerIngestJob', }; diff --git a/app/workers/media/job/webpage-screenshot.js b/app/workers/media/job/webpage-screenshot.js index 7c18cb0..7690629 100644 --- a/app/workers/media/job/webpage-screenshot.js +++ b/app/workers/media/job/webpage-screenshot.js @@ -17,7 +17,7 @@ class WebpageScreenshotJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'webpage-screenshot-job', + logId: 'wrk:chat:webpage-screenshot:job', index: 'webpageScreenshotJob', className: 'WebpageScreenshotJob', }; diff --git a/app/workers/newsletter.js b/app/workers/newsletter.js index a004a22..11fc090 100644 --- a/app/workers/newsletter.js +++ b/app/workers/newsletter.js @@ -12,7 +12,7 @@ const { SiteWorker, SiteLog } = require(path.join(__dirname, '..', '..', 'lib', module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { root: path.resolve(__dirname, '..', '..'), - component: { logId: 'newsletter-worker', index: 'newsletterWorker', className: 'NewsletterWorker' }, + component: { logId: 'wrk:newsletter', index: 'newsletter', className: 'NewsletterWorker' }, }; class NewsletterWorker extends SiteWorker { diff --git a/app/workers/newsletter/job/email-send.js b/app/workers/newsletter/job/email-send.js index 04d24d6..fc8b63e 100644 --- a/app/workers/newsletter/job/email-send.js +++ b/app/workers/newsletter/job/email-send.js @@ -12,7 +12,7 @@ class NewsletterEmailSendJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'newsletter-email-send-job', + logId: 'wrk:newsletter:email-send:job', index: 'newsletterEmailSendJob', className: 'NewsletterEmailSendJob', }; diff --git a/app/workers/newsletter/job/transmit.js b/app/workers/newsletter/job/transmit.js index f4acc08..c8e4f1b 100644 --- a/app/workers/newsletter/job/transmit.js +++ b/app/workers/newsletter/job/transmit.js @@ -17,7 +17,7 @@ class NewsletterTransmitJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'newsletter-transmit-job', + logId: 'wrk:newsletter:transmit:job', index: 'newsletterTransmitJob', className: 'NewsletterTransmitJob', }; diff --git a/app/workers/newsroom.js b/app/workers/newsroom.js index 6fa69e2..eaea87d 100644 --- a/app/workers/newsroom.js +++ b/app/workers/newsroom.js @@ -23,7 +23,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { logId: 'newsroom', index: 'newsroom', className: 'NewsroomWorker' }, + component: { logId: 'wrk:newsroom', index: 'newsroom', className: 'NewsroomWorker' }, }; module.config.site = require(path.join(module.rootPath, 'config', 'site')); diff --git a/app/workers/newsroom/cron/update-feeds.js b/app/workers/newsroom/cron/update-feeds.js index 3cb03b3..7f10e23 100644 --- a/app/workers/newsroom/cron/update-feeds.js +++ b/app/workers/newsroom/cron/update-feeds.js @@ -17,7 +17,7 @@ class UpdateFeedsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'update-feeds-cron', + logId: 'wrk:newsroom:update-feeds:cron', index: 'updateFeeds', className: 'UpdateFeedsCron', }; diff --git a/app/workers/newsroom/job/update-feed.js b/app/workers/newsroom/job/update-feed.js index 4e0dcbb..03c13a0 100644 --- a/app/workers/newsroom/job/update-feed.js +++ b/app/workers/newsroom/job/update-feed.js @@ -12,7 +12,7 @@ class UpdateFeedJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'newsroom-update-feed-job', + logId: 'wrk:newsroom:update-feed:job', index: 'newsroomUpdateFeedJob', className: 'UpdateFeedJob', }; diff --git a/app/workers/reeeper.js b/app/workers/reeeper.js index 18d6dfd..62bb2ad 100644 --- a/app/workers/reeeper.js +++ b/app/workers/reeeper.js @@ -19,7 +19,7 @@ module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); module.config = { environment: process.env.NODE_ENV, root: module.rootPath, - component: { logId: 'reeeper', index: 'reeeper', className: 'ReeeperWorker' }, + component: { logId: 'wrk:reeeper', index: 'reeeper', className: 'ReeeperWorker' }, }; module.config.site = require(path.join(module.rootPath, 'config', 'site')); diff --git a/app/workers/reeeper/cron/expire-announcements.js b/app/workers/reeeper/cron/expire-announcements.js index 144302a..837830b 100644 --- a/app/workers/reeeper/cron/expire-announcements.js +++ b/app/workers/reeeper/cron/expire-announcements.js @@ -29,7 +29,7 @@ class ExpiredAnnouncementsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'expired-announcements-cron', + logId: 'wrk:chat:expired-announcements:cron', index: 'expiredAnnouncementsCron', className: 'ExpiredAnnouncementsCron', }; diff --git a/app/workers/reeeper/cron/expire-crashed-hosts.js b/app/workers/reeeper/cron/expire-crashed-hosts.js index 3edb617..17ea9a1 100644 --- a/app/workers/reeeper/cron/expire-crashed-hosts.js +++ b/app/workers/reeeper/cron/expire-crashed-hosts.js @@ -28,7 +28,7 @@ class CrashedHostsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'crashed-hosts-cron', + logId: 'wrk:reeeper:crashed-hosts:cron', index: 'crashedHostsCron', className: 'CrashedHostsCron', }; diff --git a/app/workers/reeeper/job/archive-user-local.js b/app/workers/reeeper/job/archive-user-local.js index 073c8cc..91d9da2 100644 --- a/app/workers/reeeper/job/archive-user-local.js +++ b/app/workers/reeeper/job/archive-user-local.js @@ -30,7 +30,7 @@ class ArchiveUserLocalJob extends SiteWorkerProcess { static get COMPONENT ( ) { return { - logId: 'archive-user-local-job', + logId: 'wrk:reeeper:archive-user-local:job', index: 'archiveUserLocalJob', className: 'ArchiveUserLocalJob', }; diff --git a/client/js/index-admin.js b/client/js/index-admin.js index 6324dd1..48aed4d 100644 --- a/client/js/index-admin.js +++ b/client/js/index-admin.js @@ -4,7 +4,7 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Site Admin', slug: 'site-admin' }; +const DTP_COMPONENT = { logId: 'site-admin-index', index: 'siteAdminIndex', className: 'SiteAdminIndex' }; const dtp = window.dtp = window.dtp || { }; dtp.admin = dtp.admin || { }; @@ -13,11 +13,9 @@ import DtpSiteAdminApp from './site-admin-app.js'; import DtpWebLog from 'dtp/dtp-log.js'; window.addEventListener('load', async ( ) => { - // application console log dtp.admin.log = new DtpWebLog(DTP_COMPONENT); - dtp.adminApp = new DtpSiteAdminApp(dtp.user); - dtp.admin.log.debug('load', 'dispatching load event'); + dtp.admin.log.debug('load', 'dispatching admin load event'); window.dispatchEvent(new Event('dtp-load-admin')); }); \ No newline at end of file diff --git a/client/js/index.js b/client/js/index.js index 3288abe..362587e 100644 --- a/client/js/index.js +++ b/client/js/index.js @@ -4,13 +4,12 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Site', slug: 'site' }; +const DTP_COMPONENT = { logId: 'site-index', index: 'siteIndex', className: 'SiteIndex' }; const dtp = window. dtp = window.dtp || { }; import DtpSiteApp from './site-app.js'; import DtpWebLog from 'dtp/dtp-log.js'; -// import UIkit from 'uikit'; /** * Monkeypatch to count characters instead of .length's code point count. diff --git a/client/js/site-admin-app.js b/client/js/site-admin-app.js index 6ba76b5..4c65a4b 100644 --- a/client/js/site-admin-app.js +++ b/client/js/site-admin-app.js @@ -4,7 +4,7 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Site Admin', slug: 'site-admin-app' }; +const DTP_COMPONENT = { logId: 'site-admin-app', index: 'siteAdminApp', className: 'SiteAdminApp' }; const dtp = window.dtp = window.dtp || { }; const GRID_COLOR = '#a0a0a0'; @@ -25,7 +25,7 @@ import numeral from 'numeral'; import UIkit from 'uikit'; // import UIkit from 'uikit'; -export default class DtpSiteAdminHostStatsApp extends DtpApp { +export default class DtpSiteAdminApp extends DtpApp { constructor (user) { super(DTP_COMPONENT, user); @@ -461,4 +461,4 @@ export default class DtpSiteAdminHostStatsApp extends DtpApp { } } -dtp.DtpSiteAdminHostStatsApp = DtpSiteAdminHostStatsApp; \ No newline at end of file +dtp.DtpSiteAdminApp = DtpSiteAdminApp; \ No newline at end of file diff --git a/client/js/site-app.js b/client/js/site-app.js index b4711ac..7becf3c 100644 --- a/client/js/site-app.js +++ b/client/js/site-app.js @@ -4,7 +4,7 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Site App', slug: 'site-app' }; +const DTP_COMPONENT = { logId: 'site-app', index: 'siteApp', className: 'DtpSiteApp' }; const dtp = window.dtp = window.dtp || { }; import DtpApp from 'dtp/dtp-app.js'; diff --git a/client/js/site-chat.js b/client/js/site-chat.js index 23af616..aa06147 100644 --- a/client/js/site-chat.js +++ b/client/js/site-chat.js @@ -4,7 +4,7 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Site Chat', slug: 'site-chat' }; +const DTP_COMPONENT = { logId: 'site-chat', index: 'siteChat', className: 'DtpSiteChat' }; const dtp = window.dtp = window.dtp || { }; // jshint ignore:line const EMOJI_EXPLOSION_DURATION = 8000; diff --git a/client/js/site-comments.js b/client/js/site-comments.js index fe12dc3..e99b94c 100644 --- a/client/js/site-comments.js +++ b/client/js/site-comments.js @@ -14,7 +14,7 @@ export default class SiteComments { constructor (app) { this.app = app; - this.log = new DtpLog({ name: 'Site Comments', slug: 'comments' }); + this.log = new DtpLog({ logId: 'site-comments', index: 'siteComments', className: 'SiteComments' }); this.createEmojiPickers(); } diff --git a/client/js/site-reactions.js b/client/js/site-reactions.js index a6116fb..77da099 100644 --- a/client/js/site-reactions.js +++ b/client/js/site-reactions.js @@ -4,7 +4,7 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Site Reactions', slug: 'site-reactions' }; +const DTP_COMPONENT = { logId: 'site-reactions', index: 'siteReactions', className: 'SiteReactions' }; const dtp = window.dtp = window.dtp || { }; // jshint ignore:line import DtpLog from 'dtp/dtp-log'; diff --git a/docs/samples/controller.js b/docs/samples/controller.js index 3a55f4d..1a845e7 100644 --- a/docs/samples/controller.js +++ b/docs/samples/controller.js @@ -90,8 +90,15 @@ class HomeController extends SiteController { } module.exports = { - slug: 'home', - name: 'home', - isHome: true, + logId: 'home', + index: 'home', + className: 'HomeController', create: async (dtp) => { return new HomeController(dtp); }, + + /* + * This attribute must exist and be set to true on your Home controller to + * ensure that it is started last. This matters for ensuring that your root + * route is registered to ExpressJS last. + */ + isHome: true, }; \ No newline at end of file diff --git a/docs/samples/service.js b/docs/samples/service.js index e7dc312..e620383 100644 --- a/docs/samples/service.js +++ b/docs/samples/service.js @@ -62,7 +62,8 @@ class SampleService extends SiteService { } module.exports = { + logId: 'svc:sample', name: 'sample', - slug: 'sample', + className: 'SampleService', create: (dtp) => { return new SampleService(dtp); }, }; \ No newline at end of file diff --git a/docs/samples/worker.js b/docs/samples/worker.js index d3c725c..5240c32 100644 --- a/docs/samples/worker.js +++ b/docs/samples/worker.js @@ -33,7 +33,7 @@ class SampleWorker extends SiteWorker { try { module.rootPath = path.resolve(__dirname, '..', '..'); module.pkg = require(path.resolve(__dirname, '..', '..', 'package.json')); - module.component = { name: 'theWorkerName', slug: 'the-worker-name' }; + module.component = { logId: 'wrk:sample', index: 'sampleWorker', className: 'SampleWorker' }; module.config = { environment: process.env.NODE_ENV, diff --git a/docs/services.md b/docs/services.md index 2cb68c6..eb3cebf 100644 --- a/docs/services.md +++ b/docs/services.md @@ -33,8 +33,9 @@ class MyService extends SiteService { } module.exports = { - slug: 'my-service', - name: 'myService', + logId: 'my-service', + index: 'myService', + className: 'MyService', create: (dtp) => { return new MyService(dtp); }, }; ``` \ No newline at end of file diff --git a/dtp-media-engine.js b/dtp-media-engine.js index 4b0bad8..1c11398 100644 --- a/dtp-media-engine.js +++ b/dtp-media-engine.js @@ -16,7 +16,7 @@ const { SiteAsync, SiteCommon, SitePlatform, SiteLog } = require(path.join(__dir module.rootPath = __dirname; module.pkg = require(path.join(module.rootPath, 'package.json')); module.config = { - component: { name: 'dtpMediaEngine', slug: 'dtp-media-engine' }, + component: { logId: 'dtp-media-engine', index: 'dtpMediaEngine', className: 'DtpMediaEngine' }, root: module.rootPath, site: require(path.join(module.rootPath, 'config', 'site')), webRtcServer: [ @@ -33,7 +33,7 @@ module.log = new SiteLog(module, module.config.component); class MediaEngineWorker extends SiteCommon { constructor ( ) { - super(module, { name: 'dtpMediaWorker', slug: 'dtp-media-worker' }); + super(module, { logId: 'dtp-media-worker', index: 'dtpMediaWorker', className: 'MediaEngineWorker' }); this._id = mongoose.Types.ObjectId(); } diff --git a/lib/client/js/dtp-display-engine.js b/lib/client/js/dtp-display-engine.js index 0005dcc..18e6a5a 100644 --- a/lib/client/js/dtp-display-engine.js +++ b/lib/client/js/dtp-display-engine.js @@ -4,17 +4,17 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Display Engine', slug: 'display-engine' }; - import UIkit from 'uikit'; import DtpLog from './dtp-log.js'; export default class DtpDisplayEngine { + static get COMPONENT ( ) { return { logId: 'display-engine', index: 'displayEngine', className: 'DisplayEngine' }; } + constructor (app) { this.app = app; this.processors = { }; - this.log = new DtpLog(DTP_COMPONENT); + this.log = new DtpLog(DtpDisplayEngine.DTP_COMPONENT); } /** diff --git a/lib/client/js/dtp-socket.js b/lib/client/js/dtp-socket.js index be63d47..bddaa12 100644 --- a/lib/client/js/dtp-socket.js +++ b/lib/client/js/dtp-socket.js @@ -4,19 +4,19 @@ 'use strict'; -const DTP_COMPONENT = { name: 'Socket', slug: 'socket' }; - window.dtp = window.dtp || { }; import DtpWebLog from './dtp-log.js'; export default class DtpWebSocket { + static get COMPONENT ( ) { return { logId: 'socket', index: 'socket', className: 'DtpWebSocket' }; } + constructor ( ) { this.isConnected = false; this.isAuthenticated = false; this.joinedChannels = { }; - this.log = new DtpWebLog(DTP_COMPONENT); + this.log = new DtpWebLog(DtpWebSocket.DTP_COMPONENT); } async connect (options) { diff --git a/lib/site-worker-process.js b/lib/site-worker-process.js index 5d5ac46..57ac5ff 100644 --- a/lib/site-worker-process.js +++ b/lib/site-worker-process.js @@ -15,7 +15,7 @@ const { SiteCommon } = require(path.join(__dirname, 'site-common')); * Your derived class must implement a static getter for COMPONENT as follows: * * ``` - * static get COMPONENT ( ) { return { name: '', slug: '' }; } + * static get COMPONENT ( ) { return { logId: '', name: '', className: '' }; } * ``` * * It must pass that object to this constructor (super) along with the worker diff --git a/update-deps.js b/update-deps.js index a81ac2e..400ed3f 100644 --- a/update-deps.js +++ b/update-deps.js @@ -16,7 +16,7 @@ module.pkg = require(path.join(module.rootPath, 'package.json')); module.pinnedPackages = require(path.join(module.rootPath, 'config', 'pinned-packages')); module.config = { - component: { name: 'Webapp Dependency Updater', slug: 'webapp-update-deps' }, + component: { logId: 'webapp-update-deps', name: 'dtpUpdateDeps', className: 'DtpUpdateDeps' }, }; module.log = new SiteLog(module, module.config.component); From 230dbdde6f20809c02fc039611c400a700456fc9 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 05:52:03 -0400 Subject: [PATCH 61/76] component defs --- app/controllers/admin/announcement.js | 2 +- app/controllers/admin/attachment.js | 2 +- app/controllers/admin/content-report.js | 2 +- app/controllers/admin/core-node.js | 2 +- app/controllers/admin/core-user.js | 2 +- app/controllers/admin/host.js | 2 +- app/controllers/admin/image.js | 2 +- app/controllers/admin/job-queue.js | 2 +- app/controllers/admin/log.js | 2 +- app/controllers/admin/newsletter.js | 2 +- app/controllers/admin/newsroom.js | 2 +- app/controllers/admin/otp.js | 2 +- app/controllers/admin/service-node.js | 2 +- app/controllers/admin/settings.js | 2 +- app/controllers/admin/user.js | 2 +- app/controllers/hive/kaleidoscope.js | 2 +- app/controllers/hive/user.js | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/controllers/admin/announcement.js b/app/controllers/admin/announcement.js index 3c0c1d6..b55a013 100644 --- a/app/controllers/admin/announcement.js +++ b/app/controllers/admin/announcement.js @@ -158,7 +158,7 @@ class AnnouncementAdminController extends SiteController { } module.exports = { - logId: 'admin:announcement', + logId: 'ctl:admin:announcement', index: 'announcement', className: 'AnnouncementAdminController', create: async (dtp) => { return new AnnouncementAdminController(dtp); }, diff --git a/app/controllers/admin/attachment.js b/app/controllers/admin/attachment.js index 8268f37..688e919 100644 --- a/app/controllers/admin/attachment.js +++ b/app/controllers/admin/attachment.js @@ -130,7 +130,7 @@ class AttachmentAdminController extends SiteController { } module.exports = { - logId: 'admin:admin-attachment', + logId: 'ctl:admin:attachment', index: 'adminAttachment', className: 'AttachmentAdminController', create: async (dtp) => { return new AttachmentAdminController(dtp); }, diff --git a/app/controllers/admin/content-report.js b/app/controllers/admin/content-report.js index 9205988..e1c4774 100644 --- a/app/controllers/admin/content-report.js +++ b/app/controllers/admin/content-report.js @@ -87,7 +87,7 @@ class ContentReportAdminController extends SiteController { } module.exports = { - logId: 'admin:content-report', + logId: 'ctl:admin:content-report', index: 'adminContentReport', className: 'ContentReportAdminController', create: async (dtp) => { return new ContentReportAdminController(dtp); }, diff --git a/app/controllers/admin/core-node.js b/app/controllers/admin/core-node.js index 519ed63..772eec4 100644 --- a/app/controllers/admin/core-node.js +++ b/app/controllers/admin/core-node.js @@ -159,7 +159,7 @@ class CoreNodeAdminController extends SiteController { } module.exports = { - logId: 'admin:core-node', + logId: 'ctl:admin:core-node', index: 'adminCoreNode', className: 'CoreNodeAdminController', create: async (dtp) => { return new CoreNodeAdminController(dtp); }, diff --git a/app/controllers/admin/core-user.js b/app/controllers/admin/core-user.js index 51b131d..f3c9479 100644 --- a/app/controllers/admin/core-user.js +++ b/app/controllers/admin/core-user.js @@ -88,7 +88,7 @@ class CoreUserAdminController extends SiteController { } module.exports = { - logId: 'admin:core-user', + logId: 'ctl:admin:core-user', index: 'adminCoreUser', className: 'CoreUserAdminController', create: async (dtp) => { return new CoreUserAdminController(dtp); }, diff --git a/app/controllers/admin/host.js b/app/controllers/admin/host.js index 01638ee..147a50b 100644 --- a/app/controllers/admin/host.js +++ b/app/controllers/admin/host.js @@ -116,7 +116,7 @@ class HostAdminController extends SiteController { } module.exports = { - logId: 'admin:host', + logId: 'ctl:admin:host', index: 'adminHost', className: 'HostAdminController', create: async (dtp) => { return new HostAdminController(dtp); }, diff --git a/app/controllers/admin/image.js b/app/controllers/admin/image.js index 4420c1a..f033683 100644 --- a/app/controllers/admin/image.js +++ b/app/controllers/admin/image.js @@ -114,7 +114,7 @@ class ImageAdminController extends SiteController { } module.exports = { - logId: 'admin:image', + logId: 'ctl:admin:image', index: 'adminImage', className: 'ImageAdminController', create: async (dtp) => { return new ImageAdminController(dtp); }, diff --git a/app/controllers/admin/job-queue.js b/app/controllers/admin/job-queue.js index eeba454..4f43260 100644 --- a/app/controllers/admin/job-queue.js +++ b/app/controllers/admin/job-queue.js @@ -119,7 +119,7 @@ class JobQueueAdminController extends SiteController { } module.exports = { - logId: 'admin:job-queue', + logId: 'ctl:admin:job-queue', index: 'adminJobQueue', className: 'JobQueueAdminController', create: async (dtp) => { return new JobQueueAdminController(dtp); }, diff --git a/app/controllers/admin/log.js b/app/controllers/admin/log.js index 21a7547..311634e 100644 --- a/app/controllers/admin/log.js +++ b/app/controllers/admin/log.js @@ -51,7 +51,7 @@ class LogAdminController extends SiteController { } module.exports = { - logId: 'admin:log', + logId: 'ctl:admin:log', index: 'adminLog', className: 'LogAdminController', create: async (dtp) => { return new LogAdminController(dtp); }, diff --git a/app/controllers/admin/newsletter.js b/app/controllers/admin/newsletter.js index fcad904..ffa1325 100644 --- a/app/controllers/admin/newsletter.js +++ b/app/controllers/admin/newsletter.js @@ -167,7 +167,7 @@ class NewsletterAdminController extends SiteController { } module.exports = { - logId: 'admin:newsletter', + logId: 'ctl:admin:newsletter', index: 'adminNewsletter', className: 'NewsletterAdminController', create: async (dtp) => { return new NewsletterAdminController(dtp); }, diff --git a/app/controllers/admin/newsroom.js b/app/controllers/admin/newsroom.js index f88c885..9cac7af 100644 --- a/app/controllers/admin/newsroom.js +++ b/app/controllers/admin/newsroom.js @@ -158,7 +158,7 @@ class NewsroomAdminController extends SiteController { } module.exports = { - logId: 'admin:newsroom-admin', + logId: 'ctl:admin:newsroom', index: 'adminNewsroomAdmin', className: 'NewsroomAdminController', create: async (dtp) => { return new NewsroomAdminController(dtp); }, diff --git a/app/controllers/admin/otp.js b/app/controllers/admin/otp.js index 0868fbb..e858e66 100644 --- a/app/controllers/admin/otp.js +++ b/app/controllers/admin/otp.js @@ -49,7 +49,7 @@ class OtpAdminController extends SiteController { } module.exports = { - logId: 'admin:otp', + logId: 'ctl:admin:otp', index: 'adminOtp', className: 'OtpAdminController', create: async (dtp) => { return new OtpAdminController(dtp); }, diff --git a/app/controllers/admin/service-node.js b/app/controllers/admin/service-node.js index a277f72..efdef07 100644 --- a/app/controllers/admin/service-node.js +++ b/app/controllers/admin/service-node.js @@ -128,7 +128,7 @@ class ServiceNodeAdminController extends SiteController { } module.exports = { - logId: 'admin:service-node', + logId: 'ctl:admin:service-node', index: 'adminServiceNode', className: 'ServiceNodeAdminController', create: async (dtp) => { return new ServiceNodeAdminController(dtp); }, diff --git a/app/controllers/admin/settings.js b/app/controllers/admin/settings.js index 24b5e35..4ceee53 100644 --- a/app/controllers/admin/settings.js +++ b/app/controllers/admin/settings.js @@ -98,7 +98,7 @@ class SettingsAdminController extends SiteController { } module.exports = { - logId: 'admin:settings', + logId: 'ctl:admin:settings', index: 'adminSettings', className: 'SettingsAdminController', create: async (dtp) => { return new SettingsAdminController(dtp); }, diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index 80fb357..5020140 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -338,7 +338,7 @@ class UserAdminController extends SiteController { } module.exports = { - logId: 'admin:user', + logId: 'ctl:admin:user', index: 'adminUser', className: 'UserAdminController', create: async (dtp) => { return new UserAdminController(dtp); }, diff --git a/app/controllers/hive/kaleidoscope.js b/app/controllers/hive/kaleidoscope.js index 33a826f..0e2eb21 100644 --- a/app/controllers/hive/kaleidoscope.js +++ b/app/controllers/hive/kaleidoscope.js @@ -93,7 +93,7 @@ class HiveKaleidoscopeController extends SiteController { } module.exports = { - logId: 'ctl:hive-kaleidoscope', + logId: 'ctl:hive:kaleidoscope', index: 'hiveKaleidoscope', className: 'HiveKaleidoscopeController', create: async (dtp) => { return new HiveKaleidoscopeController(dtp); }, diff --git a/app/controllers/hive/user.js b/app/controllers/hive/user.js index bbbe862..940a498 100644 --- a/app/controllers/hive/user.js +++ b/app/controllers/hive/user.js @@ -149,7 +149,7 @@ class HiveUserController extends SiteController { } module.exports = { - logId: 'ctl:hive-user', + logId: 'ctl:hive:user', index: 'hiveUser', className: 'HiveUserController', create: async (dtp) => { return new HiveUserController(dtp); }, From f0fde7d9cf21e98b8c9c72688d083557f7dd0e0e Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 05:56:32 -0400 Subject: [PATCH 62/76] component def fix --- app/controllers/admin/announcement.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/announcement.js b/app/controllers/admin/announcement.js index b55a013..86a7106 100644 --- a/app/controllers/admin/announcement.js +++ b/app/controllers/admin/announcement.js @@ -159,7 +159,7 @@ class AnnouncementAdminController extends SiteController { module.exports = { logId: 'ctl:admin:announcement', - index: 'announcement', + index: 'adminAnnouncement', className: 'AnnouncementAdminController', create: async (dtp) => { return new AnnouncementAdminController(dtp); }, }; \ No newline at end of file From 01c940d2f88676855297960705d8a4ec68d16b69 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 06:34:23 -0400 Subject: [PATCH 63/76] client component defs --- client/js/site-admin-app.js | 5 +++-- client/js/site-chat.js | 5 +++-- client/js/site-reactions.js | 7 +++++-- lib/client/js/dtp-display-engine.js | 2 +- lib/client/js/dtp-socket.js | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/client/js/site-admin-app.js b/client/js/site-admin-app.js index 4c65a4b..009d304 100644 --- a/client/js/site-admin-app.js +++ b/client/js/site-admin-app.js @@ -4,7 +4,6 @@ 'use strict'; -const DTP_COMPONENT = { logId: 'site-admin-app', index: 'siteAdminApp', className: 'SiteAdminApp' }; const dtp = window.dtp = window.dtp || { }; const GRID_COLOR = '#a0a0a0'; @@ -27,8 +26,10 @@ import UIkit from 'uikit'; export default class DtpSiteAdminApp extends DtpApp { + static get COMPONENT ( ) { return { logId: 'site-admin-app', index: 'siteAdminApp', className: 'SiteAdminApp' }; } + constructor (user) { - super(DTP_COMPONENT, user); + super(DtpSiteAdminApp.COMPONENT, user); this.log.debug('constructor', 'app instance created'); } diff --git a/client/js/site-chat.js b/client/js/site-chat.js index aa06147..00a5874 100644 --- a/client/js/site-chat.js +++ b/client/js/site-chat.js @@ -4,7 +4,6 @@ 'use strict'; -const DTP_COMPONENT = { logId: 'site-chat', index: 'siteChat', className: 'DtpSiteChat' }; const dtp = window.dtp = window.dtp || { }; // jshint ignore:line const EMOJI_EXPLOSION_DURATION = 8000; @@ -17,9 +16,11 @@ import * as picmo from 'picmo'; export default class SiteChat { + static get COMPONENT ( ) { return { logId: 'site-chat', index: 'siteChat', className: 'DtpSiteChat' }; } + constructor (app) { this.app = app; - this.log = new DtpLog(DTP_COMPONENT); + this.log = new DtpLog(SiteChat.COMPONENT); this.ui = { menu: document.querySelector('#chat-room-menu'), diff --git a/client/js/site-reactions.js b/client/js/site-reactions.js index 77da099..0ed58ea 100644 --- a/client/js/site-reactions.js +++ b/client/js/site-reactions.js @@ -4,13 +4,14 @@ 'use strict'; -const DTP_COMPONENT = { logId: 'site-reactions', index: 'siteReactions', className: 'SiteReactions' }; const dtp = window.dtp = window.dtp || { }; // jshint ignore:line import DtpLog from 'dtp/dtp-log'; class Reaction { + static get COMPONENT ( ) { return { logId: 'reaction', index: 'reaction', className: 'Reaction' }; } + constructor (container, reaction) { this.container = container; this.reaction = reaction; @@ -96,8 +97,10 @@ class Reaction { export default class SiteReactions { + static get COMPONENT ( ) { return { logId: 'site-reactions', index: 'siteReactions', className: 'SiteReactions' }; } + constructor ( ) { - this.log = new DtpLog(DTP_COMPONENT); + this.log = new DtpLog(SiteReactions.COMPONENT); this.container = document.querySelector('#chat-reactions'); this.reactions = [ ]; diff --git a/lib/client/js/dtp-display-engine.js b/lib/client/js/dtp-display-engine.js index 18e6a5a..448ff00 100644 --- a/lib/client/js/dtp-display-engine.js +++ b/lib/client/js/dtp-display-engine.js @@ -14,7 +14,7 @@ export default class DtpDisplayEngine { constructor (app) { this.app = app; this.processors = { }; - this.log = new DtpLog(DtpDisplayEngine.DTP_COMPONENT); + this.log = new DtpLog(DtpDisplayEngine.COMPONENT); } /** diff --git a/lib/client/js/dtp-socket.js b/lib/client/js/dtp-socket.js index bddaa12..22c54f8 100644 --- a/lib/client/js/dtp-socket.js +++ b/lib/client/js/dtp-socket.js @@ -16,7 +16,7 @@ export default class DtpWebSocket { this.isConnected = false; this.isAuthenticated = false; this.joinedChannels = { }; - this.log = new DtpWebLog(DtpWebSocket.DTP_COMPONENT); + this.log = new DtpWebLog(DtpWebSocket.COMPONENT); } async connect (options) { From 8635a374a9ddeb9eb5c136098ae6172a45c67cda Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 08:36:01 -0400 Subject: [PATCH 64/76] newsroom updates --- .vscode/launch.json | 21 +++++++++++++++++++++ app/workers/newsroom.js | 23 +++++++++++++++++++++-- lib/site-worker.js | 14 +++++++------- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index ff2e38a..3660a00 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -30,6 +30,27 @@ "console": "integratedTerminal", "args": ["--action=reset-indexes", "all"] }, + { + "type": "node", + "request": "launch", + "name": "worker:newsletter", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder:dtp-base}/app/workers/newsletter.js", + "console": "integratedTerminal", + }, + { + "type": "node", + "request": "launch", + "name": "worker:newsroom", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder:dtp-base}/app/workers/newsroom.js", + "console": "integratedTerminal", + }, + { "type": "node", "request": "launch", diff --git a/app/workers/newsroom.js b/app/workers/newsroom.js index eaea87d..abf9f9c 100644 --- a/app/workers/newsroom.js +++ b/app/workers/newsroom.js @@ -9,6 +9,8 @@ const path = require('path'); require('dotenv').config({ path: path.resolve(__dirname, '..', '..', '.env') }); const mongoose = require('mongoose'); +const moment = require('moment'); + const { read: feedReader } = require('feed-reader'); const { @@ -53,13 +55,30 @@ class NewsroomWorker extends SiteWorker { const NOW = new Date(); const { feed: feedService } = this.dtp.services; try { - this.log.info('loading latest feed data', { feedId: feed._id, title: feed.title }); + this.log.info('loading latest feed data', { + feed: { + _id: feed._id, + title: feed.title, + published: { + date: feed.published, + moment: moment(feed.published).fromNow(), + }, + }, + }); + const response = await feedReader(feed.url); await SiteAsync.each(response.entries, async (entry) => { await Feed.updateOne({ _id: feed._id }, { $set: { published: feed.published || NOW }}); await feedService.createEntry(feed, entry); }, 4); - this.log.info('feed updated', { entries: response.entries.length }); + + this.log.info('feed updated', { + feed: { + _id: feed._id, + title: feed.title, + }, + entryCount: response.entries.length, + }); } catch (error) { this.log.error('failed to update feed', { feedId: feed._id, title: feed.title, error }); } diff --git a/lib/site-worker.js b/lib/site-worker.js index 30a3b88..7acd36d 100644 --- a/lib/site-worker.js +++ b/lib/site-worker.js @@ -71,7 +71,7 @@ class SiteWorker extends SiteCommon { const { COMPONENT } = ProcessorClass; this.log.info('loading worker processor', { component: COMPONENT.logId }); - this.processors[COMPONENT.name] = processor; + this.processors[COMPONENT.index] = processor; return processor; } @@ -83,20 +83,20 @@ class SiteWorker extends SiteCommon { */ async startProcessors ( ) { const slugs = Object.keys(this.processors); - await SiteAsync.each(slugs, async (slug) => { + for (const slug of slugs) { const processor = this.processors[slug]; try { this.log.info('starting worker processor', { - component: processor.component.name, + component: processor.component.logId, }); await processor.start(); } catch (error) { this.log.error('failed to start processor', { - component: processor.component.name, + component: processor.component.logId, error, }); } - }, 1); + } } /** @@ -108,12 +108,12 @@ class SiteWorker extends SiteCommon { const processor = this.processors[slug]; try { this.log.info('stopping worker processor', { - component: processor.component.name, + component: processor.component.logId, }); await processor.stop(); } catch (error) { this.log.error('failed to stop processor', { - component: processor.component.name, + component: processor.component.logId, error, }); } From 910a7b3f07a6e64c44be6abc99e74d4f4e24140f Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 17:51:06 -0400 Subject: [PATCH 65/76] update a feed's favicon when fetching the feed --- app/workers/newsroom.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/workers/newsroom.js b/app/workers/newsroom.js index abf9f9c..00e500a 100644 --- a/app/workers/newsroom.js +++ b/app/workers/newsroom.js @@ -55,7 +55,7 @@ class NewsroomWorker extends SiteWorker { const NOW = new Date(); const { feed: feedService } = this.dtp.services; try { - this.log.info('loading latest feed data', { + this.log.info('loading latest feed data and favicon', { feed: { _id: feed._id, title: feed.title, @@ -66,7 +66,9 @@ class NewsroomWorker extends SiteWorker { }, }); + await feedService.updateFavicon(feed); const response = await feedReader(feed.url); + await SiteAsync.each(response.entries, async (entry) => { await Feed.updateOne({ _id: feed._id }, { $set: { published: feed.published || NOW }}); await feedService.createEntry(feed, entry); From 42ad58e47c311f09c630c157b14dc2998c934ea7 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 24 Jun 2023 20:34:19 -0400 Subject: [PATCH 66/76] `dtp-logan-api` updated to v0.4.1 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b1bd5ea..a56698c 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "disposable-email-provider-domains": "^1.0.9", "dotenv": "^16.0.0", "dtp-jshint-reporter": "git+https://git.digitaltelepresence.com/digital-telepresence/dtp-jshint-reporter.git#master", - "dtp-logan-api": "^0.3.2", + "dtp-logan-api": "^0.4.1", "ein-validator": "^1.0.1", "email-domain-check": "^1.1.4", "email-validator": "^2.0.4", diff --git a/yarn.lock b/yarn.lock index 2d05fad..41b7aef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3125,10 +3125,10 @@ drange@^1.0.2: dependencies: chalk "^4.1.1" -dtp-logan-api@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/dtp-logan-api/-/dtp-logan-api-0.3.2.tgz#354c184ce9ea8a31c57bf0592278f5861fe672d2" - integrity sha512-7mORjmktZY0xpUNecXVLiHvRkBbJxQkjRom2QFzb+5NLQxml2u28cPegINNIlnFKjduXme7a+MQm0msuCmHYtA== +dtp-logan-api@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/dtp-logan-api/-/dtp-logan-api-0.4.1.tgz#407aacb9fef9d2e9902fc28b2adf9f6c426c184d" + integrity sha512-idw0u8M5/Edg5jTnwTv8w3R8TuM0st/MRrrd9xCJoxcA0fE/xtaOZYV8xzJAyX04e17FXjgTNFE4w2aRxIFHww== dependencies: bull "^4.10.4" ioredis "^5.3.2" From 991c240276ff730b9f08b92203463b5c7837f991 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 02:53:57 -0400 Subject: [PATCH 67/76] v0.7.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d3f0a2..9c1f2fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.9", + "version": "0.7.10", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 3c563bcecf7b3c95f219498c0c49effacb8af118 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:32:28 -0400 Subject: [PATCH 68/76] Logan component definitions --- app/controllers/admin/page.js | 10 +++++----- app/controllers/admin/post.js | 10 +++++----- app/controllers/admin/site-link.js | 10 +++++----- app/controllers/admin/venue.js | 10 +++++----- app/controllers/author.js | 10 ++++------ app/controllers/content-report.js | 10 ++++------ app/controllers/feed.js | 5 +++-- app/controllers/page.js | 4 ++-- app/controllers/post.js | 4 ++-- app/controllers/venue.js | 4 ++-- app/services/gab-tv.js | 4 ++-- app/services/page.js | 6 +++--- app/services/post.js | 4 ++-- app/services/site-link.js | 4 ++-- app/services/venue.js | 4 ++-- 15 files changed, 48 insertions(+), 51 deletions(-) diff --git a/app/controllers/admin/page.js b/app/controllers/admin/page.js index 0be4791..bb9ce15 100644 --- a/app/controllers/admin/page.js +++ b/app/controllers/admin/page.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class PageController extends SiteController { +class AdminPageController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -131,8 +131,8 @@ class PageController extends SiteController { } module.exports = { - name: 'adminPage', - slug: 'admin-page', - className: 'PageController', - create: async (dtp) => { return new PageController(dtp); }, + logId: 'ctl:admin:page', + index: 'adminPage', + className: 'AdminPageController', + create: async (dtp) => { return new AdminPageController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/post.js b/app/controllers/admin/post.js index 8aceccf..42478f0 100644 --- a/app/controllers/admin/post.js +++ b/app/controllers/admin/post.js @@ -9,7 +9,7 @@ const multer = require('multer'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class PostController extends SiteController { +class AdminPostController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -136,8 +136,8 @@ class PostController extends SiteController { } module.exports = { - name: 'adminPost', - slug: 'admin-post', - className: 'PostController', - create: async (dtp) => { return new PostController(dtp); }, + logId: 'ctl:admin:post', + index: 'adminPost', + className: 'AdminPostController', + create: async (dtp) => { return new AdminPostController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/site-link.js b/app/controllers/admin/site-link.js index d9b4b07..30db296 100644 --- a/app/controllers/admin/site-link.js +++ b/app/controllers/admin/site-link.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController } = require('../../../lib/site-lib'); -class SiteLinkAdminController extends SiteController { +class AdminSiteLinkController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -103,8 +103,8 @@ class SiteLinkAdminController extends SiteController { } module.exports = { - name: 'adminSiteLink', - slug: 'admin-site-link', - className: 'SiteLinkAdminController', - create: async (dtp) => { return new SiteLinkAdminController(dtp); }, + logId: 'ctl:admin:site-link', + index: 'adminSiteLink', + className: 'AdminSiteLinkController', + create: async (dtp) => { return new AdminSiteLinkController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/venue.js b/app/controllers/admin/venue.js index c76f737..f46e743 100644 --- a/app/controllers/admin/venue.js +++ b/app/controllers/admin/venue.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class VenueAdminController extends SiteController { +class AdminVenueController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -136,8 +136,8 @@ class VenueAdminController extends SiteController { } module.exports = { - name: 'adminVenue', - slug: 'admin-venue', - className: 'VenueAdminController', - create: async (dtp) => { return new VenueAdminController(dtp); }, + logId: 'ctl:admin:venue', + index: 'adminVenue', + className: 'AdminVenueController', + create: async (dtp) => { return new AdminVenueController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/author.js b/app/controllers/author.js index 4c7b732..afa0ce4 100644 --- a/app/controllers/author.js +++ b/app/controllers/author.js @@ -188,10 +188,8 @@ class AuthorController extends SiteController { } module.exports = { - slug: 'author', - name: 'author', - create: async (dtp) => { - let controller = new AuthorController(dtp); - return controller; - }, + logId: 'ctl:author', + index: 'author', + className: 'AuthorController', + create: async (dtp) => { return new AuthorController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/content-report.js b/app/controllers/content-report.js index c9dda1d..7f64d5e 100644 --- a/app/controllers/content-report.js +++ b/app/controllers/content-report.js @@ -100,10 +100,8 @@ class ContentReportController extends SiteController { } module.exports = { - slug: 'content-report', - name: 'contentReport', - create: async (dtp) => { - let controller = new ContentReportController(dtp); - return controller; - }, + logId: 'svc:content-report', + index: 'contentReport', + className: 'ContentReportController', + create: async (dtp) => { return new ContentReportController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/feed.js b/app/controllers/feed.js index cd91977..b269865 100644 --- a/app/controllers/feed.js +++ b/app/controllers/feed.js @@ -86,7 +86,8 @@ class SiteFeedController extends SiteController { } module.exports = { - slug: 'feed', - name: 'feed', + logId: 'ctl:feed', + index: 'feed', + className: 'SiteFeedController', create: async (dtp) => { return new SiteFeedController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/page.js b/app/controllers/page.js index af7f86d..99f7cf0 100644 --- a/app/controllers/page.js +++ b/app/controllers/page.js @@ -88,8 +88,8 @@ class PageController extends SiteController { } module.exports = { - slug: 'page', - name: 'page', + logId: 'ctl:page', + index: 'page', className: 'PageController', create: async (dtp) => { return new PageController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/post.js b/app/controllers/post.js index 606672e..91bb082 100644 --- a/app/controllers/post.js +++ b/app/controllers/post.js @@ -801,8 +801,8 @@ class PostController extends SiteController { } module.exports = { - slug: 'post', - name: 'post', + logId: 'ctl:post', + index: 'post', className: 'PostController', create: async (dtp) => { return new PostController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/venue.js b/app/controllers/venue.js index e5c7b42..289d5b3 100644 --- a/app/controllers/venue.js +++ b/app/controllers/venue.js @@ -107,8 +107,8 @@ class VenueController extends SiteController { } module.exports = { - slug: 'venue', - name: 'venue', + logId: 'ctl:venue', + index: 'venue', className: 'VenueController', create: async (dtp) => { return new VenueController(dtp); }, }; diff --git a/app/services/gab-tv.js b/app/services/gab-tv.js index 5a2a9a9..7d7824c 100644 --- a/app/services/gab-tv.js +++ b/app/services/gab-tv.js @@ -60,8 +60,8 @@ class GabTVService extends SiteService { } module.exports = { - slug: 'gab-tv', - name: 'gabTV', + logId: 'svc:gab-tv', + index: 'gabTV', className: 'GabTVService', create: (dtp) => { return new GabTVService(dtp); }, }; \ No newline at end of file diff --git a/app/services/page.js b/app/services/page.js index b465865..51d8be1 100644 --- a/app/services/page.js +++ b/app/services/page.js @@ -321,8 +321,8 @@ class PageService extends SiteService { module.exports = { - slug: 'page', - name: 'page', + logId: 'svc:page', + index: 'page', className: 'PageService', create: (dtp) => { return new PageService(dtp); }, -}; +}; \ No newline at end of file diff --git a/app/services/post.js b/app/services/post.js index 289b894..782750d 100644 --- a/app/services/post.js +++ b/app/services/post.js @@ -427,8 +427,8 @@ class PostService extends SiteService { } module.exports = { - slug: 'post', - name: 'post', + logId: 'svc:post', + index: 'post', className: 'PostService', create: (dtp) => { return new PostService(dtp); }, }; \ No newline at end of file diff --git a/app/services/site-link.js b/app/services/site-link.js index c3e32b2..f4720a3 100644 --- a/app/services/site-link.js +++ b/app/services/site-link.js @@ -83,8 +83,8 @@ class SiteLinkService extends SiteService { } module.exports = { - slug: 'site-link', - name: 'siteLink', + logId: 'svc:site-link', + index: 'siteLink', className: 'SiteLinkService', create: (dtp) => { return new SiteLinkService(dtp); }, }; \ No newline at end of file diff --git a/app/services/venue.js b/app/services/venue.js index 695e88e..5fce094 100644 --- a/app/services/venue.js +++ b/app/services/venue.js @@ -252,8 +252,8 @@ class VenueService extends SiteService { } module.exports = { - slug: 'venue', - name: 'venue', + logId: 'svc:venue', + index: 'venue', className: 'VenueService', create: (dtp) => { return new VenueService(dtp); }, }; \ No newline at end of file From 8bb37c453e3c15f4a2990c0d16f589a2b0c0c6bf Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:38:59 -0400 Subject: [PATCH 69/76] let's try having one naming convention for child controllers --- app/controllers/admin/announcement.js | 6 +- app/controllers/admin/attachment.js | 6 +- app/controllers/admin/content-report.js | 6 +- app/controllers/admin/core-node.js | 6 +- app/controllers/admin/core-user.js | 6 +- app/controllers/admin/host.js | 6 +- app/controllers/admin/image.js | 6 +- app/controllers/admin/job-queue.js | 6 +- app/controllers/admin/log.js | 6 +- app/controllers/admin/newsletter.js | 6 +- app/controllers/admin/newsroom.js | 6 +- app/controllers/admin/otp.js | 6 +- app/controllers/admin/service-node.js | 6 +- app/controllers/admin/settings.js | 7 +- app/controllers/admin/user.js | 6 +- app/controllers/content-report.js | 107 ++++++++++++++++++++++++ 16 files changed, 152 insertions(+), 46 deletions(-) create mode 100644 app/controllers/content-report.js diff --git a/app/controllers/admin/announcement.js b/app/controllers/admin/announcement.js index 86a7106..30bee40 100644 --- a/app/controllers/admin/announcement.js +++ b/app/controllers/admin/announcement.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController } = require('../../../lib/site-lib'); -class AnnouncementAdminController extends SiteController { +class AdminAnnouncementController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -160,6 +160,6 @@ class AnnouncementAdminController extends SiteController { module.exports = { logId: 'ctl:admin:announcement', index: 'adminAnnouncement', - className: 'AnnouncementAdminController', - create: async (dtp) => { return new AnnouncementAdminController(dtp); }, + className: 'AdminAnnouncementController', + create: async (dtp) => { return new AdminAnnouncementController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/attachment.js b/app/controllers/admin/attachment.js index 688e919..f1c621a 100644 --- a/app/controllers/admin/attachment.js +++ b/app/controllers/admin/attachment.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController } = require('../../../lib/site-lib'); -class AttachmentAdminController extends SiteController { +class AdminAttachmentController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -132,6 +132,6 @@ class AttachmentAdminController extends SiteController { module.exports = { logId: 'ctl:admin:attachment', index: 'adminAttachment', - className: 'AttachmentAdminController', - create: async (dtp) => { return new AttachmentAdminController(dtp); }, + className: 'AdminAttachmentController', + create: async (dtp) => { return new AdminAttachmentController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/content-report.js b/app/controllers/admin/content-report.js index e1c4774..65af3aa 100644 --- a/app/controllers/admin/content-report.js +++ b/app/controllers/admin/content-report.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController } = require('../../../lib/site-lib'); -class ContentReportAdminController extends SiteController { +class AdminContentReportController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -89,6 +89,6 @@ class ContentReportAdminController extends SiteController { module.exports = { logId: 'ctl:admin:content-report', index: 'adminContentReport', - className: 'ContentReportAdminController', - create: async (dtp) => { return new ContentReportAdminController(dtp); }, + className: 'AdminContentReportController', + create: async (dtp) => { return new AdminContentReportController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/core-node.js b/app/controllers/admin/core-node.js index 772eec4..33f7f7c 100644 --- a/app/controllers/admin/core-node.js +++ b/app/controllers/admin/core-node.js @@ -9,7 +9,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class CoreNodeAdminController extends SiteController { +class AdminCoreNodeController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -161,6 +161,6 @@ class CoreNodeAdminController extends SiteController { module.exports = { logId: 'ctl:admin:core-node', index: 'adminCoreNode', - className: 'CoreNodeAdminController', - create: async (dtp) => { return new CoreNodeAdminController(dtp); }, + className: 'AdminCoreNodeController', + create: async (dtp) => { return new AdminCoreNodeController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/core-user.js b/app/controllers/admin/core-user.js index f3c9479..6984833 100644 --- a/app/controllers/admin/core-user.js +++ b/app/controllers/admin/core-user.js @@ -9,7 +9,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class CoreUserAdminController extends SiteController { +class AdminCoreUserController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -90,6 +90,6 @@ class CoreUserAdminController extends SiteController { module.exports = { logId: 'ctl:admin:core-user', index: 'adminCoreUser', - className: 'CoreUserAdminController', - create: async (dtp) => { return new CoreUserAdminController(dtp); }, + className: 'AdminCoreUserController', + create: async (dtp) => { return new AdminCoreUserController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/host.js b/app/controllers/admin/host.js index 147a50b..aff860d 100644 --- a/app/controllers/admin/host.js +++ b/app/controllers/admin/host.js @@ -12,7 +12,7 @@ const NetHostStats = mongoose.model('NetHostStats'); const { /*SiteError,*/ SiteController } = require('../../../lib/site-lib'); -class HostAdminController extends SiteController { +class AdminHostController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -118,6 +118,6 @@ class HostAdminController extends SiteController { module.exports = { logId: 'ctl:admin:host', index: 'adminHost', - className: 'HostAdminController', - create: async (dtp) => { return new HostAdminController(dtp); }, + className: 'AdminHostController', + create: async (dtp) => { return new AdminHostController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/image.js b/app/controllers/admin/image.js index f033683..7bab8c9 100644 --- a/app/controllers/admin/image.js +++ b/app/controllers/admin/image.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class ImageAdminController extends SiteController { +class AdminImageController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -116,6 +116,6 @@ class ImageAdminController extends SiteController { module.exports = { logId: 'ctl:admin:image', index: 'adminImage', - className: 'ImageAdminController', - create: async (dtp) => { return new ImageAdminController(dtp); }, + className: 'AdminImageController', + create: async (dtp) => { return new AdminImageController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/job-queue.js b/app/controllers/admin/job-queue.js index 4f43260..7e3eda3 100644 --- a/app/controllers/admin/job-queue.js +++ b/app/controllers/admin/job-queue.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class JobQueueAdminController extends SiteController { +class AdminJobQueueController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -121,6 +121,6 @@ class JobQueueAdminController extends SiteController { module.exports = { logId: 'ctl:admin:job-queue', index: 'adminJobQueue', - className: 'JobQueueAdminController', - create: async (dtp) => { return new JobQueueAdminController(dtp); }, + className: 'AdminJobQueueController', + create: async (dtp) => { return new AdminJobQueueController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/log.js b/app/controllers/admin/log.js index 311634e..8648cdb 100644 --- a/app/controllers/admin/log.js +++ b/app/controllers/admin/log.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController } = require('../../../lib/site-lib'); -class LogAdminController extends SiteController { +class AdminLogController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -53,6 +53,6 @@ class LogAdminController extends SiteController { module.exports = { logId: 'ctl:admin:log', index: 'adminLog', - className: 'LogAdminController', - create: async (dtp) => { return new LogAdminController(dtp); }, + className: 'AdminLogController', + create: async (dtp) => { return new AdminLogController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/newsletter.js b/app/controllers/admin/newsletter.js index ffa1325..e8a9152 100644 --- a/app/controllers/admin/newsletter.js +++ b/app/controllers/admin/newsletter.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class NewsletterAdminController extends SiteController { +class AdminNewsletterController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -169,6 +169,6 @@ class NewsletterAdminController extends SiteController { module.exports = { logId: 'ctl:admin:newsletter', index: 'adminNewsletter', - className: 'NewsletterAdminController', - create: async (dtp) => { return new NewsletterAdminController(dtp); }, + className: 'AdminNewsletterController', + create: async (dtp) => { return new AdminNewsletterController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/newsroom.js b/app/controllers/admin/newsroom.js index 9cac7af..dfa7909 100644 --- a/app/controllers/admin/newsroom.js +++ b/app/controllers/admin/newsroom.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class NewsroomAdminController extends SiteController { +class AdminNewsroomController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -160,6 +160,6 @@ class NewsroomAdminController extends SiteController { module.exports = { logId: 'ctl:admin:newsroom', index: 'adminNewsroomAdmin', - className: 'NewsroomAdminController', - create: async (dtp) => { return new NewsroomAdminController(dtp); }, + className: 'AdminNewsroomController', + create: async (dtp) => { return new AdminNewsroomController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/otp.js b/app/controllers/admin/otp.js index e858e66..139b903 100644 --- a/app/controllers/admin/otp.js +++ b/app/controllers/admin/otp.js @@ -9,7 +9,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class OtpAdminController extends SiteController { +class AdminOtpController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -51,6 +51,6 @@ class OtpAdminController extends SiteController { module.exports = { logId: 'ctl:admin:otp', index: 'adminOtp', - className: 'OtpAdminController', - create: async (dtp) => { return new OtpAdminController(dtp); }, + className: 'AdminOtpController', + create: async (dtp) => { return new AdminOtpController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/service-node.js b/app/controllers/admin/service-node.js index efdef07..2958ac3 100644 --- a/app/controllers/admin/service-node.js +++ b/app/controllers/admin/service-node.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class ServiceNodeAdminController extends SiteController { +class AdminServiceNodeController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -130,6 +130,6 @@ class ServiceNodeAdminController extends SiteController { module.exports = { logId: 'ctl:admin:service-node', index: 'adminServiceNode', - className: 'ServiceNodeAdminController', - create: async (dtp) => { return new ServiceNodeAdminController(dtp); }, + className: 'AdminServiceNodeController', + create: async (dtp) => { return new AdminServiceNodeController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/settings.js b/app/controllers/admin/settings.js index 4ceee53..09b0925 100644 --- a/app/controllers/admin/settings.js +++ b/app/controllers/admin/settings.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController } = require('../../../lib/site-lib'); -class SettingsAdminController extends SiteController { +class AdminSettingsController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -94,12 +94,11 @@ class SettingsAdminController extends SiteController { }); } } - } module.exports = { logId: 'ctl:admin:settings', index: 'adminSettings', - className: 'SettingsAdminController', - create: async (dtp) => { return new SettingsAdminController(dtp); }, + className: 'AdminSettingsController', + create: async (dtp) => { return new AdminSettingsController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/admin/user.js b/app/controllers/admin/user.js index 5020140..3545f43 100644 --- a/app/controllers/admin/user.js +++ b/app/controllers/admin/user.js @@ -8,7 +8,7 @@ const express = require('express'); const { SiteController, SiteError } = require('../../../lib/site-lib'); -class UserAdminController extends SiteController { +class AdminUserController extends SiteController { constructor (dtp) { super(dtp, module.exports); @@ -340,6 +340,6 @@ class UserAdminController extends SiteController { module.exports = { logId: 'ctl:admin:user', index: 'adminUser', - className: 'UserAdminController', - create: async (dtp) => { return new UserAdminController(dtp); }, + className: 'AdminUserController', + create: async (dtp) => { return new AdminUserController(dtp); }, }; \ No newline at end of file diff --git a/app/controllers/content-report.js b/app/controllers/content-report.js new file mode 100644 index 0000000..7f64d5e --- /dev/null +++ b/app/controllers/content-report.js @@ -0,0 +1,107 @@ +// content-report.js +// Copyright (C) 2021 Digital Telepresence, LLC +// License: Apache-2.0 + +'use strict'; + +const express = require('express'); +const multer = require('multer'); + +const { SiteController } = require('../../lib/site-lib'); + +class ContentReportController extends SiteController { + + constructor (dtp) { + super(dtp, module.exports); + } + + async start ( ) { + const { dtp } = this; + const { limiter: limiterService, session: sessionService } = dtp.services; + + const authRequired = sessionService.authCheckMiddleware({ requiredLogin: true }); + const upload = multer({ dest: `/tmp/${this.dtp.config.site.domainKey}/uploads` }); + + const router = express.Router(); + dtp.app.use('/content-report', router); + + router.use(async (req, res, next) => { + res.locals.currentView = 'content-report'; + return next(); + }); + + router.post('/comment/form', + limiterService.createMiddleware(limiterService.config.contentReport.postCommentReportForm), + authRequired, + upload.none(), + this.postCommentReportForm.bind(this), + ); + router.post('/comment', + limiterService.createMiddleware(limiterService.config.contentReport.postCommentReport), + authRequired, + upload.none(), + this.postCommentReport.bind(this), + ); + } + + async postCommentReportForm (req, res, next) { + const { comment: commentService } = this.dtp.services; + try { + res.locals.comment = await commentService.getById(req.body.commentId); + res.locals.params = req.body; + res.render('comment/components/report-form'); + } catch (error) { + return next(error); + } + } + + async postCommentReport (req, res) { + const { + contentReport: contentReportService, + comment: commentService, + user: userService, + } = this.dtp.services; + + const displayList = this.createDisplayList('add-recipient'); + + try { + res.locals.report = await contentReportService.create(req.user, { + resourceType: 'Comment', + resourceId: req.body.commentId, + category: req.body.category, + reason: req.body.reason, + }); + displayList.showNotification('Comment reported successfully', 'success', 'bottom-center', 5000); + + if (req.body.blockAuthor === 'on') { + const comment = await commentService.getById(req.body.commentId); + await userService.blockUser(req.user._id, comment.author._id || comment.author); + displayList.showNotification('Comment author blocked successfully', 'success', 'bottom-center', 5000); + } + + res.status(200).json({ success: true, displayList }); + } catch (error) { + this.log.error('failed to post comment report', { error }); + if (error.code === 11000) { + displayList.showNotification( + 'You already reported this comment', + 'primary', + 'bottom-center', + 5000, + ); + return res.status(200).json({ success: true, displayList }); + } + return res.status(error.statusCode || 500).json({ + success: false, + message: error.message, + }); + } + } +} + +module.exports = { + logId: 'svc:content-report', + index: 'contentReport', + className: 'ContentReportController', + create: async (dtp) => { return new ContentReportController(dtp); }, +}; \ No newline at end of file From fb6affa19c5f8cc7e8699529943985976ad71da2 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:39:18 -0400 Subject: [PATCH 70/76] v0.8.23 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a56698c..1337b88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.22", + "version": "0.8.23", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From c301952c0ce968fb93aee74d82741f8c55ae0622 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:42:37 -0400 Subject: [PATCH 71/76] v0.7.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e015477..b89edbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.10", + "version": "0.7.11", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From 9864cd91ab315bd9e652694d7a9481a0d0906de4 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:50:13 -0400 Subject: [PATCH 72/76] Logan API updated --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1337b88..f8dae35 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "disposable-email-provider-domains": "^1.0.9", "dotenv": "^16.0.0", "dtp-jshint-reporter": "git+https://git.digitaltelepresence.com/digital-telepresence/dtp-jshint-reporter.git#master", - "dtp-logan-api": "^0.4.1", + "dtp-logan-api": "^0.4.3", "ein-validator": "^1.0.1", "email-domain-check": "^1.1.4", "email-validator": "^2.0.4", diff --git a/yarn.lock b/yarn.lock index 41b7aef..3ce218e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3125,10 +3125,10 @@ drange@^1.0.2: dependencies: chalk "^4.1.1" -dtp-logan-api@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/dtp-logan-api/-/dtp-logan-api-0.4.1.tgz#407aacb9fef9d2e9902fc28b2adf9f6c426c184d" - integrity sha512-idw0u8M5/Edg5jTnwTv8w3R8TuM0st/MRrrd9xCJoxcA0fE/xtaOZYV8xzJAyX04e17FXjgTNFE4w2aRxIFHww== +dtp-logan-api@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/dtp-logan-api/-/dtp-logan-api-0.4.3.tgz#4f5f748d78c0f2673b23a08f2476d815ccfb01ee" + integrity sha512-QNR3/l33SokZh9TVKqbITv1zPwM+G01Ef2EVo54QxRD541nsDLvsQ4wMGHLfgjzESG7h9ncuA7XKuqdO7Be3gg== dependencies: bull "^4.10.4" ioredis "^5.3.2" From 5e4a36004ba1b9b0f633d5f8793a283608044039 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:50:21 -0400 Subject: [PATCH 73/76] v0.8.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8dae35..3071750 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-base", - "version": "0.8.23", + "version": "0.8.24", "description": "Open source web app engine for the Digital Telepresence Platform.", "main": "dtp-webapp.js", "author": "DTP Technologies, LLC", From cfc4571b7900f550edea2a72c1192c87ef167b41 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 4 Jul 2023 03:52:30 -0400 Subject: [PATCH 74/76] v0.7.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0bbdff..d8be760 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.11", + "version": "0.7.12", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC", From b2fdd1f61770cd77d453b528a67019e5f5462453 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 15 Jul 2023 17:35:57 -0400 Subject: [PATCH 75/76] fix for adding Venue channels --- app/services/venue.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/venue.js b/app/services/venue.js index 5fce094..6f72735 100644 --- a/app/services/venue.js +++ b/app/services/venue.js @@ -92,12 +92,13 @@ class VenueService extends SiteService { widgetKey: channelDefinition['credentials.widgetKey'].trim(), }; + const status = await this.updateChannelStatus(channel); channel.name = status.name; channel.description = status.description; await channel.save(); - channel.currentStatus = await this.updateChannelStatus(channel); + channel.currentStatus = status; return channel.toObject(); } From 2056e247b5c2c95f11f3d59c6a2df145eafbaf26 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 15 Jul 2023 17:36:07 -0400 Subject: [PATCH 76/76] v0.7.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8be760..ee14364 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dtp-sites", - "version": "0.7.12", + "version": "0.7.13", "description": "Open source blogging engine for the Digital Telepresence Platform.", "main": "dtp-sites.js", "author": "DTP Technologies, LLC",