Browse Source

feat: check for updates

pull/760/head
Nicolas Giard 5 years ago
parent
commit
63c044a09b
13 changed files with 95 additions and 15 deletions
  1. 4
      client/components/admin/admin-api.vue
  2. 5
      client/components/admin/admin-dashboard.vue
  3. 4
      client/components/admin/admin-groups-edit-rules.vue
  4. 3
      package.json
  5. 4
      server/app/data.yml
  6. 5
      server/core/config.js
  7. 3
      server/core/redis.js
  8. 19
      server/core/system.js
  9. 2
      server/graph/resolvers/group.js
  10. 5
      server/graph/resolvers/system.js
  11. 45
      server/jobs/sync-graph-updates.js
  12. 1
      server/master.js
  13. 10
      server/views/unauthorized.pug

4
client/components/admin/admin-api.vue

@ -5,7 +5,7 @@
.admin-header .admin-header
img(src='/svg/icon-rest-api.svg', alt='API', style='width: 80px;') img(src='/svg/icon-rest-api.svg', alt='API', style='width: 80px;')
.admin-header-title .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] .subheading.grey--text Manage keys to access the API #[v-chip(label, color='primary', small).white--text coming soon]
v-spacer v-spacer
v-btn(outline, color='grey', large, @click='refresh', disabled) v-btn(outline, color='grey', large, @click='refresh', disabled)
@ -58,7 +58,7 @@
td {{ props.item.updatedOn }} td {{ props.item.updatedOn }}
td: v-btn(icon): v-icon.grey--text.text--darken-1 more_horiz td: v-btn(icon): v-icon.grey--text.text--darken-1 more_horiz
template(slot='no-data') 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 .text-xs-center.py-2
v-pagination(v-model='pagination.page', :length='pages') v-pagination(v-model='pagination.page', :length='pages')
</template> </template>

5
client/components/admin/admin-dashboard.vue

@ -46,11 +46,10 @@
dark dark
) )
v-btn(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)') 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-card-text
v-icon.dashboard-icon blur_on 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-if='isLatestVersion') You are running the latest version.
.body-2(v-else) A new version is available: {{info.latestVersion}} .body-2(v-else) A new version is available: {{info.latestVersion}}
v-flex(xs12) v-flex(xs12)

4
client/components/admin/admin-groups-edit-rules.vue

@ -182,6 +182,10 @@
strong Path Is Exactly... strong Path Is Exactly...
em.caption.pl-1 (highest) 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. .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.
</template> </template>

3
package.json

@ -1,6 +1,7 @@
{ {
"name": "wiki", "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", "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
"main": "wiki.js", "main": "wiki.js",
"scripts": { "scripts": {

4
server/app/data.yml

@ -66,6 +66,10 @@ jobs:
onInit: true onInit: true
cron: '0 0 * * *' cron: '0 0 * * *'
concurrency: 0 concurrency: 0
syncGraphUpdates:
onInit: true
cron: '0 0 * * *'
concurrency: 0
syncStorage: syncStorage:
onInit: false onInit: false
cron: false cron: false

5
server/core/config.js

@ -52,9 +52,12 @@ module.exports = {
appconfig.port = process.env.PORT || 80 appconfig.port = process.env.PORT || 80
} }
const packageInfo = require(path.join(WIKI.ROOTPATH, 'package.json'))
WIKI.config = appconfig WIKI.config = appconfig
WIKI.data = appdata WIKI.data = appdata
WIKI.version = require(path.join(WIKI.ROOTPATH, 'package.json')).version
WIKI.version = packageInfo.version
WIKI.releaseDate = packageInfo.releaseDate
}, },
/** /**

3
server/core/redis.js

@ -25,12 +25,11 @@ module.exports = {
red.on('message', (channel, msg) => { red.on('message', (channel, msg) => {
WIKI.events.emit(channel, msg) WIKI.events.emit(channel, msg)
}) })
red.subscribe('localization', (err, count) => {
red.subscribe('localization', 'updates', (err, count) => {
if (err) { if (err) {
WIKI.logger.error(err) WIKI.logger.error(err)
process.exit(1) process.exit(1)
} }
WIKI.logger.info('Redis Subscriber connection: [ OK ]')
}) })
return red return red
} }

19
server/core/system.js

@ -5,6 +5,25 @@ const Promise = require('bluebird')
/* global WIKI */ /* global WIKI */
module.exports = { 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 * Upgrade from WIKI.js 1.x - MongoDB database
* *

2
server/graph/resolvers/group.js

@ -75,7 +75,7 @@ module.exports = {
}, },
async update(obj, args) { async update(obj, args) {
if(_.some(args.pageRules, pr => { 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.') throw new gql.GraphQLError('Some Page Rules contains unsafe or exponential time regex.')
} }

5
server/graph/resolvers/system.js

@ -5,6 +5,7 @@ const os = require('os')
const filesize = require('filesize') const filesize = require('filesize')
const path = require('path') const path = require('path')
const fs = require('fs-extra') const fs = require('fs-extra')
const moment = require('moment')
/* global WIKI */ /* global WIKI */
@ -62,10 +63,10 @@ module.exports = {
} }
}, },
latestVersion() { latestVersion() {
return '2.0.0' // TODO
return WIKI.system.updates.version
}, },
latestVersionReleaseDate() { latestVersionReleaseDate() {
return new Date() // TODO
return moment.utc(WIKI.system.updates.releaseDate)
}, },
async operatingSystem() { async operatingSystem() {
let osLabel = `${os.type()} (${os.platform()}) ${os.release()} ${os.arch()}` let osLabel = `${os.type()} (${os.platform()}) ${os.release()} ${os.arch()}`

45
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)
}
}

1
server/master.js

@ -20,6 +20,7 @@ module.exports = async () => {
WIKI.auth = require('./core/auth').init() WIKI.auth = require('./core/auth').init()
WIKI.lang = require('./core/localization').init() WIKI.lang = require('./core/localization').init()
WIKI.mail = require('./core/mail').init() WIKI.mail = require('./core/mail').init()
WIKI.system = require('./core/system').init()
// ---------------------------------------- // ----------------------------------------
// Load middlewares // Load middlewares

10
server/views/unauthorized.pug

@ -8,6 +8,10 @@ block body
img.animated.fadeIn(src='/svg/icon-delete-shield.svg', alt='Unauthorized') img.animated.fadeIn(src='/svg/icon-delete-shield.svg', alt='Unauthorized')
.headline= t('unauthorized.title') .headline= t('unauthorized.title')
.subheading.mt-3= t('unauthorized.action.' + action) .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')
Loading…
Cancel
Save