mirror of https://github.com/requarks/wiki
parent
3752cf7415
commit
7786f9042f
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
localization {
|
||||||
|
locales {
|
||||||
|
code
|
||||||
|
createdAt
|
||||||
|
isInstalled
|
||||||
|
installDate
|
||||||
|
isRTL
|
||||||
|
name
|
||||||
|
nativeName
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
let WIKI = {
|
||||||
|
IS_DEBUG: process.env.NODE_ENV === 'development',
|
||||||
|
ROOTPATH: process.cwd(),
|
||||||
|
SERVERPATH: path.join(process.cwd(), 'server'),
|
||||||
|
Error: require('../helpers/error'),
|
||||||
|
configSvc: require('./config')
|
||||||
|
}
|
||||||
|
global.WIKI = WIKI
|
||||||
|
|
||||||
|
WIKI.configSvc.init()
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Init Logger
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
WIKI.logger = require('./logger').init('JOB')
|
@ -0,0 +1,46 @@
|
|||||||
|
const graphHelper = require('../../helpers/graph')
|
||||||
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Query: {
|
||||||
|
async localization() { return {} }
|
||||||
|
},
|
||||||
|
Mutation: {
|
||||||
|
async localization() { return {} }
|
||||||
|
},
|
||||||
|
LocalizationQuery: {
|
||||||
|
async locales(obj, args, context, info) {
|
||||||
|
let remoteLocales = await WIKI.redis.get('locales')
|
||||||
|
let localLocales = await WIKI.db.Locale.findAll({
|
||||||
|
attributes: {
|
||||||
|
exclude: ['strings']
|
||||||
|
},
|
||||||
|
raw: true
|
||||||
|
})
|
||||||
|
remoteLocales = (remoteLocales) ? JSON.parse(remoteLocales) : localLocales
|
||||||
|
return _.map(remoteLocales, rl => {
|
||||||
|
let isInstalled = _.some(localLocales, ['code', rl.code])
|
||||||
|
return {
|
||||||
|
...rl,
|
||||||
|
isInstalled,
|
||||||
|
installDate: isInstalled ? _.find(localLocales, ['code', rl.code]).updatedAt : null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
LocalizationMutation: {
|
||||||
|
async updateLocale(obj, args, context) {
|
||||||
|
try {
|
||||||
|
let authResult = await WIKI.db.User.login(args, context)
|
||||||
|
return {
|
||||||
|
...authResult,
|
||||||
|
responseResult: graphHelper.generateSuccess('Login success')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return graphHelper.generateError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
# ===============================================
|
||||||
|
# LOCALIZATION
|
||||||
|
# ===============================================
|
||||||
|
|
||||||
|
extend type Query {
|
||||||
|
localization: LocalizationQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
extend type Mutation {
|
||||||
|
localization: LocalizationMutation
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------
|
||||||
|
# QUERIES
|
||||||
|
# -----------------------------------------------
|
||||||
|
|
||||||
|
type LocalizationQuery {
|
||||||
|
locales: [LocalizationLocale]
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------
|
||||||
|
# MUTATIONS
|
||||||
|
# -----------------------------------------------
|
||||||
|
|
||||||
|
type LocalizationMutation {
|
||||||
|
updateLocale(
|
||||||
|
localeId: String!
|
||||||
|
autoUpdate: Boolean!
|
||||||
|
): DefaultResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------
|
||||||
|
# TYPES
|
||||||
|
# -----------------------------------------------
|
||||||
|
|
||||||
|
type LocalizationLocale {
|
||||||
|
code: String!
|
||||||
|
createdAt: Date!
|
||||||
|
installDate: Date
|
||||||
|
isInstalled: Boolean!
|
||||||
|
isRTL: Boolean!
|
||||||
|
name: String!
|
||||||
|
nativeName: String!
|
||||||
|
updatedAt: Date!
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
require('../core/worker')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
const Promise = require('bluebird')
|
||||||
|
const fs = Promise.promisifyAll(require('fs-extra'))
|
||||||
|
const moment = require('moment')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = async (job) => {
|
||||||
|
WIKI.logger.info('Purging orphaned upload files...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const uplTempPath = path.resolve(process.cwd(), WIKI.config.paths.data, 'temp-upload')
|
||||||
|
const ls = await fs.readdirAsync(uplTempPath)
|
||||||
|
const fifteenAgo = moment().subtract(15, 'minutes')
|
||||||
|
|
||||||
|
await Promise.map(ls, (f) => {
|
||||||
|
return fs.statAsync(path.join(uplTempPath, f)).then((s) => { return { filename: f, stat: s } })
|
||||||
|
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
|
||||||
|
return Promise.map(arrFiles, (f) => {
|
||||||
|
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
|
||||||
|
return fs.unlinkAsync(path.join(uplTempPath, f.filename))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
WIKI.logger.info('Purging orphaned upload files: [ COMPLETED ]')
|
||||||
|
} catch (err) {
|
||||||
|
WIKI.logger.error('Purging orphaned upload files: [ FAILED ]')
|
||||||
|
WIKI.logger.error(err.message)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
// /* global WIKI */
|
||||||
|
|
||||||
|
// const Promise = require('bluebird')
|
||||||
|
// const fs = Promise.promisifyAll(require('fs-extra'))
|
||||||
|
// const klaw = require('klaw')
|
||||||
|
// const moment = require('moment')
|
||||||
|
// const path = require('path')
|
||||||
|
// const entryHelper = require('../helpers/entry')
|
||||||
|
|
||||||
|
module.exports = (job) => {
|
||||||
|
return true
|
||||||
|
// return WIKI.git.resync().then(() => {
|
||||||
|
// // -> Stream all documents
|
||||||
|
|
||||||
|
// let cacheJobs = []
|
||||||
|
// let jobCbStreamDocsResolve = null
|
||||||
|
// let jobCbStreamDocs = new Promise((resolve, reject) => {
|
||||||
|
// jobCbStreamDocsResolve = resolve
|
||||||
|
// })
|
||||||
|
|
||||||
|
// klaw(WIKI.REPOPATH).on('data', function (item) {
|
||||||
|
// if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') {
|
||||||
|
// let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path))
|
||||||
|
// let cachePath = entryHelper.getCachePath(entryPath)
|
||||||
|
|
||||||
|
// // -> Purge outdated cache
|
||||||
|
|
||||||
|
// cacheJobs.push(
|
||||||
|
// fs.statAsync(cachePath).then((st) => {
|
||||||
|
// return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active'
|
||||||
|
// }).catch((err) => {
|
||||||
|
// return (err.code !== 'EEXIST') ? err : 'new'
|
||||||
|
// }).then((fileStatus) => {
|
||||||
|
// // -> Delete expired cache file
|
||||||
|
|
||||||
|
// if (fileStatus === 'expired') {
|
||||||
|
// return fs.unlinkAsync(cachePath).return(fileStatus)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return fileStatus
|
||||||
|
// }).then((fileStatus) => {
|
||||||
|
// // -> Update cache and search index
|
||||||
|
|
||||||
|
// if (fileStatus !== 'active') {
|
||||||
|
// return global.entries.updateCache(entryPath).then(entry => {
|
||||||
|
// process.send({
|
||||||
|
// action: 'searchAdd',
|
||||||
|
// content: entry
|
||||||
|
// })
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }).on('end', () => {
|
||||||
|
// jobCbStreamDocsResolve(Promise.all(cacheJobs))
|
||||||
|
// })
|
||||||
|
|
||||||
|
// return jobCbStreamDocs
|
||||||
|
// }).then(() => {
|
||||||
|
// WIKI.logger.info('Git remote repository sync: DONE')
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
require('../core/worker')
|
||||||
|
const _ = require('lodash')
|
||||||
|
const { createApolloFetch } = require('apollo-fetch')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
WIKI.redis = require('../core/redis').init()
|
||||||
|
const apollo = createApolloFetch({
|
||||||
|
uri: 'https://graph.requarks.io'
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = async (job) => {
|
||||||
|
WIKI.logger.info('Syncing locales with Graph endpoint...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await apollo({
|
||||||
|
query: `{
|
||||||
|
localization {
|
||||||
|
locales {
|
||||||
|
code
|
||||||
|
name
|
||||||
|
nativeName
|
||||||
|
isRTL
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
})
|
||||||
|
const locales = _.sortBy(_.get(resp, 'data.localization.locales', []), 'name').map(lc => ({...lc, isInstalled: (lc.code === 'en')}))
|
||||||
|
WIKI.redis.set('locales', JSON.stringify(locales))
|
||||||
|
|
||||||
|
WIKI.logger.info('Syncing locales with Graph endpoint: [ COMPLETED ]')
|
||||||
|
} catch (err) {
|
||||||
|
WIKI.logger.error('Syncing locales with Graph endpoint: [ FAILED ]')
|
||||||
|
WIKI.logger.error(err.message)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"auth": {
|
||||||
|
"actions": {
|
||||||
|
"login": "Log In"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"invalidLogin": "Invalid Login",
|
||||||
|
"invalidLoginMsg": "The email or password is invalid.",
|
||||||
|
"invalidUserEmail": "Invalid User Email",
|
||||||
|
"loginError": "Login error",
|
||||||
|
"notYetAuthorized": "You have not been authorized to login to this site yet.",
|
||||||
|
"tooManyAttempts": "Too many attempts!",
|
||||||
|
"tooManyAttemptsMsg": "You've made too many failed attempts in a short period of time, please try again {{time}}.",
|
||||||
|
"userNotFound": "User not found"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"emailUser": "Email / Username",
|
||||||
|
"password": "Password"
|
||||||
|
},
|
||||||
|
"loginRequired": "Login required",
|
||||||
|
"providers": {
|
||||||
|
"azure": "Azure Active Directory",
|
||||||
|
"facebook": "Facebook",
|
||||||
|
"github": "GitHub",
|
||||||
|
"google": "Google ID",
|
||||||
|
"ldap": "LDAP / Active Directory",
|
||||||
|
"local": "Local",
|
||||||
|
"slack": "Slack",
|
||||||
|
"windowslive": "Microsoft Account"
|
||||||
|
},
|
||||||
|
"tfa": {
|
||||||
|
"placeholder": "XXXXXX",
|
||||||
|
"subtitle": "Security code required:",
|
||||||
|
"title": "Two Factor Authentication",
|
||||||
|
"verifyToken": "Verify"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Locale schema
|
||||||
|
*/
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
let localeSchema = sequelize.define('locale', {
|
||||||
|
code: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
strings: {
|
||||||
|
type: DataTypes.JSON,
|
||||||
|
allowNull: true
|
||||||
|
},
|
||||||
|
isRTL: {
|
||||||
|
type: DataTypes.BOOLEAN,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: false
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
nativeName: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
timestamps: true,
|
||||||
|
version: true,
|
||||||
|
indexes: [
|
||||||
|
{
|
||||||
|
unique: true,
|
||||||
|
fields: ['code']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
return localeSchema
|
||||||
|
}
|
@ -1,68 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
/* global WIKI */
|
|
||||||
|
|
||||||
const Promise = require('bluebird')
|
|
||||||
const fs = Promise.promisifyAll(require('fs-extra'))
|
|
||||||
const klaw = require('klaw')
|
|
||||||
const moment = require('moment')
|
|
||||||
const path = require('path')
|
|
||||||
const entryHelper = require('../helpers/entry')
|
|
||||||
|
|
||||||
module.exports = (job) => {
|
|
||||||
return WIKI.git.resync().then(() => {
|
|
||||||
// -> Stream all documents
|
|
||||||
|
|
||||||
let cacheJobs = []
|
|
||||||
let jobCbStreamDocsResolve = null
|
|
||||||
let jobCbStreamDocs = new Promise((resolve, reject) => {
|
|
||||||
jobCbStreamDocsResolve = resolve
|
|
||||||
})
|
|
||||||
|
|
||||||
klaw(WIKI.REPOPATH).on('data', function (item) {
|
|
||||||
if (path.extname(item.path) === '.md' && path.basename(item.path) !== 'README.md') {
|
|
||||||
let entryPath = entryHelper.parsePath(entryHelper.getEntryPathFromFullPath(item.path))
|
|
||||||
let cachePath = entryHelper.getCachePath(entryPath)
|
|
||||||
|
|
||||||
// -> Purge outdated cache
|
|
||||||
|
|
||||||
cacheJobs.push(
|
|
||||||
fs.statAsync(cachePath).then((st) => {
|
|
||||||
return moment(st.mtime).isBefore(item.stats.mtime) ? 'expired' : 'active'
|
|
||||||
}).catch((err) => {
|
|
||||||
return (err.code !== 'EEXIST') ? err : 'new'
|
|
||||||
}).then((fileStatus) => {
|
|
||||||
// -> Delete expired cache file
|
|
||||||
|
|
||||||
if (fileStatus === 'expired') {
|
|
||||||
return fs.unlinkAsync(cachePath).return(fileStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileStatus
|
|
||||||
}).then((fileStatus) => {
|
|
||||||
// -> Update cache and search index
|
|
||||||
|
|
||||||
if (fileStatus !== 'active') {
|
|
||||||
return global.entries.updateCache(entryPath).then(entry => {
|
|
||||||
process.send({
|
|
||||||
action: 'searchAdd',
|
|
||||||
content: entry
|
|
||||||
})
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}).on('end', () => {
|
|
||||||
jobCbStreamDocsResolve(Promise.all(cacheJobs))
|
|
||||||
})
|
|
||||||
|
|
||||||
return jobCbStreamDocs
|
|
||||||
}).then(() => {
|
|
||||||
WIKI.logger.info('Git remote repository sync: DONE')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
/* global WIKI */
|
|
||||||
|
|
||||||
const Promise = require('bluebird')
|
|
||||||
const fs = Promise.promisifyAll(require('fs-extra'))
|
|
||||||
const moment = require('moment')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
module.exports = (job) => {
|
|
||||||
return fs.readdirAsync(WIKI.UPLTEMPPATH).then((ls) => {
|
|
||||||
let fifteenAgo = moment().subtract(15, 'minutes')
|
|
||||||
|
|
||||||
return Promise.map(ls, (f) => {
|
|
||||||
return fs.statAsync(path.join(WIKI.UPLTEMPPATH, f)).then((s) => { return { filename: f, stat: s } })
|
|
||||||
}).filter((s) => { return s.stat.isFile() }).then((arrFiles) => {
|
|
||||||
return Promise.map(arrFiles, (f) => {
|
|
||||||
if (moment(f.stat.ctime).isBefore(fifteenAgo, 'minute')) {
|
|
||||||
return fs.unlinkAsync(path.join(WIKI.UPLTEMPPATH, f.filename))
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).then(() => {
|
|
||||||
WIKI.logger.info('Purging temporary upload files: DONE')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
const Promise = require('bluebird')
|
|
||||||
|
|
||||||
/* global WIKI */
|
|
||||||
|
|
||||||
module.exports = Promise.join(
|
|
||||||
WIKI.db.onReady,
|
|
||||||
WIKI.configSvc.loadFromDb(['features', 'logging', 'site', 'uploads'])
|
|
||||||
).then(() => {
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
WIKI.REPOPATH = path.resolve(WIKI.ROOTPATH, WIKI.config.paths.repo)
|
|
||||||
WIKI.DATAPATH = path.resolve(WIKI.ROOTPATH, WIKI.config.paths.data)
|
|
||||||
WIKI.UPLTEMPPATH = path.join(WIKI.DATAPATH, 'temp-upload')
|
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
// Load global modules
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
WIKI.lang = require('i18next')
|
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
// Localization Engine
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
const i18nBackend = require('i18next-node-fs-backend')
|
|
||||||
WIKI.lang.use(i18nBackend).init({
|
|
||||||
load: 'languageOnly',
|
|
||||||
ns: ['common', 'admin', 'auth', 'errors'],
|
|
||||||
defaultNS: 'common',
|
|
||||||
saveMissing: false,
|
|
||||||
preload: [WIKI.config.lang],
|
|
||||||
lng: WIKI.config.lang,
|
|
||||||
fallbackLng: 'en',
|
|
||||||
backend: {
|
|
||||||
loadPath: path.join(WIKI.SERVERPATH, 'locales/{{lng}}/{{ns}}.yml')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
// Start Queues
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
const Bull = require('bull')
|
|
||||||
const autoload = require('auto-load')
|
|
||||||
|
|
||||||
let queues = autoload(path.join(WIKI.SERVERPATH, 'queues'))
|
|
||||||
|
|
||||||
for (let queueName in queues) {
|
|
||||||
new Bull(queueName, {
|
|
||||||
prefix: `q-${WIKI.config.ha.nodeuid}`,
|
|
||||||
redis: WIKI.config.redis
|
|
||||||
}).process(queues[queueName])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
// Shutdown gracefully
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
process.on('disconnect', () => {
|
|
||||||
process.exit()
|
|
||||||
})
|
|
||||||
})
|
|
Loading…
Reference in new issue