diff --git a/client/components/admin/admin-api.vue b/client/components/admin/admin-api.vue index edad343a..360b1c52 100644 --- a/client/components/admin/admin-api.vue +++ b/client/components/admin/admin-api.vue @@ -5,7 +5,7 @@ .admin-header img(src='/svg/icon-rest-api.svg', alt='API', style='width: 80px;') .admin-header-title - .headline.blue--text.text--darken-2 API + .headline.blue--text.text--darken-2 API Access .subheading.grey--text Manage keys to access the API #[v-chip(label, color='primary', small).white--text coming soon] v-spacer v-btn(outline, color='grey', large, @click='refresh', disabled) @@ -58,7 +58,7 @@ td {{ props.item.updatedOn }} td: v-btn(icon): v-icon.grey--text.text--darken-1 more_horiz template(slot='no-data') - v-alert.mt-3(icon='info', :value='true', outline, color='info') No API have been generated yet. + v-alert.mt-3(icon='info', :value='true', outline, color='info') No API keys have been generated yet. .text-xs-center.py-2 v-pagination(v-model='pagination.page', :length='pages') diff --git a/client/components/admin/admin-dashboard.vue b/client/components/admin/admin-dashboard.vue index 34e0659a..4b7ae4c3 100644 --- a/client/components/admin/admin-dashboard.vue +++ b/client/components/admin/admin-dashboard.vue @@ -46,11 +46,10 @@ dark ) v-btn(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)') - v-icon(v-if='isLatestVersion', color='teal') build - v-icon(v-else, color='red darken-4') get_app + v-icon(:color='isLatestVersion ? `teal` : `red darken-4`') build v-card-text v-icon.dashboard-icon blur_on - .subheading Wiki.js {{info.currentVersion}} BETA + .subheading Wiki.js {{info.currentVersion}} .body-2(v-if='isLatestVersion') You are running the latest version. .body-2(v-else) A new version is available: {{info.latestVersion}} v-flex(xs12) diff --git a/client/components/admin/admin-groups-edit-rules.vue b/client/components/admin/admin-groups-edit-rules.vue index 6bb3baad..ff33a2bb 100644 --- a/client/components/admin/admin-groups-edit-rules.vue +++ b/client/components/admin/admin-groups-edit-rules.vue @@ -182,6 +182,10 @@ strong Path Is Exactly... em.caption.pl-1 (highest) .body-1.pl-3.pt-2 When 2 rules have the same path specificity AND the same match type, #[strong.red--text DENY] will always override an #[strong.green--text ALLOW] rule. + v-divider.mt-3 + v-subheader.pl-0 Regular Expressions + span Expressions that are deemed unsafe or could result in exponential time processing will be rejected upon saving. + diff --git a/package.json b/package.json index 3d715e42..f3e98354 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "wiki", - "version": "2.0.0", + "version": "2.0.0-beta.1", + "releaseDate": "2019-01-01T01:01:01.000Z", "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown", "main": "wiki.js", "scripts": { diff --git a/server/app/data.yml b/server/app/data.yml index d3fdf518..be98321b 100644 --- a/server/app/data.yml +++ b/server/app/data.yml @@ -66,6 +66,10 @@ jobs: onInit: true cron: '0 0 * * *' concurrency: 0 + syncGraphUpdates: + onInit: true + cron: '0 0 * * *' + concurrency: 0 syncStorage: onInit: false cron: false diff --git a/server/core/config.js b/server/core/config.js index dfe26ea2..1bf4b68b 100644 --- a/server/core/config.js +++ b/server/core/config.js @@ -52,9 +52,12 @@ module.exports = { appconfig.port = process.env.PORT || 80 } + const packageInfo = require(path.join(WIKI.ROOTPATH, 'package.json')) + WIKI.config = appconfig WIKI.data = appdata - WIKI.version = require(path.join(WIKI.ROOTPATH, 'package.json')).version + WIKI.version = packageInfo.version + WIKI.releaseDate = packageInfo.releaseDate }, /** diff --git a/server/core/redis.js b/server/core/redis.js index f90a58cc..4a254d2a 100644 --- a/server/core/redis.js +++ b/server/core/redis.js @@ -25,12 +25,11 @@ module.exports = { red.on('message', (channel, msg) => { WIKI.events.emit(channel, msg) }) - red.subscribe('localization', (err, count) => { + red.subscribe('localization', 'updates', (err, count) => { if (err) { WIKI.logger.error(err) process.exit(1) } - WIKI.logger.info('Redis Subscriber connection: [ OK ]') }) return red } diff --git a/server/core/system.js b/server/core/system.js index e38c596f..d2da7660 100644 --- a/server/core/system.js +++ b/server/core/system.js @@ -5,6 +5,25 @@ const Promise = require('bluebird') /* global WIKI */ module.exports = { + updates: { + channel: 'BETA', + version: WIKI.version, + releaseDate: WIKI.releaseDate, + minimumVersionRequired: '2.0.0-beta.0', + minimumNodeRequired: '10.12.0' + }, + init() { + // Listen for updates events + WIKI.events.on('updates', (infoRaw) => { + try { + this.updates = JSON.parse(infoRaw) + } catch (err) { + WIKI.logger.warn('Failed to parse updates info.') + } + }) + + return this + }, /** * Upgrade from WIKI.js 1.x - MongoDB database * diff --git a/server/graph/resolvers/group.js b/server/graph/resolvers/group.js index 00f109d7..6cbf3dc0 100644 --- a/server/graph/resolvers/group.js +++ b/server/graph/resolvers/group.js @@ -75,7 +75,7 @@ module.exports = { }, async update(obj, args) { if(_.some(args.pageRules, pr => { - return pr.match !== 'REGEX' || safeRegex(pr.path) + return pr.match === 'REGEX' && !safeRegex(pr.path) })) { throw new gql.GraphQLError('Some Page Rules contains unsafe or exponential time regex.') } diff --git a/server/graph/resolvers/system.js b/server/graph/resolvers/system.js index 5395c985..525c970a 100644 --- a/server/graph/resolvers/system.js +++ b/server/graph/resolvers/system.js @@ -5,6 +5,7 @@ const os = require('os') const filesize = require('filesize') const path = require('path') const fs = require('fs-extra') +const moment = require('moment') /* global WIKI */ @@ -62,10 +63,10 @@ module.exports = { } }, latestVersion() { - return '2.0.0' // TODO + return WIKI.system.updates.version }, latestVersionReleaseDate() { - return new Date() // TODO + return moment.utc(WIKI.system.updates.releaseDate) }, async operatingSystem() { let osLabel = `${os.type()} (${os.platform()}) ${os.release()} ${os.arch()}` diff --git a/server/jobs/sync-graph-updates.js b/server/jobs/sync-graph-updates.js new file mode 100644 index 00000000..6a8c9202 --- /dev/null +++ b/server/jobs/sync-graph-updates.js @@ -0,0 +1,45 @@ +require('../core/worker') +const _ = require('lodash') +const { createApolloFetch } = require('apollo-fetch') + +/* global WIKI */ + +WIKI.redis = require('../core/redis').init() +WIKI.models = require('../core/db').init() + +module.exports = async (job) => { + WIKI.logger.info(`Fetching latest updates from Graph endpoint...`) + + try { + await WIKI.configSvc.loadFromDb() + const apollo = createApolloFetch({ + uri: WIKI.config.graphEndpoint + }) + + const resp = await apollo({ + query: `query ($channel: ReleaseChannel!, $version: String!) { + releases { + checkForUpdates(channel: $channel, version: $version) { + channel + version + releaseDate + minimumVersionRequired + minimumNodeRequired + } + } + }`, + variables: { + channel: 'BETA', // TODO + version: WIKI.version + } + }) + const info = _.get(resp, 'data.releases.checkForUpdates', {}) + + await WIKI.redis.publish('updates', JSON.stringify(info)) + + WIKI.logger.info(`Fetching latest updates from Graph endpoint: [ COMPLETED ]`) + } catch (err) { + WIKI.logger.error(`Fetching latest updates from Graph endpoint: [ FAILED ]`) + WIKI.logger.error(err.message) + } +} diff --git a/server/master.js b/server/master.js index 8f2e2990..5e317bf6 100644 --- a/server/master.js +++ b/server/master.js @@ -20,6 +20,7 @@ module.exports = async () => { WIKI.auth = require('./core/auth').init() WIKI.lang = require('./core/localization').init() WIKI.mail = require('./core/mail').init() + WIKI.system = require('./core/system').init() // ---------------------------------------- // Load middlewares diff --git a/server/views/unauthorized.pug b/server/views/unauthorized.pug index 61d22f00..d303797e 100644 --- a/server/views/unauthorized.pug +++ b/server/views/unauthorized.pug @@ -8,6 +8,10 @@ block body img.animated.fadeIn(src='/svg/icon-delete-shield.svg', alt='Unauthorized') .headline= t('unauthorized.title') .subheading.mt-3= t('unauthorized.action.' + action) - v-btn.mt-5(color='red lighten-4', href='javascript:window.history.go(-1);', large, outline) - v-icon(left) arrow_back - span= t('unauthorized.goback') + .mt-5 + v-btn(color='red lighten-4', href='javascript:window.history.go(-1);', large, outline) + v-icon(left) arrow_back + span= t('unauthorized.goback') + v-btn(color='red lighten-4', href='/login', large, outline) + v-icon(left) person_outline + span= t('unauthorized.login')