Browse Source

Merge branch 'develop' of git.digitaltelepresence.com:digital-telepresence/dtp-base into develop

develop
Andrew Woodlee 2 years ago
parent
commit
47189dd9a7
  1. 8
      app/controllers/home.js
  2. 31
      app/controllers/user.js
  3. 11
      app/services/feed.js
  4. 22
      app/services/user.js
  5. 5
      app/views/admin/layouts/main.pug
  6. 8
      app/views/components/library.pug
  7. 2
      app/views/components/navbar.pug
  8. 2
      app/views/components/off-canvas.pug
  9. 2
      app/views/layouts/main-sidebar.pug
  10. 10
      app/views/newsroom/components/feed-entry-list-item.pug
  11. 7
      client/less/site/main.less
  12. 6
      dtp-webapp.js
  13. 7
      lib/site-common.js

8
app/controllers/home.js

@ -63,19 +63,13 @@ class HomeController extends SiteController {
} }
async getHome (req, res, next) { async getHome (req, res, next) {
const { const { announcement: announcementService, hive: hiveService } = this.dtp.services;
announcement: announcementService,
feed: feedService,
hive: hiveService,
} = this.dtp.services;
try { try {
res.locals.announcements = await announcementService.getLatest(req.user); res.locals.announcements = await announcementService.getLatest(req.user);
res.locals.pagination = this.getPaginationParameters(req, 20); res.locals.pagination = this.getPaginationParameters(req, 20);
res.locals.constellationTimeline = await hiveService.getConstellationTimeline(req.user, res.locals.pagination); res.locals.constellationTimeline = await hiveService.getConstellationTimeline(req.user, res.locals.pagination);
res.locals.newsfeed = await feedService.getNewsfeed();
res.render('index'); res.render('index');
} catch (error) { } catch (error) {
this.log.error('failed to render home view', { error }); this.log.error('failed to render home view', { error });

31
app/controllers/user.js

@ -33,12 +33,12 @@ class UserController extends SiteController {
const otpSetup = otpAuthService.middleware('Account', { const otpSetup = otpAuthService.middleware('Account', {
adminRequired: false, adminRequired: false,
otpRequired: true, otpRequired: true,
otpRedirectURL: async (req) => { return `/user/${req.user._id}`; }, otpRedirectURL: async (req) => { return `/user/${req.user.username}`; },
}); });
const otpMiddleware = otpAuthService.middleware('Account', { const otpMiddleware = otpAuthService.middleware('Account', {
adminRequired: false, adminRequired: false,
otpRequired: false, otpRequired: false,
otpRedirectURL: async (req) => { return `/user/${req.user._id}`; }, otpRedirectURL: async (req) => { return `/user/${req.user.username}`; },
}); });
router.use( router.use(
@ -60,8 +60,9 @@ class UserController extends SiteController {
return next(); return next();
} }
router.param('userId', this.populateUser.bind(this)); router.param('username', this.populateUsername.bind(this));
router.param('coreUserId', this.populateCoreUser.bind(this)); router.param('userId', this.populateUserId.bind(this));
router.param('coreUserId', this.populateCoreUserId.bind(this));
router.post( router.post(
'/core/:coreUserId/settings', '/core/:coreUserId/settings',
@ -131,7 +132,7 @@ class UserController extends SiteController {
this.getUserSettingsView.bind(this), this.getUserSettingsView.bind(this),
); );
router.get( router.get(
'/:userId', '/:username',
limiterService.createMiddleware(limiterService.config.user.getUserProfile), limiterService.createMiddleware(limiterService.config.user.getUserProfile),
authRequired, authRequired,
otpMiddleware, otpMiddleware,
@ -147,7 +148,21 @@ class UserController extends SiteController {
); );
} }
async populateUser (req, res, next, userId) { async populateUsername (req, res, next, username) {
const { user: userService } = this.dtp.services;
try {
res.locals.userProfile = await userService.getPublicProfile('User', username);
if (!res.locals.userProfile) {
throw new SiteError(404, 'Member not found');
}
return next();
} catch (error) {
this.log.error('failed to populate username with public profile', { username, error });
return next(error);
}
}
async populateUserId (req, res, next, userId) {
const { user: userService } = this.dtp.services; const { user: userService } = this.dtp.services;
try { try {
userId = mongoose.Types.ObjectId(userId); userId = mongoose.Types.ObjectId(userId);
@ -163,7 +178,7 @@ class UserController extends SiteController {
} }
} }
async populateCoreUser (req, res, next, coreUserId) { async populateCoreUserId (req, res, next, coreUserId) {
const { coreNode: coreNodeService } = this.dtp.services; const { coreNode: coreNodeService } = this.dtp.services;
try { try {
coreUserId = mongoose.Types.ObjectId(coreUserId); coreUserId = mongoose.Types.ObjectId(coreUserId);
@ -203,7 +218,7 @@ class UserController extends SiteController {
if (error) { if (error) {
return next(error); return next(error);
} }
res.redirect(`/user/${res.locals.user._id}`); res.redirect(`/user/${res.locals.user.username}`);
}); });
} catch (error) { } catch (error) {
this.log.error('failed to create new user', { error }); this.log.error('failed to create new user', { error });

11
app/services/feed.js

@ -27,6 +27,17 @@ class FeedService extends SiteService {
this.jobQueue = await this.getJobQueue('newsroom', this.dtp.config.jobQueues.newsroom); this.jobQueue = await this.getJobQueue('newsroom', this.dtp.config.jobQueues.newsroom);
} }
middleware (options) {
options = Object.assign({ maxEntryCount: 5 }, options);
return async (req, res, next) => {
if (this.isSystemRoute(req.path)) {
return next(); // don't load newsfeeds for non-content routes
}
res.locals.newsfeed = await this.getNewsfeed({ skip: 0, cpp: options.maxEntryCount });
return next();
};
}
async create (feedDefinition) { async create (feedDefinition) {
feedDefinition.url = feedDefinition.url.trim(); feedDefinition.url = feedDefinition.url.trim();
const feedContent = await this.load(feedDefinition.url); const feedContent = await this.load(feedDefinition.url);

22
app/services/user.js

@ -459,7 +459,7 @@ class UserService extends SiteService {
return user; return user;
} }
async getPublicProfile (username) { async getPublicProfile (type, username) {
if (!username || (typeof username !== 'string')) { if (!username || (typeof username !== 'string')) {
throw new SiteError(406, 'Invalid username'); throw new SiteError(406, 'Invalid username');
} }
@ -469,20 +469,20 @@ class UserService extends SiteService {
throw new SiteError(406, 'Invalid username'); throw new SiteError(406, 'Invalid username');
} }
/** let user;
* Try to resolve the user as a CoreUser switch (type) {
*/ case 'CoreUser':
let user = await CoreUser user = await CoreUser
.findOne({ username_lc: username }) .findOne({ username_lc: username })
.select('_id created username username_lc displayName bio picture header core') .select('_id created username username_lc displayName bio picture header core')
.populate(this.populateUser) .populate(this.populateUser)
.lean(); .lean();
if (user) { if (user) {
user.type = 'CoreUser'; user.type = 'CoreUser';
} else { }
/* break;
* Try to resolve the user as a local User
*/ case 'User':
user = await User user = await User
.findOne({ username_lc: username }) .findOne({ username_lc: username })
.select('_id created username username_lc displayName bio picture header') .select('_id created username username_lc displayName bio picture header')
@ -491,6 +491,10 @@ class UserService extends SiteService {
if (user) { if (user) {
user.type = 'User'; user.type = 'User';
} }
break;
default:
throw new SiteError(400, 'Invalid user account type');
} }
return user; return user;

5
app/views/admin/layouts/main.pug

@ -4,11 +4,6 @@ block vendorcss
block content-container block content-container
block page-header
section.uk-section.uk-section-header.uk-section-xsmall
.uk-container
h1.uk-text-center.uk-margin-remove #{site.name} Admin
block admin-layout block admin-layout
section.uk-section.uk-section-default.uk-section-small section.uk-section.uk-section-default.uk-section-small

8
app/views/components/library.pug

@ -40,9 +40,9 @@ include section-title
function getUserProfileUrl (user) { function getUserProfileUrl (user) {
if (user.core) { if (user.core) {
return `/user/core/${user._id}`; return `/user/core/${user.username}`;
} }
return `/user/${user._id}`; return `/user/${user.username}`;
} }
mixin renderCell (label, value, className) mixin renderCell (label, value, className)
@ -60,6 +60,6 @@ mixin renderBackButton (options)
mixin renderUserLink (user) mixin renderUserLink (user)
if user.coreUserId if user.coreUserId
a(href=`/user/core/${user._id}`)= `${user.username}@${user.core.meta.domainKey}` a(href=`/user/core/${user.username}`)= `${user.username}@${user.core.meta.domainKey}`
else else
a(href=`/user/${user._id}`)= user.displayName || user.username a(href=`/user/${user.username}`)= user.displayName || user.username

2
app/views/components/navbar.pug

@ -47,7 +47,7 @@ nav(uk-navbar).uk-navbar-container.uk-position-fixed.uk-position-top
li.uk-nav-heading.uk-text-center= user.displayName || user.username li.uk-nav-heading.uk-text-center= user.displayName || user.username
li.uk-nav-divider li.uk-nav-divider
li li
a(href= user.core ? `/user/core/${user._id}` : `/user/${user._id}`) a(href= user.core ? `/user/core/${user.username}` : `/user/${user.username}`)
span.nav-item-icon span.nav-item-icon
i.fas.fa-user i.fas.fa-user
span Profile span Profile

2
app/views/components/off-canvas.pug

@ -40,7 +40,7 @@ mixin renderMenuItem (iconClass, label)
.uk-width-expand Chat .uk-width-expand Chat
li(class={ "uk-active": (currentView === 'user-settings') }) li(class={ "uk-active": (currentView === 'user-settings') })
a(href=`/user/${user._id}`).uk-display-block a(href=`/user/${user.username}`).uk-display-block
div(uk-grid).uk-grid-collapse div(uk-grid).uk-grid-collapse
.uk-width-auto .uk-width-auto
.app-menu-icon .app-menu-icon

2
app/views/layouts/main-sidebar.pug

@ -1,6 +1,8 @@
extends main extends main
block content-container block content-container
block content-header block content-header
section.uk-section.uk-section-default.uk-section-small section.uk-section.uk-section-default.uk-section-small
.uk-container .uk-container
div(uk-grid)#dtp-content-grid div(uk-grid)#dtp-content-grid

10
app/views/newsroom/components/feed-entry-list-item.pug

@ -1,9 +1,9 @@
mixin renderNewsroomFeedEntryListItem (entry) mixin renderNewsroomFeedEntryListItem (entry)
.uk-text-bold a(href= entry.link, target="_blank").dtp-link
a(href= entry.link, target="_blank").uk-link-reset= entry.title div= entry.title
.uk-text-small .uk-article-meta
div(uk-grid).uk-grid-small div(uk-grid).uk-grid-small.uk-grid-divider
.uk-width-expand .uk-width-auto.uk-text-truncate
a(href= entry.feed.link, target="_blank").uk-link-reset= entry.feed.title a(href= entry.feed.link, target="_blank").uk-link-reset= entry.feed.title
.uk-width-auto .uk-width-auto
div= moment(entry.published).fromNow() div= moment(entry.published).fromNow()

7
client/less/site/main.less

@ -50,6 +50,13 @@ body {
} }
} }
a.dtp-link {
color: inherit;
&:hover {
color: @global-link-hover-color;
}
}
.dtp-site-footer { .dtp-site-footer {
.uk-subnav { .uk-subnav {
a.dtp-social-link { a.dtp-social-link {

6
dtp-webapp.js

@ -21,12 +21,16 @@ module.config = {
site: require(path.join(module.rootPath, 'config', 'site')), site: require(path.join(module.rootPath, 'config', 'site')),
http: require(path.join(module.rootPath, 'config', 'http')), http: require(path.join(module.rootPath, 'config', 'http')),
https: require(path.join(module.rootPath, 'config', 'https')), https: require(path.join(module.rootPath, 'config', 'https')),
registerMiddleware: async (dtp, app) => {
const { feed: feedService } = dtp.services;
app.use(feedService.middleware({ maxEntryCount: 5 }));
},
}; };
module.log = new SiteLog(module, module.config.component); module.log = new SiteLog(module, module.config.component);
module.shutdown = async ( ) => { module.shutdown = async ( ) => {
await SitePlatform.shutdown();
}; };
(async ( ) => { (async ( ) => {

7
lib/site-common.js

@ -106,6 +106,13 @@ class SiteCommon extends EventEmitter2 {
}); });
} }
isSystemRoute (pathname) {
return pathname.startsWith('/auth') ||
pathname.startsWith('/image') ||
pathname.startsWith('/manifest')
;
}
isValidString (text) { isValidString (text) {
return text && (typeof text === 'string') && (text.length > 0); return text && (typeof text === 'string') && (text.length > 0);
} }

Loading…
Cancel
Save