diff --git a/app/controllers/home.js b/app/controllers/home.js index e4d4ec8..8246d33 100644 --- a/app/controllers/home.js +++ b/app/controllers/home.js @@ -30,6 +30,8 @@ class HomeController extends SiteController { return next(); }); + router.post('/link', this.postCreateLink.bind(this)); + router.get('/:username', limiterService.create(limiterService.config.home.getPublicProfile), this.getPublicProfile.bind(this), @@ -52,6 +54,17 @@ class HomeController extends SiteController { } } + async postCreateLink (req, res, next) { + const { link: linkService } = this.dtp.services; + try { + res.locals.link = await linkService.create(req.user, req.body); + res.redirect('/'); + } catch (error) { + this.log.error('failed to create link', { error }); + return next(error); + } + } + async getPublicProfile (req, res, next) { const { link: linkService } = this.dtp.services; try { @@ -70,9 +83,11 @@ class HomeController extends SiteController { } async getHome (req, res, next) { + const { link: linkService } = this.dtp.services; try { res.locals.pagination = this.getPaginationParameters(req, 20); if (req.user) { + res.locals.links = await linkService.getForUser(req.user, res.locals.pagination); res.render('index-logged-in'); } else { res.render('index'); diff --git a/app/services/user.js b/app/services/user.js index 8051f82..d1698b8 100644 --- a/app/services/user.js +++ b/app/services/user.js @@ -47,6 +47,7 @@ class UserService { // strip characters we don't want to allow in username userDefinition.username = userDefinition.username.trim().replace(/[^A-Za-z0-9\-_]/gi, ''); const username_lc = userDefinition.username.toLowerCase(); + this.checkUsername(username_lc); // test the email address for validity, blacklisting, etc. await mailService.checkEmailAddress(userDefinition.email); @@ -72,6 +73,9 @@ class UserService { user.email = userDefinition.email; user.username = userDefinition.username; user.username_lc = username_lc; + if (userDefinition.displayName) { + user.displayName = striptags(userDefinition.displayName.trim()); + } user.passwordSalt = passwordSalt; user.password = maskedPassword; @@ -386,6 +390,28 @@ class UserService { return false; } + + checkUsername (username) { + if (!username || (typeof username !== 'string') || (username.length === 0)) { + throw new SiteError(406, 'Invalid username'); + } + const reservedNames = [ + 'admin', + 'auth', + 'dist', + 'fonts', + 'img', + 'image', + 'less', + 'manifest.json', + 'newsletter', + 'user', + 'welcome', + ]; + if (reservedNames.includes(username.trim().toLowerCase())) { + throw new SiteError(403, 'That username is reserved for system use'); + } + } } module.exports = { diff --git a/app/views/index-logged-in.pug b/app/views/index-logged-in.pug index 835d787..d977e17 100644 --- a/app/views/index-logged-in.pug +++ b/app/views/index-logged-in.pug @@ -4,4 +4,33 @@ block content section.uk-section.uk-section-default .uk-container.uk-container-expand .uk-margin - +renderSectionTitle('My Links', { url: `/${user.username}`, label: 'My profile' }) + div(uk-grid).uk-grid-small + .uk-width-expand + h3.uk-heading-bullet.uk-margin-small Your links + .uk-width-auto + button(type="button", uk-toggle={ target: '#link-editor' }).uk-button.dtp-button-primary.uk-button-small Add Link + + .uk-margin + #link-editor(hidden).uk-card.uk-card-secondary.uk-card-small + .uk-card-body + form(method="POST", action="/link").uk-form + .uk-margin + label(for="label").uk-form-label Label + input(id="label", name="label", type="text", placeholder="Enter link label/title").uk-input + .uk-margin + label(for="href").uk-form-label URL + input(id="href", name="href", type="text", placeholder="Enter link URL").uk-input + div(uk-grid).uk-grid-small + .uk-width-auto + button(type="button", uk-toggle={ target: '#link-editor' }).uk-button.dtp-button-default Cancel + .uk-width-auto + button(type="submit").uk-button.dtp-button-primary Add link + + .uk-margin + if Array.isArray(links) && (links.length > 0) + ul.uk-list + each link in links + li + a(href= link.href).uk-button.dtp-button-primary.uk-display-block= link.label + else + div You have no links. \ No newline at end of file diff --git a/app/views/layouts/public-profile.pug b/app/views/layouts/public-profile.pug index 0e0cb8d..2d65ef4 100644 --- a/app/views/layouts/public-profile.pug +++ b/app/views/layouts/public-profile.pug @@ -3,12 +3,12 @@ extends main block content-container section.uk-section.uk-section-default .uk-container - div(uk-grid) - .uk-width-1-3 - .uk-margin + div(uk-grid).uk-grid-small + div(class="uk-width-1-1 uk-width-auto@m") + .uk-width-small.uk-margin.uk-margin-auto img(src="/img/default-member.png").site-profile-picture - .uk-width-expand + div(class="uk-width-1-1 uk-width-expand@m") block content block page-footer diff --git a/app/views/profile/home.pug b/app/views/profile/home.pug index c21af2d..1a39f08 100644 --- a/app/views/profile/home.pug +++ b/app/views/profile/home.pug @@ -1,11 +1,15 @@ extends ../layouts/public-profile block content - .uk-margin - +renderSectionTitle(`${userProfile.displayName || userProfile.username}'s links`) + .uk-margin.uk-text-center + h1= userProfile.displayName || userProfile.username .uk-margin ul.uk-list each link in links li - a(href= link.href).uk-button.dtp-button-primary.uk-display-block.uk-border-rounded= link.label \ No newline at end of file + a(href= link.href).uk-button.dtp-button-primary.uk-display-block.uk-border-rounded= link.label + +block dtp-navbar +block dtp-off-canvas +block view-title \ No newline at end of file