Skip to content
This repository has been archived by the owner on Aug 28, 2021. It is now read-only.

Commit

Permalink
added 馃殾 permission checks on *some* routes, tested 50%
Browse files Browse the repository at this point in the history
  • Loading branch information
didimitrie committed Mar 17, 2018
1 parent cd97289 commit add9733
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 77 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Expand Up @@ -6,5 +6,4 @@ npm-debug.log

# keep only the data folder
data/*
!data/.gitkeep

!data/.gitkeep
19 changes: 15 additions & 4 deletions app/api/core/streams/StreamDiff.js
@@ -1,6 +1,7 @@
const winston = require( 'winston' )
const _ = require( 'lodash' )
const DataStream = require( '../../../../models/DataStream' )
const PermissionCheck = require( '../../middleware/PermissionCheck' )

module.exports = ( req, res ) => {
if ( !req.params.streamId || !req.params.otherId ) {
Expand All @@ -13,16 +14,26 @@ module.exports = ( req, res ) => {
return res.send( { success: false, message: 'Can not diff the same stream, yo!' } )
}

let first = {}
let second = {}

DataStream.find( { streamId: { $in: [ req.params.streamId, req.params.otherId ] } } ).lean( )
.then( streams => {
let first = streams.find( s => s.streamId === req.params.streamId )
let second = streams.find( s => s.streamId === req.params.otherId )

first = streams.find( s => s.streamId === req.params.streamId )
second = streams.find( s => s.streamId === req.params.otherId )
// check if user can read first stream
return PermissionCheck( req.user, 'read', first )
} )
.then( ( ) => {
// check if user can read second stream
return PermissionCheck( req.user, 'read', second )
} )
.then( ( ) => {
let objects = { common: null, inA: null, inB: null }
objects.inA = _.differenceWith( first.objects, second.objects, ( arrVal, otherVal ) => arrVal.toString( ) === otherVal.toString( ) )
objects.inB = _.differenceWith( second.objects, first.objects, ( arrVal, otherVal ) => arrVal.toString( ) === otherVal.toString( ) )
objects.common = _.intersectionWith( first.objects, second.objects, ( arrVal, otherVal ) => arrVal.toString( ) === otherVal.toString( ) )

let layers = { common: null, inA: null, inB: null }
layers.common = _.intersectionWith( first.layers, second.layers, ( arrVal, otherVal ) => arrVal.guid === otherVal.guid )
layers.inA = _.differenceWith( first.layers, second.layers, ( arrVal, otherVal ) => arrVal.guid === otherVal.guid )
Expand Down
9 changes: 8 additions & 1 deletion app/api/core/streams/StreamDuplicate.js
Expand Up @@ -3,6 +3,7 @@ const mongoose = require( 'mongoose' )
const shortId = require( 'shortid' )

const DataStream = require( '../../../../models/DataStream' )
const PermissionCheck = require( '../../middleware/PermissionCheck' )

module.exports = ( req, res ) => {
if ( !req.params.streamId ) {
Expand All @@ -12,16 +13,22 @@ module.exports = ( req, res ) => {

let clone = {}
let parent = {}
let stream = {}

DataStream.findOne( { streamId: req.params.streamId } )
.then( stream => {
.then( result => {
stream = result
return PermissionCheck( req.user, 'read', result )
} )
.then( ( ) => {
if ( !stream ) throw new Error( 'Database fail.' )
clone = new DataStream( stream )
clone._id = mongoose.Types.ObjectId( )
clone.streamId = shortId.generate( )
clone.parent = stream.streamId
clone.children = [ ]
clone.isNew = true
clone.owner = req.user._id
stream.children.push( clone.streamId )
return stream.save( )
} )
Expand Down
15 changes: 9 additions & 6 deletions app/api/core/streams/StreamGet.js
Expand Up @@ -3,7 +3,9 @@ const winston = require( 'winston' )
const passport = require( 'passport' )
const chalk = require( 'chalk' )


const DataStream = require( '../../../../models/DataStream' )
const PermissionCheck = require( '../../middleware/PermissionCheck' )

module.exports = ( req, res ) => {

Expand All @@ -12,17 +14,18 @@ module.exports = ( req, res ) => {
return res.send( { success: false, message: 'No stream id provided.' } )
}

let stream = null
DataStream.findOne( { streamId: req.params.streamId } )
.then( stream => {
.then( doc => {
stream = doc
return PermissionCheck( req.user, 'read', doc )
} )
.then( ( ) => {
if ( !stream ) throw new Error( 'No stream found.' )
if ( stream.private && !req.user ) throw new Error( 'Unauthorized. Please log in.' )
if ( stream.private && ( !req.user || !( req.user._id.equals( stream.owner ) || stream.sharedWith.find( id => { return req.user._id.equals( id ) } ) ) ) )
throw new Error( 'Unauthorized. Please log in.' )

return res.send( { success: true, message: 'Delivered stream.', stream: stream } )
} )
.catch( err => {
res.status( err.message === 'Unauthorized. Please log in.' ? 401 : 404 )
res.status( err.message.indexOf( 'authorised' ) >= 0 ? 401 : 404 )
res.send( { success: false, message: err.message, streamId: req.streamId } )
} )
}
5 changes: 4 additions & 1 deletion app/api/core/streams/StreamPatch.js
Expand Up @@ -6,6 +6,7 @@ const mongoose = require( 'mongoose' )
const DataStream = require( '../../../../models/DataStream' )
const SpeckleObject = require( '../../../../models/SpeckleObject' )
const MergeLayers = require( '../../helpers/MergeLayers' )
const PermissionCheck = require( '../../middleware/PermissionCheck' )

module.exports = ( req, res ) => {
winston.debug( chalk.bgGreen( 'Patching stream', req.params.streamId ) )
Expand All @@ -19,7 +20,9 @@ module.exports = ( req, res ) => {
DataStream.findOne( { streamId: req.params.streamId } )
.then( result => {
stream = result

return PermissionCheck( req.user, 'write', result )
})
.then(() => {
for ( var key in req.body ) {
if ( stream.toObject( ).hasOwnProperty( key ) ) {
stream[ key ] = req.body[ key ]
Expand Down
11 changes: 7 additions & 4 deletions app/api/core/streams/StreamPut.js
Expand Up @@ -6,6 +6,7 @@ const mongoose = require( 'mongoose' )
const DataStream = require( '../../../../models/DataStream' )
const SpeckleObject = require( '../../../../models/SpeckleObject' )
const MergeLayers = require( '../../helpers/MergeLayers' )
const PermissionCheck = require( '../../middleware/PermissionCheck' )

module.exports = ( req, res ) => {
winston.debug( chalk.bgGreen( 'Getting stream', req.params.streamId ) )
Expand All @@ -18,11 +19,13 @@ module.exports = ( req, res ) => {
DataStream.findOne( { streamId: req.params.streamId } )
.then( result => {
stream = result

return PermissionCheck( req.user, 'write', result )
} )
.then( ( ) => {
if ( req.body.private ) stream.private = req.body.private
if ( req.body.parent ) stream.parent = req.body.parent
if( req.body.globalMeasures ) stream.globalMeasures = req.body.globalMeasures
if( req.body.baseProperties ) stream.baseProperties = req.body.baseProperties
if ( req.body.globalMeasures ) stream.globalMeasures = req.body.globalMeasures
if ( req.body.baseProperties ) stream.baseProperties = req.body.baseProperties

stream.name = req.body.name ? req.body.name : stream.name
stream.layers = req.body.layers ? MergeLayers( stream.layers, req.body.layers ) : stream.layers
Expand All @@ -47,7 +50,7 @@ module.exports = ( req, res ) => {
} )
.catch( err => {
winston.error( err )
res.status( 400 )
res.status( err.message.indexOf( 'authorised' ) >= 0 ? 401 : 400 )
res.send( { success: false, message: err.toString( ) } )
} )
}
54 changes: 54 additions & 0 deletions app/api/middleware/PermissionCheck.js
@@ -0,0 +1,54 @@
'use strict'
const winston = require( 'winston' )
const chalk = require( 'chalk' )
const url = require( 'url' )
const User = require( '../../../models/User' )

module.exports = ( user, operation, resource ) => {
return new Promise( ( resolve, reject ) => {

if ( user == null ) user = { role: 'guest', _id: '' }
winston.debug( chalk.bgRed( 'checking perms' ), user.role, user._id.toString( ) )

// admin or owner
if ( user.role === 'admin' || user._id.toString( ) === resource.owner.toString( ) ) {
winston.debug( chalk.bgGreen( 'checking perms' ), 'user is admin or owner' )
return resolve( )
}

if ( operation == null ) {
winston.debug( chalk.bgRed( 'checking perms' ), 'no operation specified' )
return reject( new Error( "You are not authorised." ) )
}

switch ( operation ) {
case 'write':
if ( resource.canWrite.indexOf( user._id ) >= 0 ) {
winston.debug( chalk.bgGreen( 'checking perms' ), `user has ${operation} access` )
return resolve( )
}
winston.debug( chalk.bgRed( 'checking perms' ), `user has NO ${operation} access` )
return reject( new Error( "You are not authorised." ) )

case 'read':
if ( !resource.private ) {
winston.debug( chalk.bgGreen( 'checking perms' ), `${operation} ok, resource is public` )
return resolve( )
}
if ( resource.canWrite.indexOf( user._id ) >= 0 ) {
winston.debug( chalk.bgGreen( 'checking perms' ), `user has write & ${operation} access` )
return resolve( )
}
if ( resource.canRead.indexOf( user._id ) >= 0 ) {
winston.debug( chalk.bgGreen( 'checking perms' ), `user has ${operation} access` )
return resolve( )
}
winston.debug( chalk.bgRed( 'checking perms' ), `user has NO ${operation} access` )
return reject( new Error( "You are not authorised." ) )

default:
winston.debug( chalk.bgRed( 'checking perms' ), `operation ${operation} not defined` )
return reject( new Error( "You are not authorised." ) )
}
} )
}

0 comments on commit add9733

Please sign in to comment.