Permissions refactor; create sharing API; update dependencies
This commit is contained in:
@@ -19,7 +19,7 @@ class File extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -44,7 +44,7 @@ class File extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -53,7 +53,7 @@ class File extends Controller {
|
||||
|
||||
const group = await FileGroup.findOne({UUID: req.params.FilesId})
|
||||
if ( !group ) return res.status(404).message('Invalid file group.').api({})
|
||||
if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
const File = this.models.get('upload::File')
|
||||
const files = await File.find({_id: {$in: group.FileIds.map(x => ObjectId(x))}})
|
||||
@@ -67,7 +67,7 @@ class File extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -76,7 +76,7 @@ class File extends Controller {
|
||||
|
||||
const group = await FileGroup.findOne({UUID: req.params.FilesId})
|
||||
if ( !group ) return res.status(404).message('Invalid file group.').api({})
|
||||
if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
if ( req.uploads.uploaded_file ) {
|
||||
group.FileIds.push(req.uploads.uploaded_file.id)
|
||||
@@ -91,7 +91,7 @@ class File extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -100,7 +100,7 @@ class File extends Controller {
|
||||
|
||||
const group = await FileGroup.findOne({UUID: req.params.FilesId})
|
||||
if ( !group ) return res.status(404).message('Invalid file group.').api({})
|
||||
if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
if ( !group.FileIds.includes(req.params.FileId) ) {
|
||||
return req.security.deny()
|
||||
@@ -118,7 +118,7 @@ class File extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -127,7 +127,7 @@ class File extends Controller {
|
||||
|
||||
const group = await FileGroup.findOne({UUID: req.params.FilesId})
|
||||
if ( !group ) return res.status(404).message('Invalid file group.').api({})
|
||||
if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !group.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
await group.delete()
|
||||
return res.api({})
|
||||
|
||||
@@ -15,7 +15,7 @@ class FormCode extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -37,7 +37,7 @@ class FormCode extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -55,7 +55,7 @@ class FormCode extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -78,7 +78,7 @@ class FormCode extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -43,7 +43,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -53,7 +53,7 @@ class FormDatabase extends Controller {
|
||||
const DatabaseId = req.params.DatabaseId
|
||||
const db = await Database.findOne({UUID: DatabaseId})
|
||||
if ( !db ) return res.status(404).message('Database not found with that ID.').api({})
|
||||
if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
return res.api(db)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -73,7 +73,7 @@ class FormDatabase extends Controller {
|
||||
const DatabaseId = req.params.DatabaseId
|
||||
const db = await Database.findOne({UUID: DatabaseId})
|
||||
if ( !db ) return res.status(404).message('Database not found with that ID.').api({})
|
||||
if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
const columns = await ColumnDef.find({ DatabaseId: db.UUID })
|
||||
return res.api(columns)
|
||||
@@ -84,7 +84,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -94,7 +94,7 @@ class FormDatabase extends Controller {
|
||||
const DatabaseId = req.params.DatabaseId
|
||||
const db = await Database.findOne({UUID: DatabaseId})
|
||||
if ( !db ) return res.status(404).message('Database not found with that ID.').api({})
|
||||
if ( !db.accessible_by(req.user, 'update') ) return req.security.deny()
|
||||
// if ( !db.accessible_by(req.user, 'update') ) return req.security.deny()
|
||||
|
||||
const existing_columns = await ColumnDef.find({ DatabaseId: db.UUID })
|
||||
const assoc_columns = []
|
||||
@@ -136,7 +136,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -146,7 +146,7 @@ class FormDatabase extends Controller {
|
||||
const DatabaseId = req.params.DatabaseId
|
||||
const db = await Database.findOne({UUID: DatabaseId})
|
||||
if ( !db ) return res.status(404).message('Database not found with that ID.').api({})
|
||||
if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
const entries = await DBEntry.find({DatabaseId: db.UUID})
|
||||
entries.forEach(entry => entry.RowData.UUID = entry.UUID)
|
||||
@@ -159,7 +159,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -169,7 +169,7 @@ class FormDatabase extends Controller {
|
||||
const DatabaseId = req.params.DatabaseId
|
||||
const db = await Database.findOne({UUID: DatabaseId})
|
||||
if ( !db ) return res.status(404).message('Database not found with that ID.').api({})
|
||||
if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
await DBEntry.deleteMany({DatabaseId: db.UUID})
|
||||
|
||||
@@ -193,7 +193,7 @@ class FormDatabase extends Controller {
|
||||
|
||||
let page = await Page.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
|
||||
const NodeId = req.params.NodeId
|
||||
|
||||
@@ -203,7 +203,7 @@ class FormDatabase extends Controller {
|
||||
const DatabaseId = req.params.DatabaseId
|
||||
const db = await Database.findOne({UUID: DatabaseId})
|
||||
if ( !db ) return res.status(404).message('Database not found with that ID.').api({})
|
||||
if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
// if ( !db.accessible_by(req.user) ) return req.security.deny()
|
||||
|
||||
await DBEntry.deleteMany({DatabaseId: db.UUID})
|
||||
await db.delete()
|
||||
|
||||
@@ -11,6 +11,8 @@ class Menu extends Controller {
|
||||
}
|
||||
|
||||
async get_items(req, res) {
|
||||
const Page = this.models.get('api:Page')
|
||||
|
||||
// Build the "My Tree" option
|
||||
const root_page = await req.user.get_root_page()
|
||||
const nodes = await this._build_menu_object(root_page)
|
||||
@@ -24,6 +26,53 @@ class Menu extends Controller {
|
||||
virtual: true,
|
||||
})
|
||||
|
||||
// Get view only shared trees
|
||||
const view_only_trees = await Page.find({ shared_users_view: req.user._id })
|
||||
const view_only_nodes = []
|
||||
for ( const tree of view_only_trees ) {
|
||||
if ( !(await tree.is_accessible_by(req.user)) ) continue
|
||||
view_only_nodes.push({
|
||||
id: tree.UUID,
|
||||
name: tree.Name,
|
||||
children: await this._build_secure_menu_object(tree, req.user),
|
||||
level: await tree.access_level_for(req.user),
|
||||
})
|
||||
}
|
||||
|
||||
// Get update, view shared trees
|
||||
const update_trees = await Page.find({ shared_users_update: req.user._id })
|
||||
const update_nodes = []
|
||||
for ( const tree of update_trees ) {
|
||||
if ( !(await tree.is_accessible_by(req.user)) ) continue
|
||||
update_nodes.push({
|
||||
id: tree.UUID,
|
||||
name: tree.Name,
|
||||
children: await this._build_secure_menu_object(tree, req.user),
|
||||
level: await tree.access_level_for(req.user),
|
||||
})
|
||||
}
|
||||
|
||||
// Get update, view, manage shared trees
|
||||
const manage_trees = await Page.find({ shared_users_manage: req.user._id })
|
||||
const manage_nodes = []
|
||||
for ( const tree of manage_trees ) {
|
||||
if ( !(await tree.is_accessible_by(req.user)) ) continue
|
||||
manage_nodes.push({
|
||||
id: tree.UUID,
|
||||
name: tree.Name,
|
||||
children: await this._build_secure_menu_object(tree, req.user),
|
||||
level: await tree.access_level_for(req.user),
|
||||
})
|
||||
}
|
||||
|
||||
menu.push({
|
||||
id: 0,
|
||||
name: 'Trees Shared With Me',
|
||||
children: [...view_only_nodes, ...update_nodes, ...manage_nodes],
|
||||
noDelete: true,
|
||||
virtual: true,
|
||||
})
|
||||
|
||||
return res.api(menu)
|
||||
}
|
||||
|
||||
@@ -33,7 +82,8 @@ class Menu extends Controller {
|
||||
for ( const child of children ) {
|
||||
arr.push({
|
||||
id: child.UUID,
|
||||
name: child.Name,
|
||||
name: child.is_shared() ? child.Name + ' ⁽ˢʰᵃʳᵉᵈ⁾' : child.Name,
|
||||
shared: child.is_shared(),
|
||||
children: await this._build_menu_object(child),
|
||||
})
|
||||
}
|
||||
@@ -42,6 +92,22 @@ class Menu extends Controller {
|
||||
return arr
|
||||
}
|
||||
|
||||
async _build_secure_menu_object(parent_node, user, arr = []) {
|
||||
const children = await parent_node.childPages
|
||||
if ( children ) {
|
||||
for ( const child of children ) {
|
||||
if ( !(await child.is_accessible_by(user)) ) continue
|
||||
arr.push({
|
||||
id: child.UUID,
|
||||
name: child.Name,
|
||||
children: await this._build_secure_menu_object(child, user),
|
||||
level: await child.access_level_for(user),
|
||||
})
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = Menu
|
||||
|
||||
@@ -14,7 +14,9 @@ class Page extends Controller {
|
||||
|
||||
const page = await PageModel.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(user) ) return req.security.deny()
|
||||
|
||||
if ( !(await page.is_accessible_by(user)) ) return req.security.deny()
|
||||
page.level = await page.access_level_for(req.user)
|
||||
|
||||
return res.api(page)
|
||||
}
|
||||
@@ -26,7 +28,7 @@ class Page extends Controller {
|
||||
if ( PageId ) {
|
||||
page = await PageModel.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user, 'update') ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
} else {
|
||||
page = new PageModel
|
||||
page.CreatedUserId = req.user.id
|
||||
@@ -44,13 +46,13 @@ class Page extends Controller {
|
||||
page.IsVisibleInMenu = !!req.body.IsVisibleInMenu
|
||||
}
|
||||
|
||||
let parent;
|
||||
/*let parent;
|
||||
if ( !req.body.ParentId ) return res.status(400).message('Missing required: ParentId').api({})
|
||||
else {
|
||||
parent = await PageModel.findOne({UUID: req.body.ParentId})
|
||||
if ( !parent ) return res.status(404).message('Parent page not found with that ID.').api({})
|
||||
if ( !parent.accessible_by(req.user, 'update') ) return req.security.kickout()
|
||||
}
|
||||
if ( !(await parent.is_accessible_by(req.user, 'update')) ) return req.security.kickout()
|
||||
}*/ // TODO re-implement this to account for sharing
|
||||
|
||||
page.UpdatedAt = new Date
|
||||
page.UpdateUserId = req.user._id
|
||||
@@ -66,7 +68,7 @@ class Page extends Controller {
|
||||
if ( PageId ) {
|
||||
page = await PageModel.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user) ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user)) ) return req.security.deny()
|
||||
}
|
||||
|
||||
const nodes = await Node.find({PageId: page.UUID});
|
||||
@@ -89,7 +91,7 @@ class Page extends Controller {
|
||||
if ( PageId ) {
|
||||
page = await PageModel.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user, 'update') ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'update')) ) return req.security.deny()
|
||||
}
|
||||
|
||||
const nodes = await Node.find({PageId: page.UUID})
|
||||
@@ -204,7 +206,7 @@ class Page extends Controller {
|
||||
const parent = await PageModel.findOne({UUID: req.body.parentId})
|
||||
if ( !parent ) {
|
||||
return res.status(404).message('Unable to find parent with that ID.').api({})
|
||||
} else if ( !parent.accessible_by(req.user, 'update') ) {
|
||||
} else if ( !(await parent.is_accessible_by(req.user, 'manage')) ) {
|
||||
return res.security.deny()
|
||||
}
|
||||
|
||||
@@ -248,7 +250,7 @@ class Page extends Controller {
|
||||
if ( PageId ) {
|
||||
page = await PageModel.findOne({UUID: PageId})
|
||||
if ( !page ) return res.status(404).message('Page not found with that ID.').api({})
|
||||
if ( !page.accessible_by(req.user, 'update') ) return req.security.deny()
|
||||
if ( !(await page.is_accessible_by(req.user, 'manage')) ) return req.security.deny()
|
||||
if ( page.ParentId === '0' ) return req.security.kickout()
|
||||
}
|
||||
|
||||
|
||||
74
app/controllers/api/v1/Sharing.controller.js
Normal file
74
app/controllers/api/v1/Sharing.controller.js
Normal file
@@ -0,0 +1,74 @@
|
||||
const Controller = require('libflitter/controller/Controller')
|
||||
|
||||
/*
|
||||
* Sharing Controller
|
||||
* -------------------------------------------------------------
|
||||
* Put some description here!
|
||||
*/
|
||||
class Sharing extends Controller {
|
||||
static get services() {
|
||||
return [...super.services, 'models']
|
||||
}
|
||||
|
||||
async share_page(req, res) {
|
||||
const level = req.form.level
|
||||
await req.form.page.share_with(req.form.user, level)
|
||||
return res.api({})
|
||||
}
|
||||
|
||||
async revoke_page(req, res) {
|
||||
await req.form.page.unshare_with(req.form.user)
|
||||
return res.api({})
|
||||
}
|
||||
|
||||
async page_info(req, res) {
|
||||
const data = {
|
||||
view: (await req.form.page.view_users).map(x => {
|
||||
return {username: x.uid, id: x.id, level: 'view'}
|
||||
}),
|
||||
update: (await req.form.page.update_users).map(x => {
|
||||
return {username: x.uid, id: x.id, level: 'update'}
|
||||
}),
|
||||
manage: (await req.form.page.manage_users).map(x => {
|
||||
return {username: x.uid, id: x.id, level: 'manage'}
|
||||
}),
|
||||
}
|
||||
|
||||
return res.api(data)
|
||||
}
|
||||
|
||||
async get_link(req, res) {
|
||||
const KeyAction = this.models.get('auth:KeyAction')
|
||||
const in_1_week = new Date
|
||||
in_1_week.setDate(in_1_week.getDate() + 7)
|
||||
|
||||
const action = new KeyAction({
|
||||
handler: 'controller::api:v1:Sharing.accept_link',
|
||||
expires: in_1_week,
|
||||
auto_login: false,
|
||||
no_auto_logout: true, // THIS IS FINE. It's because the MW requires a traditional sign-in.
|
||||
})
|
||||
|
||||
await action.save()
|
||||
action.data_set('level', req.form.level)
|
||||
action.data_set('PageId', req.form.page.UUID)
|
||||
await action.save()
|
||||
|
||||
return res.api({ link: action.auth_url() })
|
||||
}
|
||||
|
||||
async accept_link(req, res) {
|
||||
if ( !req.user ) return req.security.kickout()
|
||||
const Page = this.models.get('api:Page')
|
||||
const PageId = req.key_action.data_get('PageId')
|
||||
const level = req.key_action.data_get('level')
|
||||
|
||||
const page = await Page.findOne({UUID: PageId})
|
||||
await page.share_with(req.user, level)
|
||||
|
||||
return res.redirect(`/i/editor;id=${PageId}`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = Sharing
|
||||
Reference in New Issue
Block a user