feat: page Rules access check

This commit is contained in:
Nicolas Giard
2019-01-12 18:33:30 -05:00
parent 75eb277401
commit 7e62c01ed1
34 changed files with 581 additions and 725 deletions

View File

@@ -2,41 +2,41 @@
/* global WIKI */
module.exports = {
Query: {
comments(obj, args, context, info) {
return WIKI.models.Comment.findAll({ where: args })
}
},
Mutation: {
createComment(obj, args) {
return WIKI.models.Comment.create({
content: args.content,
author: args.userId,
document: args.documentId
})
},
deleteComment(obj, args) {
return WIKI.models.Comment.destroy({
where: {
id: args.id
},
limit: 1
})
},
modifyComment(obj, args) {
return WIKI.models.Comment.update({
content: args.content
}, {
where: { id: args.id }
})
}
},
Comment: {
author(cm) {
return cm.getAuthor()
},
document(cm) {
return cm.getDocument()
}
}
// Query: {
// comments(obj, args, context, info) {
// return WIKI.models.Comment.findAll({ where: args })
// }
// },
// Mutation: {
// createComment(obj, args) {
// return WIKI.models.Comment.create({
// content: args.content,
// author: args.userId,
// document: args.documentId
// })
// },
// deleteComment(obj, args) {
// return WIKI.models.Comment.destroy({
// where: {
// id: args.id
// },
// limit: 1
// })
// },
// modifyComment(obj, args) {
// return WIKI.models.Comment.update({
// content: args.content
// }, {
// where: { id: args.id }
// })
// }
// },
// Comment: {
// author(cm) {
// return cm.getAuthor()
// },
// document(cm) {
// return cm.getDocument()
// }
// }
}

View File

@@ -1,46 +0,0 @@
/* global WIKI */
module.exports = {
Query: {
documents(obj, args, context, info) {
return WIKI.models.Document.findAll({ where: args })
}
},
Mutation: {
createDocument(obj, args) {
return WIKI.models.Document.create(args)
},
deleteDocument(obj, args) {
return WIKI.models.Document.destroy({
where: {
id: args.id
},
limit: 1
})
},
modifyDocument(obj, args) {
return WIKI.models.Document.update({
title: args.title,
subtitle: args.subtitle
}, {
where: { id: args.id }
})
},
moveDocument(obj, args) {
return WIKI.models.Document.update({
path: args.path
}, {
where: { id: args.id }
})
}
},
Document: {
comments(doc) {
return doc.getComments()
},
tags(doc) {
return doc.getTags()
}
}
}

View File

@@ -4,48 +4,48 @@
const gql = require('graphql')
module.exports = {
Query: {
files(obj, args, context, info) {
return WIKI.models.File.findAll({ where: args })
}
},
Mutation: {
uploadFile(obj, args) {
// todo
return WIKI.models.File.create(args)
},
deleteFile(obj, args) {
return WIKI.models.File.destroy({
where: {
id: args.id
},
limit: 1
})
},
renameFile(obj, args) {
return WIKI.models.File.update({
filename: args.filename
}, {
where: { id: args.id }
})
},
moveFile(obj, args) {
return WIKI.models.File.findById(args.fileId).then(fl => {
if (!fl) {
throw new gql.GraphQLError('Invalid File ID')
}
return WIKI.models.Folder.findById(args.folderId).then(fld => {
if (!fld) {
throw new gql.GraphQLError('Invalid Folder ID')
}
return fl.setFolder(fld)
})
})
}
},
File: {
folder(fl) {
return fl.getFolder()
}
}
// Query: {
// files(obj, args, context, info) {
// return WIKI.models.File.findAll({ where: args })
// }
// },
// Mutation: {
// uploadFile(obj, args) {
// // todo
// return WIKI.models.File.create(args)
// },
// deleteFile(obj, args) {
// return WIKI.models.File.destroy({
// where: {
// id: args.id
// },
// limit: 1
// })
// },
// renameFile(obj, args) {
// return WIKI.models.File.update({
// filename: args.filename
// }, {
// where: { id: args.id }
// })
// },
// moveFile(obj, args) {
// return WIKI.models.File.findById(args.fileId).then(fl => {
// if (!fl) {
// throw new gql.GraphQLError('Invalid File ID')
// }
// return WIKI.models.Folder.findById(args.folderId).then(fld => {
// if (!fld) {
// throw new gql.GraphQLError('Invalid Folder ID')
// }
// return fl.setFolder(fld)
// })
// })
// }
// },
// File: {
// folder(fl) {
// return fl.getFolder()
// }
// }
}

