Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wiki-js
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
wiki-js
Commits
9a92789d
Unverified
Commit
9a92789d
authored
Apr 06, 2023
by
NGPixel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: editor create page mode
parent
278a9bef
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
594 additions
and
419 deletions
+594
-419
common.js
server/controllers/common.js
+347
-357
web.js
server/web.js
+1
-5
HeaderNav.vue
ux/src/components/HeaderNav.vue
+1
-0
PageHeader.vue
ux/src/components/PageHeader.vue
+52
-2
TreeBrowserDialog.vue
ux/src/components/TreeBrowserDialog.vue
+4
-1
WelcomeOverlay.vue
ux/src/components/WelcomeOverlay.vue
+1
-1
AdminGeneral.vue
ux/src/pages/AdminGeneral.vue
+1
-6
page.js
ux/src/stores/page.js
+182
-46
site.js
ux/src/stores/site.js
+5
-1
No files found.
server/controllers/common.js
View file @
9a92789d
...
...
@@ -106,20 +106,6 @@ router.get('/_thumb/:id.webp', async (req, res, next) => {
}
})
/**
* New v3 vue app
*/
router
.
get
([
'/_admin'
,
'/_admin/*'
,
'/_profile'
,
'/_profile/*'
,
'/_error'
,
'/_error/*'
,
'/_welcome'
],
(
req
,
res
,
next
)
=>
{
res
.
sendFile
(
path
.
join
(
WIKI
.
ROOTPATH
,
'assets/index.html'
))
})
// router.get(['/_admin', '/_admin/*'], (req, res, next) => {
// if (!WIKI.auth.checkAccess(req.user, [
// 'manage:system',
...
...
@@ -140,297 +126,297 @@ router.get([
// })
/**
* Download Page / Version
*/
router
.
get
([
'/d'
,
'/d/*'
],
async
(
req
,
res
,
next
)
=>
{
const
pageArgs
=
pageHelper
.
parsePath
(
req
.
path
,
{
stripExt
:
true
})
const
versionId
=
(
req
.
query
.
v
)
?
_
.
toSafeInteger
(
req
.
query
.
v
)
:
0
const
page
=
await
WIKI
.
db
.
pages
.
getPageFromDb
({
path
:
pageArgs
.
path
,
locale
:
pageArgs
.
locale
,
userId
:
req
.
user
.
id
,
isPrivate
:
false
})
pageArgs
.
tags
=
_
.
get
(
page
,
'tags'
,
[])
if
(
versionId
>
0
)
{
if
(
!
WIKI
.
auth
.
checkAccess
(
req
.
user
,
[
'read:history'
],
pageArgs
))
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'downloadVersion'
})
}
}
else
{
if
(
!
WIKI
.
auth
.
checkAccess
(
req
.
user
,
[
'read:source'
],
pageArgs
))
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'download'
})
}
}
if
(
page
)
{
const
fileName
=
_
.
last
(
page
.
path
.
split
(
'/'
))
+
'.'
+
pageHelper
.
getFileExtension
(
page
.
contentType
)
res
.
attachment
(
fileName
)
if
(
versionId
>
0
)
{
const
pageVersion
=
await
WIKI
.
db
.
pageHistory
.
getVersion
({
pageId
:
page
.
id
,
versionId
})
res
.
send
(
pageHelper
.
injectPageMetadata
(
pageVersion
))
}
else
{
res
.
send
(
pageHelper
.
injectPageMetadata
(
page
))
}
}
else
{
res
.
status
(
404
).
end
()
}
})
/**
* Create/Edit document
*/
router
.
get
([
'/_edit'
,
'/_edit/*'
],
async
(
req
,
res
,
next
)
=>
{
const
pageArgs
=
pageHelper
.
parsePath
(
req
.
path
,
{
stripExt
:
true
})
const
site
=
await
WIKI
.
db
.
sites
.
getSiteByHostname
({
hostname
:
req
.
hostname
})
if
(
!
site
)
{
throw
new
Error
(
'INVALID_SITE'
)
}
if
(
pageArgs
.
path
===
''
)
{
return
res
.
redirect
(
`/_edit/home`
)
}
// if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) {
// return res.redirect(`/_edit/${pageArgs.locale}/${pageArgs.path}`)
// }
// /**
// * Download Page / Version
// */
// router.get(['/d', '/d/*'], async (req, res, next) => {
// const pageArgs = pageHelper.parsePath(req.path, { stripExt: true })
// const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0
// const page = await WIKI.db.pages.getPageFromDb({
// path: pageArgs.path,
// locale: pageArgs.locale,
// userId: req.user.id,
// isPrivate: false
// })
// pageArgs.tags = _.get(page, 'tags', [])
// if (versionId > 0) {
// if (!WIKI.auth.checkAccess(req.user, ['read:history'], pageArgs)) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'downloadVersion' })
// }
// } else {
// if (!WIKI.auth.checkAccess(req.user, ['read:source'], pageArgs)) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'download' })
// }
// }
// req.i18n.changeLanguage(pageArgs.locale)
// if (page) {
// const fileName = _.last(page.path.split('/')) + '.' + pageHelper.getFileExtension(page.contentType)
// res.attachment(fileName)
// if (versionId > 0) {
// const pageVersion = await WIKI.db.pageHistory.getVersion({ pageId: page.id, versionId })
// res.send(pageHelper.injectPageMetadata(pageVersion))
// } else {
// res.send(pageHelper.injectPageMetadata(page))
// }
// } else {
// res.status(404).end()
// }
// })
// -> Set Editor Lang
_
.
set
(
res
,
'locals.siteConfig.lang'
,
pageArgs
.
locale
)
// _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
// /**
// * Create/Edit document
// */
// router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
// const pageArgs = pageHelper.parsePath(req.path, { stripExt: true })
// const site = await WIKI.db.sites.getSiteByHostname({ hostname: req.hostname })
// -> Check for reserved path
if
(
pageHelper
.
isReservedPath
(
pageArgs
.
path
))
{
return
next
(
new
Error
(
'Cannot create this page because it starts with a system reserved path.'
))
}
// if (!site) {
// throw new Error('INVALID_SITE')
// }
// -> Get page data from DB
let
page
=
await
WIKI
.
db
.
pages
.
getPageFromDb
({
siteId
:
site
.
id
,
path
:
pageArgs
.
path
,
locale
:
pageArgs
.
locale
,
userId
:
req
.
user
.
id
})
// if (pageArgs.path === '') {
// return res.redirect(`/_edit/home`)
// }
pageArgs
.
tags
=
_
.
get
(
page
,
'tags'
,
[])
// // if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) {
// // return res.redirect(`/_edit/${pageArgs.locale}/${pageArgs.path}`)
// // }
// -> Effective Permissions
const
effectivePermissions
=
WIKI
.
auth
.
getEffectivePermissions
(
req
,
pageArgs
)
// // req.i18n.changeLanguage(pageArgs.locale)
const
injectCode
=
{
css
:
''
,
// WIKI.config.theming.injectCSS,
head
:
''
,
// WIKI.config.theming.injectHead,
body
:
''
// WIKI.config.theming.injectBody
}
// // -> Set Editor Lang
// _.set(res, 'locals.siteConfig.lang', pageArgs.locale)
// // _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
if
(
page
)
{
// -> EDIT MODE
if
(
!
(
effectivePermissions
.
pages
.
write
||
effectivePermissions
.
pages
.
manage
))
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'edit'
})
}
// // -> Check for reserved path
// if (pageHelper.isReservedPath(pageArgs.path)) {
// return next(new Error('Cannot create this page because it starts with a system reserved path.'))
// }
// -> Get page tags
await
page
.
$relatedQuery
(
'tags'
)
page
.
tags
=
_
.
map
(
page
.
tags
,
'tag'
)
// // -> Get page data from DB
// let page = await WIKI.db.pages.getPageFromDb({
// siteId: site.id,
// path: pageArgs.path,
// locale: pageArgs.locale,
// userId: req.user.id
// })
// Handle missing extra field
page
.
extra
=
page
.
extra
||
{
css
:
''
,
js
:
''
}
// pageArgs.tags = _.get(page, 'tags', [])
// -> Beautify Script CSS
if
(
!
_
.
isEmpty
(
page
.
extra
.
css
))
{
page
.
extra
.
css
=
new
CleanCSS
({
format
:
'beautify'
}).
minify
(
page
.
extra
.
css
).
styles
}
// // -> Effective Permissions
// const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
`Edit
${
page
.
title
}
`
)
_
.
set
(
res
.
locals
,
'pageMeta.description'
,
page
.
description
)
page
.
mode
=
'update'
page
.
isPublished
=
(
page
.
isPublished
===
true
||
page
.
isPublished
===
1
)
?
'true'
:
'false'
page
.
content
=
Buffer
.
from
(
page
.
content
).
toString
(
'base64'
)
}
else
{
// -> CREATE MODE
if
(
!
effectivePermissions
.
pages
.
write
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'create'
})
}
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
`New Page`
)
page
=
{
path
:
pageArgs
.
path
,
localeCode
:
pageArgs
.
locale
,
editorKey
:
null
,
mode
:
'create'
,
content
:
null
,
title
:
null
,
description
:
null
,
updatedAt
:
new
Date
().
toISOString
(),
extra
:
{
css
:
''
,
js
:
''
}
}
}
// const injectCode = {
// css: '', // WIKI.config.theming.injectCSS,
// head: '', // WIKI.config.theming.injectHead,
// body: '' // WIKI.config.theming.injectBody
// }
res
.
render
(
'editor'
,
{
page
,
injectCode
,
effectivePermissions
})
})
// if (page) {
// // -> EDIT MODE
// if (!(effectivePermissions.pages.write || effectivePermissions.pages.manage)) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'edit' })
// }
// // -> Get page tags
// await page.$relatedQuery('tags')
// page.tags = _.map(page.tags, 'tag')
// // Handle missing extra field
// page.extra = page.extra || { css: '', js: '' }
// // -> Beautify Script CSS
// if (!_.isEmpty(page.extra.css)) {
// page.extra.css = new CleanCSS({ format: 'beautify' }).minify(page.extra.css).styles
// }
// _.set(res.locals, 'pageMeta.title', `Edit ${page.title}`)
// _.set(res.locals, 'pageMeta.description', page.description)
// page.mode = 'update'
// page.isPublished = (page.isPublished === true || page.isPublished === 1) ? 'true' : 'false'
// page.content = Buffer.from(page.content).toString('base64')
// } else {
// // -> CREATE MODE
// if (!effectivePermissions.pages.write) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'create' })
// }
// _.set(res.locals, 'pageMeta.title', `New Page`)
// page = {
// path: pageArgs.path,
// localeCode: pageArgs.locale,
// editorKey: null,
// mode: 'create',
// content: null,
// title: null,
// description: null,
// updatedAt: new Date().toISOString(),
// extra: {
// css: '',
// js: ''
// }
// }
// }
/**
* History
*/
router
.
get
([
'/h'
,
'/h/*'
],
async
(
req
,
res
,
next
)
=>
{
const
pageArgs
=
pageHelper
.
parsePath
(
req
.
path
,
{
stripExt
:
true
})
// res.render('editor', { page, injectCode, effectivePermissions })
// })
if
(
WIKI
.
config
.
lang
.
namespacing
&&
!
pageArgs
.
explicitLocale
)
{
return
res
.
redirect
(
`/h/
${
pageArgs
.
locale
}
/
${
pageArgs
.
path
}
`
)
}
// /**
// * History
// */
// router.get(['/h', '/h/*'], async (req, res, next) => {
// const pageArgs = pageHelper.parsePath(req.path, { stripExt: true })
req
.
i18n
.
changeLanguage
(
pageArgs
.
locale
)
// if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) {
// return res.redirect(`/h/${pageArgs.locale}/${pageArgs.path}`)
// }
_
.
set
(
res
,
'locals.siteConfig.lang'
,
pageArgs
.
locale
)
_
.
set
(
res
,
'locals.siteConfig.rtl'
,
req
.
i18n
.
dir
()
===
'rtl'
)
// req.i18n.changeLanguage(pageArgs.locale)
const
page
=
await
WIKI
.
db
.
pages
.
getPageFromDb
({
path
:
pageArgs
.
path
,
locale
:
pageArgs
.
locale
,
userId
:
req
.
user
.
id
,
isPrivate
:
false
})
// _.set(res, 'locals.siteConfig.lang', pageArgs.locale)
// _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
if
(
!
page
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Page Not Found'
)
return
res
.
status
(
404
).
render
(
'notfound'
,
{
action
:
'history'
})
}
// const page = await WIKI.db.pages.getPageFromDb({
// path: pageArgs.path,
// locale: pageArgs.locale,
// userId: req.user.id,
// isPrivate: false
// })
pageArgs
.
tags
=
_
.
get
(
page
,
'tags'
,
[])
// if (!page) {
// _.set(res.locals, 'pageMeta.title', 'Page Not Found')
// return res.status(404).render('notfound', { action: 'history' })
// }
const
effectivePermissions
=
WIKI
.
auth
.
getEffectivePermissions
(
req
,
pageArgs
)
// pageArgs.tags = _.get(page, 'tags', []
)
if
(
!
effectivePermissions
.
history
.
read
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'history'
})
}
// const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
if
(
page
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
page
.
title
)
_
.
set
(
res
.
locals
,
'pageMeta.description'
,
page
.
description
)
// if (!effectivePermissions.history.read) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'history' })
// }
res
.
render
(
'history'
,
{
page
,
effectivePermissions
})
}
else
{
res
.
redirect
(
`/
${
pageArgs
.
path
}
`
)
}
})
// if (page) {
// _.set(res.locals, 'pageMeta.title', page.title)
// _.set(res.locals, 'pageMeta.description', page.description)
/**
* Page ID redirection
*/
router
.
get
([
'/i'
,
'/i/:id'
],
async
(
req
,
res
,
next
)
=>
{
const
pageId
=
_
.
toSafeInteger
(
req
.
params
.
id
)
if
(
pageId
<=
0
)
{
return
res
.
redirect
(
'/'
)
}
// res.render('history', { page, effectivePermissions })
// } else {
// res.redirect(`/${pageArgs.path}`)
// }
// })
const
page
=
await
WIKI
.
db
.
pages
.
query
().
column
([
'path'
,
'localeCode'
,
'isPrivate'
,
'privateNS'
]).
findById
(
pageId
)
if
(
!
page
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Page Not Found'
)
return
res
.
status
(
404
).
render
(
'notfound'
,
{
action
:
'view'
})
}
// /**
// * Page ID redirection
// */
// router.get(['/i', '/i/:id'], async (req, res, next) => {
// const pageId = _.toSafeInteger(req.params.id)
// if (pageId <= 0) {
// return res.redirect('/')
// }
if
(
!
WIKI
.
auth
.
checkAccess
(
req
.
user
,
[
'read:pages'
],
{
locale
:
page
.
localeCode
,
path
:
page
.
path
,
private
:
page
.
isPrivate
,
privateNS
:
page
.
privateNS
,
explicitLocale
:
false
,
tags
:
page
.
tags
}))
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'view'
})
}
// const page = await WIKI.db.pages.query().column(['path', 'localeCode', 'isPrivate', 'privateNS']).findById(pageId)
// if (!page) {
// _.set(res.locals, 'pageMeta.title', 'Page Not Found')
// return res.status(404).render('notfound', { action: 'view' })
// }
if
(
WIKI
.
config
.
lang
.
namespacing
)
{
return
res
.
redirect
(
`/
${
page
.
localeCode
}
/
${
page
.
path
}
`
)
}
else
{
return
res
.
redirect
(
`/
${
page
.
path
}
`
)
}
})
// if (!WIKI.auth.checkAccess(req.user, ['read:pages'], {
// locale: page.localeCode,
// path: page.path,
// private: page.isPrivate,
// privateNS: page.privateNS,
// explicitLocale: false,
// tags: page.tags
// })) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'view' })
// }
/**
* Source
*/
router
.
get
([
'/s'
,
'/s/*'
],
async
(
req
,
res
,
next
)
=>
{
const
pageArgs
=
pageHelper
.
parsePath
(
req
.
path
,
{
stripExt
:
true
})
const
versionId
=
(
req
.
query
.
v
)
?
_
.
toSafeInteger
(
req
.
query
.
v
)
:
0
const
page
=
await
WIKI
.
db
.
pages
.
getPageFromDb
({
path
:
pageArgs
.
path
,
locale
:
pageArgs
.
locale
,
userId
:
req
.
user
.
id
,
isPrivate
:
false
})
// if (WIKI.config.lang.namespacing) {
// return res.redirect(`/${page.localeCode}/${page.path}`)
// } else {
// return res.redirect(`/${page.path}`)
// }
// })
pageArgs
.
tags
=
_
.
get
(
page
,
'tags'
,
[])
// /**
// * Source
// */
// router.get(['/s', '/s/*'], async (req, res, next) => {
// const pageArgs = pageHelper.parsePath(req.path, { stripExt: true })
// const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0
if
(
WIKI
.
config
.
lang
.
namespacing
&&
!
pageArgs
.
explicitLocale
)
{
return
res
.
redirect
(
`/s/
${
pageArgs
.
locale
}
/
${
pageArgs
.
path
}
`
)
}
// const page = await WIKI.db.pages.getPageFromDb({
// path: pageArgs.path,
// locale: pageArgs.locale,
// userId: req.user.id,
// isPrivate: false
// })
// -> Effective Permissions
const
effectivePermissions
=
WIKI
.
auth
.
getEffectivePermissions
(
req
,
pageArgs
)
// pageArgs.tags = _.get(page, 'tags', [])
_
.
set
(
res
,
'locals.siteConfig.lang'
,
pageArgs
.
locale
)
_
.
set
(
res
,
'locals.siteConfig.rtl'
,
req
.
i18n
.
dir
()
===
'rtl'
)
// if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) {
// return res.redirect(`/s/${pageArgs.locale}/${pageArgs.path}`)
// }
if
(
versionId
>
0
)
{
if
(
!
effectivePermissions
.
history
.
read
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'sourceVersion'
})
}
}
else
{
if
(
!
effectivePermissions
.
source
.
read
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
render
(
'unauthorized'
,
{
action
:
'source'
})
}
}
// // -> Effective Permissions
// const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
// _.set(res, 'locals.siteConfig.lang', pageArgs.locale)
// _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
// if (versionId > 0) {
// if (!effectivePermissions.history.read) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'sourceVersion' })
// }
// } else {
// if (!effectivePermissions.source.read) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.render('unauthorized', { action: 'source' })
// }
// }
if
(
page
)
{
if
(
versionId
>
0
)
{
const
pageVersion
=
await
WIKI
.
db
.
pageHistory
.
getVersion
({
pageId
:
page
.
id
,
versionId
})
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
pageVersion
.
title
)
_
.
set
(
res
.
locals
,
'pageMeta.description'
,
pageVersion
.
description
)
res
.
render
(
'source'
,
{
page
:
{
...
page
,
...
pageVersion
},
effectivePermissions
})
}
else
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
page
.
title
)
_
.
set
(
res
.
locals
,
'pageMeta.description'
,
page
.
description
)
res
.
render
(
'source'
,
{
page
,
effectivePermissions
})
}
}
else
{
res
.
redirect
(
`/
${
pageArgs
.
path
}
`
)
}
})
//
if (page) {
//
if (versionId > 0) {
//
const pageVersion = await WIKI.db.pageHistory.getVersion({ pageId: page.id, versionId })
//
_.set(res.locals, 'pageMeta.title', pageVersion.title)
//
_.set(res.locals, 'pageMeta.description', pageVersion.description)
//
res.render('source', {
//
page: {
//
...page,
//
...pageVersion
//
},
//
effectivePermissions
//
})
//
} else {
//
_.set(res.locals, 'pageMeta.title', page.title)
//
_.set(res.locals, 'pageMeta.description', page.description)
//
res.render('source', { page, effectivePermissions })
//
}
//
} else {
//
res.redirect(`/${pageArgs.path}`)
//
}
//
})
/**
* Tags
*/
router
.
get
([
'/t'
,
'/t/*'
],
(
req
,
res
,
next
)
=>
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Tags'
)
res
.
render
(
'tags'
)
})
/
/ /
**
//
* Tags
//
*/
//
router.get(['/t', '/t/*'], (req, res, next) => {
//
_.set(res.locals, 'pageMeta.title', 'Tags')
//
res.render('tags')
//
})
/**
* User Avatar
...
...
@@ -448,96 +434,100 @@ router.get('/_user/:uid/avatar', async (req, res, next) => {
return
res
.
sendStatus
(
404
)
})
/**
* View document / asset
*/
router
.
get
(
'/*'
,
async
(
req
,
res
,
next
)
=>
{
const
stripExt
=
_
.
some
(
WIKI
.
data
.
pageExtensions
,
ext
=>
_
.
endsWith
(
req
.
path
,
`.
${
ext
}
`
))
const
pageArgs
=
pageHelper
.
parsePath
(
req
.
path
,
{
stripExt
})
const
isPage
=
(
stripExt
||
pageArgs
.
path
.
indexOf
(
'.'
)
===
-
1
)
const
site
=
await
WIKI
.
db
.
sites
.
getSiteByHostname
({
hostname
:
req
.
hostname
})
if
(
!
site
)
{
throw
new
Error
(
'INVALID_SITE'
)
}
if
(
isPage
)
{
// if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) {
// return res.redirect(`/${pageArgs.locale}/${pageArgs.path}`)
// }
// req.i18n.changeLanguage(pageArgs.locale)
try
{
// -> Get Page from cache
const
page
=
await
WIKI
.
db
.
pages
.
getPage
({
siteId
:
site
.
id
,
path
:
pageArgs
.
path
,
locale
:
pageArgs
.
locale
,
userId
:
req
.
user
.
id
})
pageArgs
.
tags
=
_
.
get
(
page
,
'tags'
,
[])
// -> Effective Permissions
const
effectivePermissions
=
WIKI
.
auth
.
getEffectivePermissions
(
req
,
pageArgs
)
// -> Check User Access
if
(
!
effectivePermissions
.
pages
.
read
)
{
if
(
req
.
user
.
id
===
WIKI
.
auth
.
guest
.
id
)
{
res
.
cookie
(
'loginRedirect'
,
req
.
path
,
{
maxAge
:
15
*
60
*
1000
})
}
if
(
pageArgs
.
path
===
'home'
&&
req
.
user
.
id
===
WIKI
.
auth
.
guest
.
id
)
{
return
res
.
redirect
(
'/login'
)
}
return
res
.
redirect
(
`/_error/unauthorized?from=
${
req
.
path
}
`
)
}
// /**
// * View document / asset
// */
// router.get('/*', async (req, res, next) => {
// const stripExt = _.some(WIKI.data.pageExtensions, ext => _.endsWith(req.path, `.${ext}`))
// const pageArgs = pageHelper.parsePath(req.path, { stripExt })
// const isPage = (stripExt || pageArgs.path.indexOf('.') === -1)
// const site = await WIKI.db.sites.getSiteByHostname({ hostname: req.hostname })
// if (!site) {
// throw new Error('INVALID_SITE')
// }
_
.
set
(
res
,
'locals.siteConfig.lang'
,
pageArgs
.
locale
)
// _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
if
(
page
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
page
.
title
)
_
.
set
(
res
.
locals
,
'pageMeta.description'
,
page
.
description
)
// -> Check Publishing State
let
pageIsPublished
=
page
.
isPublished
if
(
pageIsPublished
&&
!
_
.
isEmpty
(
page
.
publishStartDate
))
{
pageIsPublished
=
moment
(
page
.
publishStartDate
).
isSameOrBefore
()
}
if
(
pageIsPublished
&&
!
_
.
isEmpty
(
page
.
publishEndDate
))
{
pageIsPublished
=
moment
(
page
.
publishEndDate
).
isSameOrAfter
()
}
if
(
!
pageIsPublished
&&
!
effectivePermissions
.
pages
.
write
)
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Unauthorized'
)
return
res
.
status
(
403
).
render
(
'unauthorized'
,
{
action
:
'view'
})
}
// -> Render view
res
.
sendFile
(
path
.
join
(
WIKI
.
ROOTPATH
,
'assets/index.html'
))
}
else
if
(
pageArgs
.
path
===
'home'
)
{
res
.
redirect
(
'/_welcome'
)
}
else
{
_
.
set
(
res
.
locals
,
'pageMeta.title'
,
'Page Not Found'
)
if
(
effectivePermissions
.
pages
.
write
)
{
res
.
status
(
404
).
render
(
'new'
,
{
path
:
pageArgs
.
path
,
locale
:
pageArgs
.
locale
})
}
else
{
res
.
status
(
404
).
render
(
'notfound'
,
{
action
:
'view'
})
}
}
}
catch
(
err
)
{
next
(
err
)
}
}
else
{
if
(
!
WIKI
.
auth
.
checkAccess
(
req
.
user
,
[
'read:assets'
],
pageArgs
))
{
return
res
.
sendStatus
(
403
)
}
// if (isPage) {
// // if (WIKI.config.lang.namespacing && !pageArgs.explicitLocale) {
// // return res.redirect(`/${pageArgs.locale}/${pageArgs.path}`)
// // }
// // req.i18n.changeLanguage(pageArgs.locale)
// try {
// // -> Get Page from cache
// const page = await WIKI.db.pages.getPage({
// siteId: site.id,
// path: pageArgs.path,
// locale: pageArgs.locale,
// userId: req.user.id
// })
// pageArgs.tags = _.get(page, 'tags', [])
// // -> Effective Permissions
// const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
// // -> Check User Access
// if (!effectivePermissions.pages.read) {
// if (req.user.id === WIKI.auth.guest.id) {
// res.cookie('loginRedirect', req.path, {
// maxAge: 15 * 60 * 1000
// })
// }
// if (pageArgs.path === 'home' && req.user.id === WIKI.auth.guest.id) {
// return res.redirect('/login')
// }
// return res.redirect(`/_error/unauthorized?from=${req.path}`)
// }
// _.set(res, 'locals.siteConfig.lang', pageArgs.locale)
// // _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
// if (page) {
// _.set(res.locals, 'pageMeta.title', page.title)
// _.set(res.locals, 'pageMeta.description', page.description)
// // -> Check Publishing State
// let pageIsPublished = page.isPublished
// if (pageIsPublished && !_.isEmpty(page.publishStartDate)) {
// pageIsPublished = moment(page.publishStartDate).isSameOrBefore()
// }
// if (pageIsPublished && !_.isEmpty(page.publishEndDate)) {
// pageIsPublished = moment(page.publishEndDate).isSameOrAfter()
// }
// if (!pageIsPublished && !effectivePermissions.pages.write) {
// _.set(res.locals, 'pageMeta.title', 'Unauthorized')
// return res.status(403).render('unauthorized', {
// action: 'view'
// })
// }
// // -> Render view
// res.sendFile(path.join(WIKI.ROOTPATH, 'assets/index.html'))
// } else if (pageArgs.path === 'home') {
// res.redirect('/_welcome')
// } else {
// _.set(res.locals, 'pageMeta.title', 'Page Not Found')
// if (effectivePermissions.pages.write) {
// res.status(404).render('new', { path: pageArgs.path, locale: pageArgs.locale })
// } else {
// res.status(404).render('notfound', { action: 'view' })
// }
// }
// } catch (err) {
// next(err)
// }
// } else {
// if (!WIKI.auth.checkAccess(req.user, ['read:assets'], pageArgs)) {
// return res.sendStatus(403)
// }
// await WIKI.db.assets.getAsset(pageArgs.path, res)
// }
// })
await
WIKI
.
db
.
assets
.
getAsset
(
pageArgs
.
path
,
res
)
}
router
.
get
(
'/*'
,
(
req
,
res
,
next
)
=>
{
res
.
sendFile
(
path
.
join
(
WIKI
.
ROOTPATH
,
'assets/index.html'
))
})
module
.
exports
=
router
server/web.js
View file @
9a92789d
...
...
@@ -74,17 +74,13 @@ module.exports = async () => {
index
:
false
,
maxAge
:
'7d'
}))
app
.
use
(
'/_assets
-legacy
/svg/twemoji'
,
async
(
req
,
res
,
next
)
=>
{
app
.
use
(
'/_assets/svg/twemoji'
,
async
(
req
,
res
,
next
)
=>
{
try
{
WIKI
.
asar
.
serve
(
'twemoji'
,
req
,
res
,
next
)
}
catch
(
err
)
{
res
.
sendStatus
(
404
)
}
})
app
.
use
(
'/_assets-legacy'
,
express
.
static
(
path
.
join
(
WIKI
.
ROOTPATH
,
'assets-legacy'
),
{
index
:
false
,
maxAge
:
'7d'
}))
// ----------------------------------------
// SSL Handlers
...
...
ux/src/components/HeaderNav.vue
View file @
9a92789d
...
...
@@ -27,6 +27,7 @@ q-header.bg-header.text-white.site-header(
q-toolbar.gt-sm(
style='height: 64px;'
dark
v-if='siteStore.features.search'
)
q-input(
dark
...
...
ux/src/components/PageHeader.vue
View file @
9a92789d
...
...
@@ -126,6 +126,17 @@
@click='discardChanges'
)
q-btn.acrylic-btn(
v-if='editorStore.mode === `create`'
flat
icon='las la-check'
color='positive'
label='Create Page'
aria-label='Create Page'
no-caps
@click='createPage'
)
q-btn.acrylic-btn(
v-else
flat
icon='las la-check'
color='positive'
...
...
@@ -246,10 +257,49 @@ async function saveChanges () {
$q
.
loading
.
hide
()
}
function
editPage
()
{
async
function
createPage
()
{
$q
.
dialog
({
component
:
defineAsyncComponent
(()
=>
import
(
'../components/TreeBrowserDialog.vue'
)),
componentProps
:
{
mode
:
'createPage'
,
folderPath
:
''
,
itemTitle
:
pageStore
.
title
,
itemFileName
:
pageStore
.
path
}
}).
onOk
(
async
({
path
,
title
})
=>
{
$q
.
loading
.
show
()
try
{
pageStore
.
$patch
({
title
,
path
})
await
pageStore
.
pageSave
()
$q
.
notify
({
type
:
'positive'
,
message
:
'Page created successfully.'
})
editorStore
.
$patch
({
isActive
:
false
})
}
catch
(
err
)
{
$q
.
notify
({
type
:
'negative'
,
message
:
'Failed to create page.'
,
caption
:
err
.
message
})
}
$q
.
loading
.
hide
()
})
}
async
function
editPage
()
{
$q
.
loading
.
show
()
await
pageStore
.
pageLoad
({
id
:
pageStore
.
id
,
withContent
:
true
})
editorStore
.
$patch
({
isActive
:
true
,
editor
:
'markdown'
mode
:
'edit'
,
editor
:
pageStore
.
editor
})
$q
.
loading
.
hide
()
}
</
script
>
ux/src/components/TreeBrowserDialog.vue
View file @
9a92789d
...
...
@@ -230,7 +230,10 @@ const files = computed(() => {
// METHODS
async
function
save
()
{
onDialogOK
()
onDialogOK
({
title
:
state
.
title
,
path
:
state
.
path
})
}
async
function
treeLazyLoad
(
nodeId
,
{
done
,
fail
})
{
...
...
ux/src/components/WelcomeOverlay.vue
View file @
9a92789d
...
...
@@ -93,7 +93,7 @@ function createHomePage (editor) {
pageStore
.
pageCreate
({
editor
,
locale
:
'en'
,
path
:
''
,
path
:
'
home
'
,
title
:
t
(
'welcome.homeDefault.title'
),
description
:
t
(
'welcome.homeDefault.description'
),
content
:
t
(
'welcome.homeDefault.content'
)
...
...
ux/src/pages/AdminGeneral.vue
View file @
9a92789d
...
...
@@ -752,12 +752,7 @@ async function save () {
})
await
adminStore
.
fetchSites
()
if
(
adminStore
.
currentSiteId
===
siteStore
.
id
)
{
siteStore
.
$patch
({
title
:
state
.
config
.
title
,
description
:
state
.
config
.
description
,
company
:
state
.
config
.
company
,
contentLicense
:
state
.
config
.
contentLicense
})
siteStore
.
loadSite
(
window
.
location
.
hostname
)
}
}
catch
(
err
)
{
$q
.
notify
({
...
...
ux/src/stores/page.js
View file @
9a92789d
...
...
@@ -78,6 +78,34 @@ const gqlQueries = {
}
}
${
pagePropsFragment
}
`
,
pageByIdWithContent
:
gql
`
query loadPageWithContent (
$id: UUID!
) {
pageById(
id: $id
) {
...PageRead,
content
}
}
${
pagePropsFragment
}
`
,
pageByPathWithContent
:
gql
`
query loadPageWithContent (
$siteId: UUID!
$path: String!
) {
pageByPath(
siteId: $siteId
path: $path
) {
...PageRead,
content
}
}
${
pagePropsFragment
}
`
}
...
...
@@ -92,6 +120,7 @@ export const usePageStore = defineStore('page', {
content
:
''
,
createdAt
:
''
,
description
:
''
,
editor
:
''
,
icon
:
'las la-file-alt'
,
id
:
''
,
isBrowsable
:
true
,
...
...
@@ -140,12 +169,18 @@ export const usePageStore = defineStore('page', {
/**
* PAGE - LOAD
*/
async
pageLoad
({
path
,
id
})
{
async
pageLoad
({
path
,
id
,
withContent
=
false
})
{
const
editorStore
=
useEditorStore
()
const
siteStore
=
useSiteStore
()
try
{
let
query
if
(
withContent
)
{
query
=
id
?
gqlQueries
.
pageByIdWithContent
:
gqlQueries
.
pageByPathWithContent
}
else
{
query
=
id
?
gqlQueries
.
pageById
:
gqlQueries
.
pageByPath
}
const
resp
=
await
APOLLO_CLIENT
.
query
({
query
:
id
?
gqlQueries
.
pageById
:
gqlQueries
.
pageByPath
,
query
,
variables
:
id
?
{
id
}
:
{
siteId
:
siteStore
.
id
,
path
},
fetchPolicy
:
'network-only'
})
...
...
@@ -221,56 +256,157 @@ export const usePageStore = defineStore('page', {
*/
async
pageSave
()
{
const
editorStore
=
useEditorStore
()
const
siteStore
=
useSiteStore
()
try
{
const
resp
=
await
APOLLO_CLIENT
.
mutate
({
mutation
:
gql
`
mutation savePage (
$id: UUID!
$patch: PageUpdateInput!
) {
updatePage (
id: $id
patch: $patch
if
(
editorStore
.
mode
===
'create'
)
{
const
resp
=
await
APOLLO_CLIENT
.
mutate
({
mutation
:
gql
`
mutation createPage (
$allowComments: Boolean
$allowContributions: Boolean
$allowRatings: Boolean
$content: String!
$description: String!
$editor: String!
$icon: String
$isBrowsable: Boolean
$locale: String!
$path: String!
$publishState: PagePublishState!
$publishEndDate: Date
$publishStartDate: Date
$relations: [PageRelationInput!]
$scriptCss: String
$scriptJsLoad: String
$scriptJsUnload: String
$showSidebar: Boolean
$showTags: Boolean
$showToc: Boolean
$siteId: UUID!
$tags: [String!]
$title: String!
$tocDepth: PageTocDepthInput
) {
operation {
succeeded
message
createPage (
allowComments: $allowComments
allowContributions: $allowContributions
allowRatings: $allowRatings
content: $content
description: $description
editor: $editor
icon: $icon
isBrowsable: $isBrowsable
locale: $locale
path: $path
publishState: $publishState
publishEndDate: $publishEndDate
publishStartDate: $publishStartDate
relations: $relations
scriptCss: $scriptCss
scriptJsLoad: $scriptJsLoad
scriptJsUnload: $scriptJsUnload
showSidebar: $showSidebar
showTags: $showTags
showToc: $showToc
siteId: $siteId
tags: $tags
title: $title
tocDepth: $tocDepth
) {
operation {
succeeded
message
}
}
}
`
,
variables
:
{
...
pick
(
this
,
[
'allowComments'
,
'allowContributions'
,
'allowRatings'
,
'content'
,
'description'
,
'icon'
,
'isBrowsable'
,
'locale'
,
'password'
,
'path'
,
'publishEndDate'
,
'publishStartDate'
,
'publishState'
,
'relations'
,
'scriptJsLoad'
,
'scriptJsUnload'
,
'scriptCss'
,
'showSidebar'
,
'showTags'
,
'showToc'
,
'tags'
,
'title'
,
'tocDepth'
]),
editor
:
editorStore
.
editor
,
siteId
:
siteStore
.
id
}
`
,
variables
:
{
id
:
this
.
id
,
patch
:
pick
(
this
,
[
'allowComments'
,
'allowContributions'
,
'allowRatings'
,
// 'content',
'description'
,
'icon'
,
'isBrowsable'
,
'locale'
,
'password'
,
'path'
,
'publishEndDate'
,
'publishStartDate'
,
'publishState'
,
'relations'
,
'scriptJsLoad'
,
'scriptJsUnload'
,
'scriptCss'
,
'showSidebar'
,
'showTags'
,
'showToc'
,
'tags'
,
'title'
,
'tocDepth'
])
})
const
result
=
resp
?.
data
?.
createPage
?.
operation
??
{}
if
(
!
result
.
succeeded
)
{
throw
new
Error
(
result
.
message
)
}
this
.
id
=
resp
.
data
.
createPage
.
page
.
id
this
.
editor
=
editorStore
.
editor
}
else
{
const
resp
=
await
APOLLO_CLIENT
.
mutate
({
mutation
:
gql
`
mutation savePage (
$id: UUID!
$patch: PageUpdateInput!
) {
updatePage (
id: $id
patch: $patch
) {
operation {
succeeded
message
}
}
}
`
,
variables
:
{
id
:
this
.
id
,
patch
:
pick
(
this
,
[
'allowComments'
,
'allowContributions'
,
'allowRatings'
,
'content'
,
'description'
,
'icon'
,
'isBrowsable'
,
'locale'
,
'password'
,
'path'
,
'publishEndDate'
,
'publishStartDate'
,
'publishState'
,
'relations'
,
'scriptJsLoad'
,
'scriptJsUnload'
,
'scriptCss'
,
'showSidebar'
,
'showTags'
,
'showToc'
,
'tags'
,
'title'
,
'tocDepth'
])
}
})
const
result
=
resp
?.
data
?.
updatePage
?.
operation
??
{}
if
(
!
result
.
succeeded
)
{
throw
new
Error
(
result
.
message
)
}
})
const
result
=
resp
?.
data
?.
updatePage
?.
operation
??
{}
if
(
!
result
.
succeeded
)
{
throw
new
Error
(
result
.
message
)
}
// Update editor state timestamps
const
curDate
=
DateTime
.
utc
()
...
...
ux/src/stores/site.js
View file @
9a92789d
...
...
@@ -26,7 +26,9 @@ export const useSiteStore = defineStore('site', {
showSidebar
:
true
,
overlay
:
null
,
features
:
{
ratingsMode
:
'off'
ratingsMode
:
'off'
,
reasonForChange
:
'required'
,
search
:
false
},
editors
:
{
asciidoc
:
false
,
...
...
@@ -87,6 +89,8 @@ export const useSiteStore = defineStore('site', {
footerExtra
features {
ratingsMode
reasonForChange
search
}
editors {
asciidoc {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment