From 637d0fb03b07c20447fa3e5958951d2eee8702d9 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 25 Aug 2022 00:41:32 -0400 Subject: [PATCH] Added ability to delete an OAuth2Client (Service Node) --- app/controllers/admin/service-node.js | 19 +++++++++++++++++++ app/services/oauth2.js | 9 +++++++++ app/views/admin/service-node/editor.pug | 19 +++++++++++++++++-- client/js/site-admin-app.js | 20 ++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/service-node.js b/app/controllers/admin/service-node.js index c644026..26f8c06 100644 --- a/app/controllers/admin/service-node.js +++ b/app/controllers/admin/service-node.js @@ -32,6 +32,8 @@ class ServiceNodeController extends SiteController { router.get('/:clientId', this.getClientView.bind(this)); router.get('/', this.getIndex.bind(this)); + router.delete('/:clientId', this.deleteClient.bind(this)); + return router; } @@ -106,6 +108,23 @@ class ServiceNodeController extends SiteController { return next(error); } } + + async deleteClient (req, res) { + const { oauth2: oauth2Service } = this.dtp.services; + try { + await oauth2Service.removeClient(res.locals.serviceNode); + + const displayList = this.createDisplayList('delete-newsletter'); + displayList.navigateTo('/admin/service-node'); + res.status(200).json({ success: true, displayList }); + } catch (error) { + this.log.error('failed to delete client', { clientId: res.locals.serviceNode._id, error }); + return res.status(error.statusCode || 500).json({ + success: false, + message: error.message, + }); + } + } } module.exports = { diff --git a/app/services/oauth2.js b/app/services/oauth2.js index ec8532f..2e886b8 100644 --- a/app/services/oauth2.js +++ b/app/services/oauth2.js @@ -458,6 +458,15 @@ class OAuth2Service extends SiteService { */ return done(null, client); } + + /** + * Removes and fully de-authorizes an OAuth2Client from the system. + * @param {OAuth2Client} client the client to be removed + */ + async removeClient (client) { + this.log.info('removing client', { clientId: client._id, }); + await OAuth2Client.deleteOne({ _id: client._id }); + } } module.exports = { diff --git a/app/views/admin/service-node/editor.pug b/app/views/admin/service-node/editor.pug index f309898..21a09d7 100644 --- a/app/views/admin/service-node/editor.pug +++ b/app/views/admin/service-node/editor.pug @@ -18,15 +18,30 @@ block content .uk-margin label(for="notes").uk-form-label Notes - textarea(id="notes", name="notes", rows="4", placeholder="Enter client notes").uk-textarea= serviceNode.admin.notes + textarea(id="notes", name="notes", rows="4", placeholder="Enter client notes").uk-textarea= (serviceNode.admin && serviceNode.admin.notes) ? serviceNode.admin.notes : undefined .uk-margin label(for="is-active") input(id="is-active", name="isActive", type="checkbox", checked= serviceNode.flags.isActive).uk-checkbox span.uk-margin-small-left Is Active + .uk-card-footer div(uk-grid).uk-grid-small .uk-width-expand +renderBackButton() + + .uk-width-auto + button( + type="button", + data-service-node-id= serviceNode._id, + onclick="return dtp.adminApp.deleteServiceNode(event);" + ).uk-button.uk-button-danger.uk-border-rounded + span + i.fas.fa-trash + span.uk-margin-small-left Delete + .uk-width-auto - button(type="submit").uk-button.uk-button-primary Save \ No newline at end of file + button(type="submit").uk-button.uk-button-primary.uk-border-rounded + span + i.fas.fa-save + span.uk-margin-small-left Save \ No newline at end of file diff --git a/client/js/site-admin-app.js b/client/js/site-admin-app.js index 6786430..57a1eb7 100644 --- a/client/js/site-admin-app.js +++ b/client/js/site-admin-app.js @@ -324,6 +324,26 @@ export default class DtpSiteAdminHostStatsApp extends DtpApp { UIkit.modal.alert(`Failed to send Core Connect response: ${error.message}`); } } + + async deleteServiceNode (event) { + const target = event.currentTarget || event.target; + const serviceNodeId = target.getAttribute('data-service-node-id'); + try { + await UIkit.modal.confirm('Are you sure you want to delete the Service Node?'); + } catch (error) { + return; // user cancel + } + try { + const actionUrl = `/admin/service-node/${serviceNodeId}`; + const response = await fetch(actionUrl, { method: 'DELETE' }); + if (!response.ok) { + throw new Error('Server error'); + } + await this.processResponse(response); + } catch (error) { + UIkit.modal.alert(`Failed to delete Service Node: ${error.message}`); + } + } } dtp.DtpSiteAdminHostStatsApp = DtpSiteAdminHostStatsApp; \ No newline at end of file