From 1737a1a5bb3662dba901235479f5ac40ce8f16b8 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 21 Dec 2021 16:14:42 -0500 Subject: [PATCH] switch links to a[href, onclick] --- app/controllers/admin.js | 11 +++++ app/controllers/home.js | 84 ++++++++++++++++++++++++++++++++++++++ app/controllers/link.js | 12 +++--- app/services/user.js | 33 +++++++++------ app/views/profile/home.pug | 7 +++- client/js/site-app.js | 10 +++++ config/limiter.js | 2 +- 7 files changed, 137 insertions(+), 22 deletions(-) diff --git a/app/controllers/admin.js b/app/controllers/admin.js index a735b15..7317bab 100644 --- a/app/controllers/admin.js +++ b/app/controllers/admin.js @@ -51,11 +51,22 @@ class AdminController extends SiteController { router.use('/settings',await this.loadChild(path.join(__dirname, 'admin', 'settings'))); router.use('/user', await this.loadChild(path.join(__dirname, 'admin', 'user'))); + router.get('/diagnostics', this.getDiagnostics.bind(this)); + router.get('/', this.getHomeView.bind(this)); return router; } + async getDiagnostics (req, res) { + res.status(200).json({ + success: true, + url: req.url, + ip: req.ip, + headers: req.headers, + }); + } + async getHomeView (req, res) { const { link: linkService, dashboard: dashboardService } = this.dtp.services; res.locals.stats = { diff --git a/app/controllers/home.js b/app/controllers/home.js index f2ca8ed..905788f 100644 --- a/app/controllers/home.js +++ b/app/controllers/home.js @@ -8,6 +8,8 @@ const DTP_COMPONENT_NAME = 'home'; const express = require('express'); +const moment = require('moment'); + const { SiteController, SiteError } = require('../../lib/site-lib'); class HomeController extends SiteController { @@ -30,6 +32,8 @@ class HomeController extends SiteController { return next(); }); + router.get('/:username/embed', this.getPublicProfileEmbed.bind(this)); + router.get('/:username/json', this.getPublicProfileJSON.bind(this)); router.get('/:username', limiterService.create(limiterService.config.home.getPublicProfile), this.getPublicProfile.bind(this), @@ -53,6 +57,86 @@ class HomeController extends SiteController { } } + async getPublicProfileEmbed (req, res, next) { + const { link: linkService, user: userService } = this.dtp.services; + try { + this.log.debug('profile request', { url: req.url }); + if (!res.locals.userProfile) { + return next(new SiteError(404, 'Member profile not found')); + } + + res.locals.currentView = 'profile-embed'; + + res.locals.pageTitle = `${res.locals.userProfile.displayName || res.locals.userProfile.username} | ${this.dtp.config.site.name}`; + res.locals.pageDescription = res.locals.userProfile.bio || this.dtp.config.site.description; + + res.locals.pagination = this.getPaginationParameters(req, 20); + res.locals.links = await linkService.getForUser(res.locals.userProfile, res.locals.pagination); + + await userService.recordProfileView(res.locals.userProfile, req); + + res.render('profile/embed'); + } catch (error) { + this.log.error('failed to display landing page', { error }); + return next(error); + } + } + + async getPublicProfileJSON (req, res) { + const { link: linkService, user: userService } = this.dtp.services; + try { + this.log.debug('profile request', { url: req.url }); + if (!res.locals.userProfile) { + throw new SiteError(404, 'Member profile not found'); + } + + res.locals.currentView = 'profile-embed'; + + res.locals.pageTitle = `${res.locals.userProfile.displayName || res.locals.userProfile.username} | ${this.dtp.config.site.name}`; + res.locals.pageDescription = res.locals.userProfile.bio || this.dtp.config.site.description; + + res.locals.pagination = this.getPaginationParameters(req, 20); + res.locals.links = await linkService.getForUser(res.locals.userProfile, res.locals.pagination); + + await userService.recordProfileView(res.locals.userProfile, req); + + if (res.locals.userProfile.picture) { + if (res.locals.userProfile.picture.large) { + res.locals.userProfile.picture.large = this.makeSiteLink(`/image/${res.locals.userProfile.picture.large._id}`); + } + if (res.locals.userProfile.picture.small) { + res.locals.userProfile.picture.small = this.makeSiteLink(`/image/${res.locals.userProfile.picture.small._id}`); + } + } + if (res.locals.userProfile.header) { + res.locals.userProfile.header = this.makeSiteLink(`/image/${res.locals.userProfile.header._id}`); + } + + delete res.locals.userProfile._id; + res.locals.userProfile.createdText = moment(res.locals.userProfile.created).fromNow(); + + res.locals.links.forEach((link) => { + link.href = this.makeSiteLink(`/link/${link._id}/visit`); + }); + + res.status(200).json({ + success: true, + user: res.locals.userProfile, + links: res.locals.links, + }); + } catch (error) { + this.log.error('failed to display landing page', { error }); + return res.status(error.statusCode || 500).json({ + success: false, + message: error.message, + }); + } + } + + makeSiteLink (url) { + return `https://${this.dtp.config.site.domain}${url}`; + } + async getPublicProfile (req, res, next) { const { link: linkService, user: userService } = this.dtp.services; try { diff --git a/app/controllers/link.js b/app/controllers/link.js index a8cbf8b..f56d357 100644 --- a/app/controllers/link.js +++ b/app/controllers/link.js @@ -34,11 +34,6 @@ class LinkController extends SiteController { return next(); }); - router.post('/visit/:linkId', - limiterService.create(limiterService.config.link.postCreateLinkVisit), - this.postCreateLinkVisit.bind(this), - ); - router.post('/sort', limiterService.create(limiterService.config.link.postSortLinksList), authRequired, @@ -59,6 +54,11 @@ class LinkController extends SiteController { this.postCreateLink.bind(this), ); + router.get('/:linkId/visit', + limiterService.create(limiterService.config.link.getCreateLinkVisit), + this.getCreateLinkVisit.bind(this), + ); + router.delete('/:linkId', authRequired, this.deleteLink.bind(this)); } @@ -73,7 +73,7 @@ class LinkController extends SiteController { } } - async postCreateLinkVisit (req, res, next) { + async getCreateLinkVisit (req, res, next) { const { resource: resourceService } = this.dtp.services; try { this.log.info('recording link visit', { link: res.locals.link._id, ip: req.ip }); diff --git a/app/services/user.js b/app/services/user.js index d437a71..51ddc00 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -20,6 +20,18 @@ class UserService { constructor (dtp) { this.dtp = dtp; this.log = new SiteLog(dtp, `svc:${module.exports.slug}`); + + this.populateUser = [ + { + path: 'picture.large', + }, + { + path: 'picture.small', + }, + { + path: 'header', + }, + ]; } async start ( ) { @@ -263,17 +275,7 @@ class UserService { const user = await User .findById(userId) .select('+email +flags +permissions') - .populate([ - { - path: 'picture.large', - }, - { - path: 'picture.small', - }, - { - path: 'header', - }, - ]) + .populate(this.populateUser) .lean(); if (!user) { throw new SiteError(404, 'Member account not found'); @@ -305,7 +307,10 @@ class UserService { } catch (error) { user = User.findOne({ username: userId }); } - user = await user.select('+email +flags +settings').lean(); + user = await user + .select('+email +flags +settings') + .populate(this.populateUser) + .lean(); return user; } @@ -316,7 +321,9 @@ class UserService { username = username.trim().toLowerCase(); const user = await User .findOne({ username_lc: username }) - .select('_id created username username_lc displayName bio picture header'); + .select('_id created username username_lc displayName bio picture header') + .populate(this.populateUser) + .lean(); return user; } diff --git a/app/views/profile/home.pug b/app/views/profile/home.pug index 50290f5..1876156 100644 --- a/app/views/profile/home.pug +++ b/app/views/profile/home.pug @@ -5,8 +5,11 @@ block content ul.uk-list each link in links li - form(method="POST", action=`/link/visit/${link._id}`).uk-form.uk-display-block.uk-width-1-1 - button(type="submit").dtp-link-button.uk-display-block.uk-border-rounded.uk-width-1-1= link.label + a( + href= link.href, + data-visit-url= `/link/${link._id}/visit`, + onclick="return dtp.app.visitLink(event);", + ).dtp-link-button.uk-display-block.uk-border-rounded.uk-width-1-1= link.label block dtp-navbar block dtp-off-canvas diff --git a/client/js/site-app.js b/client/js/site-app.js index 0cd378f..b6f044e 100644 --- a/client/js/site-app.js +++ b/client/js/site-app.js @@ -616,6 +616,16 @@ export default class DtpSiteApp extends DtpApp { } } + async visitLink (event) { + event.preventDefault(); + event.stopPropagation(); + + const url = (event.currentTarget || event.target).getAttribute('data-visit-url'); + window.location = url; + + return true; + } + async renderStatsGraph (selector, title, data) { try { const canvas = document.querySelector(selector); diff --git a/config/limiter.js b/config/limiter.js index 7e53fe3..7c349b6 100644 --- a/config/limiter.js +++ b/config/limiter.js @@ -98,7 +98,7 @@ module.exports = { }, link: { - postCreateLinkVisit: { + getCreateLinkVisit: { total: 30, expire: ONE_MINUTE, message: 'You are visiting links too quickly',