View File

@@ -2,34 +2,34 @@
/* global WIKI */
module.exports = {
Query: {
folders(obj, args, context, info) {
return WIKI.models.Folder.findAll({ where: args })
}
},
Mutation: {
createFolder(obj, args) {
return WIKI.models.Folder.create(args)
},
deleteFolder(obj, args) {
return WIKI.models.Folder.destroy({
where: {
id: args.id
},
limit: 1
})
},
renameFolder(obj, args) {
return WIKI.models.Folder.update({
name: args.name
}, {
where: { id: args.id }
})
}
},
Folder: {
files(grp) {
return grp.getFiles()
}
}
// Query: {
// folders(obj, args, context, info) {
// return WIKI.models.Folder.findAll({ where: args })
// }
// },
// Mutation: {
// createFolder(obj, args) {
// return WIKI.models.Folder.create(args)
// },
// deleteFolder(obj, args) {
// return WIKI.models.Folder.destroy({
// where: {
// id: args.id
// },
// limit: 1
// })
// },
// renameFolder(obj, args) {
// return WIKI.models.Folder.update({
// name: args.name
// }, {
// where: { id: args.id }
// })
// }
// },
// Folder: {
// files(grp) {
// return grp.getFiles()
// }
// }
}

View File

@@ -1,4 +1,5 @@
const graphHelper = require('../../helpers/graph')
const safeRegex = require('safe-regex')
/* global WIKI */
@@ -44,6 +45,7 @@ module.exports = {
pageRules: JSON.stringify([]),
isSystem: false
})
await WIKI.auth.reloadGroups()
return {
responseResult: graphHelper.generateSuccess('Group created successfully.'),
group
@@ -51,6 +53,7 @@ module.exports = {
},
async delete(obj, args) {
await WIKI.models.groups.query().deleteById(args.id)
await WIKI.auth.reloadGroups()
return {
responseResult: graphHelper.generateSuccess('Group has been deleted.')
}
@@ -70,11 +73,20 @@ module.exports = {
}
},
async update(obj, args) {
if(_.some(args.pageRules, pr => {
return pr.match !== 'REGEX' || safeRegex(pr.path)
})) {
throw new gql.GraphQLError('Some Page Rules contains unsafe or exponential time regex.')
}
await WIKI.models.groups.query().patch({
name: args.name,
permissions: JSON.stringify(args.permissions),
pageRules: JSON.stringify(args.pageRules)
}).where('id', args.id)
await WIKI.auth.reloadGroups()
return {
responseResult: graphHelper.generateSuccess('Group has been updated.')
}

View File

@@ -31,6 +31,9 @@ module.exports = {
namespacing: WIKI.config.lang.namespacing,
namespaces: WIKI.config.lang.namespaces
}
},
translations (obj, args, context, info) {
return WIKI.lang.getByNamespace(args.locale, args.namespace)
}
},
LocalizationMutation: {

View File

@@ -16,15 +16,6 @@ module.exports = {
offsetPage: args.offsetPage || 0,
offsetSize: args.offsetSize || 100
})
},
async list(obj, args, context, info) {
return WIKI.models.pages.query().select(
'pages.*',
WIKI.models.pages.relatedQuery('users').count().as('userCount')
)
},
async single(obj, args, context, info) {
return WIKI.models.pages.query().findById(args.id)
}
},
PageMutation: {

View File

@@ -1,53 +0,0 @@
/* global WIKI */
const gql = require('graphql')
module.exports = {
Query: {
rights(obj, args, context, info) {
return WIKI.models.Right.findAll({ where: args })
}
},
Mutation: {
addRightToGroup(obj, args) {
return WIKI.models.Group.findById(args.groupId).then(grp => {
if (!grp) {
throw new gql.GraphQLError('Invalid Group ID')
}
return WIKI.models.Right.create({
path: args.path,
role: args.role,
exact: args.exact,
allow: args.allow,
group: grp
})
})
},
removeRightFromGroup(obj, args) {
return WIKI.models.Right.destroy({
where: {
id: args.rightId
},
limit: 1
})
},
modifyRight(obj, args) {
return WIKI.models.Right.update({
path: args.path,
role: args.role,
exact: args.exact,
allow: args.allow
}, {
where: {
id: args.id
}
})
}
},
Right: {
group(rt) {
return rt.getGroup()
}
}
}

View File

@@ -1,24 +0,0 @@
/* global WIKI */
const _ = require('lodash')
module.exports = {
Query: {
settings(obj, args, context, info) {
return WIKI.models.Setting.findAll({ where: args, raw: true }).then(entries => {
return _.map(entries, entry => {
entry.config = JSON.stringify(entry.config)
return entry
})
})
}
},
Mutation: {
setConfigEntry(obj, args) {
return WIKI.models.Setting.update({
value: args.value
}, { where: { key: args.key } })
}
}
}

View File

@@ -20,13 +20,9 @@ module.exports = {
Query: {
async system() { return {} }
},
Mutation: {
async system() { return {} }
},
SystemQuery: {
async info() { return {} }
},
SystemMutation: { },
SystemInfo: {
configFile() {
return path.join(process.cwd(), 'config.yml')

View File

@@ -4,60 +4,60 @@
const gql = require('graphql')
module.exports = {
Query: {
tags(obj, args, context, info) {
return WIKI.models.Tag.findAll({ where: args })
}
},
Mutation: {
assignTagToDocument(obj, args) {
return WIKI.models.Tag.findById(args.tagId).then(tag => {
if (!tag) {
throw new gql.GraphQLError('Invalid Tag ID')
}
return WIKI.models.Document.findById(args.documentId).then(doc => {
if (!doc) {
throw new gql.GraphQLError('Invalid Document ID')
}
return tag.addDocument(doc)
})
})
},
createTag(obj, args) {
return WIKI.models.Tag.create(args)
},
deleteTag(obj, args) {
return WIKI.models.Tag.destroy({
where: {
id: args.id
},
limit: 1
})
},
removeTagFromDocument(obj, args) {
return WIKI.models.Tag.findById(args.tagId).then(tag => {
if (!tag) {
throw new gql.GraphQLError('Invalid Tag ID')
}
return WIKI.models.Document.findById(args.documentId).then(doc => {
if (!doc) {
throw new gql.GraphQLError('Invalid Document ID')
}
return tag.removeDocument(doc)
})
})
},
renameTag(obj, args) {
return WIKI.models.Group.update({
key: args.key
}, {
where: { id: args.id }
})
}
},
Tag: {
documents(tag) {
return tag.getDocuments()
}
}
// Query: {
// tags(obj, args, context, info) {
// return WIKI.models.Tag.findAll({ where: args })
// }
// },
// Mutation: {
// assignTagToDocument(obj, args) {
// return WIKI.models.Tag.findById(args.tagId).then(tag => {
// if (!tag) {
// throw new gql.GraphQLError('Invalid Tag ID')
// }
// return WIKI.models.Document.findById(args.documentId).then(doc => {
// if (!doc) {
// throw new gql.GraphQLError('Invalid Document ID')
// }
// return tag.addDocument(doc)
// })
// })
// },
// createTag(obj, args) {
// return WIKI.models.Tag.create(args)
// },
// deleteTag(obj, args) {
// return WIKI.models.Tag.destroy({
// where: {
// id: args.id
// },
// limit: 1
// })
// },
// removeTagFromDocument(obj, args) {
// return WIKI.models.Tag.findById(args.tagId).then(tag => {
// if (!tag) {
// throw new gql.GraphQLError('Invalid Tag ID')
// }
// return WIKI.models.Document.findById(args.documentId).then(doc => {
// if (!doc) {
// throw new gql.GraphQLError('Invalid Document ID')
// }
// return tag.removeDocument(doc)
// })
// })
// },
// renameTag(obj, args) {
// return WIKI.models.Group.update({
// key: args.key
// }, {
// where: { id: args.id }
// })
// }
// },
// Tag: {
// documents(tag) {
// return tag.getDocuments()
// }
// }
}

View File

@@ -1,12 +0,0 @@
/* global WIKI */
module.exports = {
Query: {
translations (obj, args, context, info) {
return WIKI.lang.getByNamespace(args.locale, args.namespace)
}
},
Mutation: {},
Translation: {}
}

View File

@@ -22,7 +22,6 @@ module.exports = {
},
async single(obj, args, context, info) {
let usr = await WIKI.models.users.query().findById(args.id)
console.info(usr)
usr.password = ''
usr.tfaSecret = ''
return usr

View File

@@ -1,37 +1,32 @@
# ENUMS
enum FileType {
binary
image
}
enum RightRole {
read
write
manage
}
# ====================== #
# Wiki.js GraphQL Schema #
# ====================== #
# DIRECTIVES
# ----------
directive @auth(requires: [String]) on QUERY | FIELD_DEFINITION | ARGUMENT_DEFINITION
# TYPES
# -----
# Generic Key Value Pair
type KeyValuePair {
key: String!
value: String!
}
# General Key Value Pair Input
input KeyValuePairInput {
key: String!
value: String!
}
# Generic Mutation Response
type DefaultResponse {
responseResult: ResponseStatus
}
# Mutation Status
type ResponseStatus {
succeeded: Boolean!
errorCode: Int!
@@ -39,220 +34,14 @@ type ResponseStatus {
message: String
}
type Comment {
id: Int!
createdAt: Date
updatedAt: Date
content: String
document: Document!
author: User!
}
type Document {
id: Int!
createdAt: Date
updatedAt: Date
path: String!
title: String!
subtitle: String
parentPath: String
parentTitle: String
isDirectory: Boolean!
isEntry: Boolean!
searchContent: String
comments: [Comment]
tags: [Tag]
}
type File {
id: Int!
createdAt: Date
updatedAt: Date
category: FileType!
mime: String!
extra: String
filename: String!
basename: String!
filesize: Int!
folder: Folder
}
type Folder {
id: Int!
createdAt: Date
updatedAt: Date
name: String!
files: [File]
}
type Right {
id: Int!
createdAt: Date
updatedAt: Date
path: String!
role: RightRole!
exact: Boolean!
allow: Boolean!
group: Group!
}
type Setting {
id: Int!
createdAt: Date
updatedAt: Date
key: String!
config: String!
}
# Tags are attached to one or more documents
type Tag {
id: Int!
createdAt: Date
updatedAt: Date
key: String!
documents: [Document]
}
type Translation {
key: String!
value: String!
}
type OperationResult {
succeeded: Boolean!
message: String
data: String
}
# ROOT
# ----
# Query (Read)
type Query {
comments(id: Int): [Comment]
documents(id: Int, path: String): [Document]
files(id: Int): [File]
folders(id: Int, name: String): [Folder]
rights(id: Int): [Right]
settings(key: String): [Setting]
tags(key: String): [Tag]
translations(locale: String!, namespace: String!): [Translation]
}
type Query
# Mutations (Create, Update, Delete)
type Mutation {
addRightToGroup(
groupId: Int!
path: String!
role: RightRole!
exact: Boolean!
allow: Boolean!
): Right
assignTagToDocument(
tagId: Int!
documentId: Int!
): OperationResult
createComment(
userId: Int!
documentId: Int!
content: String!
): Comment
createDocument(
path: String!
title: String!
subtitle: String
): Document
createFolder(
name: String!
): Folder
createTag(
name: String!
): Tag
deleteComment(
id: Int!
): OperationResult
deleteDocument(
id: Int!
): OperationResult
deleteFile(
id: Int!
): OperationResult
deleteFolder(
id: Int!
): OperationResult
deleteTag(
id: Int!
): OperationResult
modifyComment(
id: Int!
content: String!
): Document
modifyDocument(
id: Int!
title: String
subtitle: String
): Document
modifyRight(
id: Int!
path: String
role: RightRole
exact: Boolean
allow: Boolean
): Right
moveDocument(
id: Int!
path: String!
): OperationResult
moveFile(
id: Int!
folderId: Int!
): OperationResult
renameFile(
id: Int!
name: String!
): OperationResult
renameFolder(
id: Int!
name: String!
): OperationResult
renameTag(
id: Int!
key: String!
): OperationResult
removeTagFromDocument(
tagId: Int!
documentId: Int!
): OperationResult
removeRightFromGroup(
rightId: Int!
): OperationResult
setConfigEntry(
key: String!
value: String!
): OperationResult
uploadFile(
category: FileType!
filename: String!
): File
}
type Mutation
# Subscriptions (Push, Real-time)
type Subscription

View File

@@ -89,7 +89,7 @@ type PageRule {
id: String!
deny: Boolean!
match: PageRuleMatch!
roles: [PageRuleRole]!
roles: [String]!
path: String!
locales: [String]!
}
@@ -98,24 +98,11 @@ input PageRuleInput {
id: String!
deny: Boolean!
match: PageRuleMatch!
roles: [PageRuleRole]!
roles: [String]!
path: String!
locales: [String]!
}
enum PageRuleRole {
READ
WRITE
MANAGE
DELETE
AS_READ
AS_WRITE
AS_MANAGE
CM_READ
CM_WRITE
CM_MANAGE
}
enum PageRuleMatch {
START
EXACT

View File

@@ -17,6 +17,7 @@ extend type Mutation {
type LocalizationQuery {
locales: [LocalizationLocale]
config: LocalizationConfig
translations(locale: String!, namespace: String!): [Translation]
}
# -----------------------------------------------
@@ -57,3 +58,8 @@ type LocalizationConfig {
namespacing: Boolean!
namespaces: [String]!
}
type Translation {
key: String!
value: String!
}

View File

@@ -19,19 +19,7 @@ type PageQuery {
id: Int!
offsetPage: Int
offsetSize: Int
): PageHistoryResult
list(
filter: String
orderBy: String
): [PageMinimal]
single(
id: Int
path: String
locale: String
isPrivate: Boolean
): Page
): PageHistoryResult @auth(requires: ["manage:system", "read:pages"])
}
# -----------------------------------------------
@@ -82,21 +70,8 @@ type PageResponse {
page: Page
}
type PageMinimal {
id: Int!
name: String!
userCount: Int
createdAt: Date!
updatedAt: Date!
}
type Page {
id: Int!
name: String!
rights: [Right]
users: [User]
createdAt: Date!
updatedAt: Date!
}
type PageHistory {

View File

@@ -49,7 +49,7 @@ type SiteConfig {
description: String!
robots: [String]!
analyticsService: String!
analyticsId: String!
analyticsId: String!
company: String!
hasLogo: Boolean!
logoIsSquare: Boolean!

View File

@@ -6,50 +6,42 @@ extend type Query {
system: SystemQuery
}
extend type Mutation {
system: SystemMutation
}
# -----------------------------------------------
# QUERIES
# -----------------------------------------------
type SystemQuery {
info: SystemInfo @auth(requires: ["manage:system"])
info: SystemInfo
}
# -----------------------------------------------
# MUTATIONS
# -----------------------------------------------
type SystemMutation {
todo: String
}
# -----------------------------------------------
# TYPES
# -----------------------------------------------
type SystemInfo {
configFile: String
cpuCores: Int
currentVersion: String
dbHost: String
dbType: String
dbVersion: String
groupsTotal: Int
hostname: String
latestVersion: String
latestVersionReleaseDate: Date
nodeVersion: String
operatingSystem: String
pagesTotal: Int
platform: String
ramTotal: String
redisHost: String
redisTotalRAM: String
redisUsedRAM: String
redisVersion: String
usersTotal: Int
workingDirectory: String
configFile: String @auth(requires: ["manage:system"])
cpuCores: Int @auth(requires: ["manage:system"])
currentVersion: String @auth(requires: ["manage:system"])
dbHost: String @auth(requires: ["manage:system"])
dbType: String @auth(requires: ["manage:system"])
dbVersion: String @auth(requires: ["manage:system"])
groupsTotal: Int @auth(requires: ["manage:system", "manage:navigation", "manage:groups", "write:groups", "manage:users", "write:users"])
hostname: String @auth(requires: ["manage:system"])
latestVersion: String @auth(requires: ["manage:system"])
latestVersionReleaseDate: Date @auth(requires: ["manage:system"])
nodeVersion: String @auth(requires: ["manage:system"])
operatingSystem: String @auth(requires: ["manage:system"])
pagesTotal: Int @auth(requires: ["manage:system", "manage:navigation", "manage:pages", "delete:pages"])
platform: String @auth(requires: ["manage:system"])
ramTotal: String @auth(requires: ["manage:system"])
redisHost: String @auth(requires: ["manage:system"])
redisTotalRAM: String @auth(requires: ["manage:system"])
redisUsedRAM: String @auth(requires: ["manage:system"])
redisVersion: String @auth(requires: ["manage:system"])
usersTotal: Int @auth(requires: ["manage:system", "manage:navigation", "manage:groups", "write:groups", "manage:users", "write:users"])
workingDirectory: String @auth(requires: ["manage:system"])
}