From b82c788e5c1a9c3c5fc7c396306d7c2774f5d2fb Mon Sep 17 00:00:00 2001 From: BobbyB Date: Fri, 31 Jan 2020 16:57:35 -0500 Subject: [PATCH] feat: add Page Rules For Matching Tags (#1418) * Added Page Rules For Matching Tags * fix: use T as Tag Match icon * fix: reorder page rules in checkAccess * fix: common controller tags code refactor Co-authored-by: Nicolas Giard --- .../admin/admin-groups-edit-rules.vue | 9 ++-- server/controllers/common.js | 51 +++++++++++-------- server/core/auth.js | 17 +++++-- server/graph/schemas/group.graphql | 1 + 4 files changed, 52 insertions(+), 26 deletions(-) diff --git a/client/components/admin/admin-groups-edit-rules.vue b/client/components/admin/admin-groups-edit-rules.vue index d16a7eff..599911b2 100644 --- a/client/components/admin/admin-groups-edit-rules.vue +++ b/client/components/admin/admin-groups-edit-rules.vue @@ -157,8 +157,8 @@ solo v-model='rule.path' label='Path' - :prefix='rule.match !== `END` ? `/` : null' - :placeholder='rule.match === `REGEX` ? `Regular Expression` : `Path`' + :prefix='(rule.match !== `END` && rule.match !== `TAG`) ? `/` : null' + :placeholder='rule.match === `REGEX` ? `Regular Expression` : rule.match === `TAG` ? `Tag` : `Path`' :suffix='rule.match === `REGEX` ? `/` : null' hide-details :color='$vuetify.theme.dark ? `grey` : `blue-grey`' @@ -181,6 +181,8 @@ strong Path Ends With... li strong Path Matches Regex... + li + strong Tag Matches... li strong Path Is Exactly... em.caption.pl-1 (highest) @@ -222,7 +224,8 @@ export default { { text: 'Path Starts With...', value: 'START', icon: '/...' }, { text: 'Path is Exactly...', value: 'EXACT', icon: '=' }, { text: 'Path Ends With...', value: 'END', icon: '.../' }, - { text: 'Path Matches Regex...', value: 'REGEX', icon: '$.*' } + { text: 'Path Matches Regex...', value: 'REGEX', icon: '$.*' }, + { text: 'Tag Matches...', value: 'TAG', icon: 'T' } ], locales: [ { text: 'English', value: 'en' } diff --git a/server/controllers/common.js b/server/controllers/common.js index 1171d20d..10de9490 100644 --- a/server/controllers/common.js +++ b/server/controllers/common.js @@ -59,6 +59,8 @@ router.get(['/e', '/e/*'], async (req, res, next) => { isPrivate: false }) + pageArgs.tags = _.get(page, 'tags', []) + const injectCode = { css: WIKI.config.theming.injectCSS, head: WIKI.config.theming.injectHead, @@ -109,17 +111,20 @@ router.get(['/h', '/h/*'], async (req, res, next) => { _.set(res, 'locals.siteConfig.lang', pageArgs.locale) - if (!WIKI.auth.checkAccess(req.user, ['read:history'], pageArgs)) { - _.set(res.locals, 'pageMeta.title', 'Unauthorized') - return res.render('unauthorized', { action: 'history' }) - } - const page = await WIKI.models.pages.getPageFromDb({ path: pageArgs.path, locale: pageArgs.locale, userId: req.user.id, isPrivate: false }) + + pageArgs.tags = _.get(page, 'tags', []) + + if (!WIKI.auth.checkAccess(req.user, ['read:history'], pageArgs)) { + _.set(res.locals, 'pageMeta.title', 'Unauthorized') + return res.render('unauthorized', { action: 'history' }) + } + if (page) { _.set(res.locals, 'pageMeta.title', page.title) _.set(res.locals, 'pageMeta.description', page.description) @@ -149,7 +154,8 @@ router.get(['/i', '/i/:id'], async (req, res, next) => { path: page.path, private: page.isPrivate, privateNS: page.privateNS, - explicitLocale: false + explicitLocale: false, + tags: page.tags })) { _.set(res.locals, 'pageMeta.title', 'Unauthorized') return res.render('unauthorized', { action: 'view' }) @@ -175,6 +181,14 @@ router.get(['/p', '/p/*'], (req, res, next) => { */ router.get(['/s', '/s/*'], async (req, res, next) => { const pageArgs = pageHelper.parsePath(req.path, { stripExt: true }) + const page = await WIKI.models.pages.getPageFromDb({ + path: pageArgs.path, + locale: pageArgs.locale, + userId: req.user.id, + isPrivate: false + }) + + pageArgs.tags = _.get(page, 'tags', []) if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) { return res.redirect(`/s/${pageArgs.locale}/${pageArgs.path}`) @@ -186,12 +200,6 @@ router.get(['/s', '/s/*'], async (req, res, next) => { return res.render('unauthorized', { action: 'source' }) } - const page = await WIKI.models.pages.getPageFromDb({ - path: pageArgs.path, - locale: pageArgs.locale, - userId: req.user.id, - isPrivate: false - }) if (page) { _.set(res.locals, 'pageMeta.title', page.title) _.set(res.locals, 'pageMeta.description', page.description) @@ -224,14 +232,6 @@ router.get('/*', async (req, res, next) => { req.i18n.changeLanguage(pageArgs.locale) - if (!WIKI.auth.checkAccess(req.user, ['read:pages'], pageArgs)) { - if (pageArgs.path === 'home') { - return res.redirect('/login') - } - _.set(res.locals, 'pageMeta.title', 'Unauthorized') - return res.status(403).render('unauthorized', { action: 'view' }) - } - try { const page = await WIKI.models.pages.getPage({ path: pageArgs.path, @@ -239,6 +239,17 @@ router.get('/*', async (req, res, next) => { userId: req.user.id, isPrivate: false }) + pageArgs.tags = _.get(page, 'tags', []) + + if (!WIKI.auth.checkAccess(req.user, ['read:pages'], pageArgs)) { + if (pageArgs.path === 'home') { + return res.redirect('/login') + } + _.set(res.locals, 'pageMeta.title', 'Unauthorized') + return res.status(403).render('unauthorized', { + action: 'view' + }) + } _.set(res, 'locals.siteConfig.lang', pageArgs.locale) diff --git a/server/core/auth.js b/server/core/auth.js index ff5ca2ba..3fabe075 100644 --- a/server/core/auth.js +++ b/server/core/auth.js @@ -176,20 +176,31 @@ module.exports = { switch (rule.match) { case 'START': if (_.startsWith(`/${page.path}`, `/${rule.path}`)) { - checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: ['END', 'REGEX', 'EXACT'] }) + checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: ['END', 'REGEX', 'EXACT', 'TAG'] }) } break case 'END': if (_.endsWith(page.path, rule.path)) { - checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: ['REGEX', 'EXACT'] }) + checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: ['REGEX', 'EXACT', 'TAG'] }) } break case 'REGEX': const reg = new RegExp(rule.path) if (reg.test(page.path)) { - checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: ['EXACT'] }) + checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: ['EXACT', 'TAG'] }) } break + case 'TAG': + _.get(page, 'tags', []).forEach(tag => { + if (tag.tag === rule.path) { + checkState = this._applyPageRuleSpecificity({ + rule, + checkState, + higherPriority: ['EXACT'] + }) + } + }) + break case 'EXACT': if (`/${page.path}` === `/${rule.path}`) { checkState = this._applyPageRuleSpecificity({ rule, checkState, higherPriority: [] }) diff --git a/server/graph/schemas/group.graphql b/server/graph/schemas/group.graphql index 0d4c0c4d..5b294974 100644 --- a/server/graph/schemas/group.graphql +++ b/server/graph/schemas/group.graphql @@ -108,4 +108,5 @@ enum PageRuleMatch { EXACT END REGEX + TAG }