feat(resolvers): added serverInfo route, bumped test coverage
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
'use strict'
|
||||
const root = require( 'app-root-path' )
|
||||
const { AuthenticationError, UserInputError } = require( 'apollo-server-express' )
|
||||
|
||||
const { getAvailableScopes, getAvailableRoles, getServerName, getServerDescription, getAdminContact, getTOS } = require( '../../services/generic' )
|
||||
|
||||
module.exports = {
|
||||
Query: {
|
||||
async serverInfo( parent, args, context, info ) {
|
||||
let si = {
|
||||
name: await getServerName( ),
|
||||
description: await getServerDescription( ),
|
||||
adminContact: await getAdminContact( ),
|
||||
tos: await getTOS( )
|
||||
}
|
||||
|
||||
return si
|
||||
}
|
||||
},
|
||||
ServerInfo: {
|
||||
async roles( parent, args, context, info ) {
|
||||
return await getAvailableRoles( )
|
||||
},
|
||||
async scopes( parent, args, context, info ) {
|
||||
return await getAvailableScopes( )
|
||||
}
|
||||
},
|
||||
Mutation: {}
|
||||
}
|
||||
@@ -34,12 +34,6 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
// NOTE: this mutation will not exist, or will be enabled only if local user creation is enabled
|
||||
async userCreate( parent, args, context, info ) {
|
||||
let userId = await createUser( args.user )
|
||||
let token = await createToken( userId, "Default Token", [ 'streams:read', 'streams:write' ] )
|
||||
return token
|
||||
},
|
||||
async userEdit( parent, args, context, info ) {
|
||||
await updateUser( context.userId, args.user )
|
||||
return true
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
extend type Query {
|
||||
serverInfo: ServerInfo!
|
||||
}
|
||||
|
||||
"""
|
||||
Information about this server.
|
||||
"""
|
||||
type ServerInfo {
|
||||
name: String!
|
||||
description: String!
|
||||
adminContact: String!
|
||||
tos: String!
|
||||
roles: [Role]
|
||||
scopes: [Scope]
|
||||
}
|
||||
|
||||
"""
|
||||
Available roles.
|
||||
"""
|
||||
type Role {
|
||||
name: String!
|
||||
description: String!
|
||||
resourceTarget: String!
|
||||
}
|
||||
|
||||
"""
|
||||
Available scopes.
|
||||
"""
|
||||
type Scope {
|
||||
name: String!
|
||||
description: String!
|
||||
}
|
||||
@@ -8,14 +8,26 @@ const Scopes = ( ) => knex( 'app_scopes' )
|
||||
module.exports = {
|
||||
|
||||
async getAvailableScopes( ) {
|
||||
return await Roles( ).select( '*' )
|
||||
},
|
||||
|
||||
async getAvailableRoles( ) {
|
||||
return await Scopes( ).select( '*' )
|
||||
},
|
||||
|
||||
async getServerInfo( ) {
|
||||
return { todo: true }
|
||||
}
|
||||
async getAvailableRoles( ) {
|
||||
return await Roles( ).select( '*' )
|
||||
},
|
||||
|
||||
async getServerName( ) {
|
||||
return `TODO: True`
|
||||
},
|
||||
|
||||
async getServerDescription( ) {
|
||||
return `TODO: True`
|
||||
},
|
||||
|
||||
async getAdminContact( ) {
|
||||
return `TODO: True`
|
||||
},
|
||||
|
||||
async getTOS( ) {
|
||||
return `TODO: True`
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
const chai = require( 'chai' )
|
||||
const assert = require( 'assert' )
|
||||
|
||||
const root = require( 'app-root-path' )
|
||||
const { init } = require( `${root}/app` )
|
||||
const knex = require( `${root}/db/knex` )
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
const { contextApiTokenHelper, validateScopes, authorizeResolver } = require( '../../shared' )
|
||||
|
||||
describe( 'Generic AuthN & AuthZ controller tests', ( ) => {
|
||||
|
||||
it( 'Validate scopes', async ( ) => {
|
||||
try {
|
||||
await validateScopes( )
|
||||
assert.fail( 'Should have thrown an error with invalid input' )
|
||||
} catch ( e ) {
|
||||
//
|
||||
}
|
||||
|
||||
try {
|
||||
await validateScopes( [ 'a' ], 'b' )
|
||||
assert.fail( 'Should have thrown an error' )
|
||||
} catch ( e ) {
|
||||
//
|
||||
}
|
||||
|
||||
await validateScopes( [ 'a', 'b' ], 'b' ) // should pass
|
||||
} )
|
||||
|
||||
it( 'Should create proper context', async ( ) => {
|
||||
let res = await contextApiTokenHelper( { req: { headers: { authorization: 'Bearer BS' } } } )
|
||||
expect( res.auth ).to.equal( false )
|
||||
|
||||
let res2 = await contextApiTokenHelper( { req: { headers: { authorization: null } } } )
|
||||
expect( res2.auth ).to.equal( false )
|
||||
|
||||
let res3 = await contextApiTokenHelper( { req: { headers: { authorization: undefined } } } )
|
||||
expect( res3.auth ).to.equal( false )
|
||||
} )
|
||||
|
||||
it( 'Resolver Authorization Should fail nicely when roles & resources are wanky', async ( ) => {
|
||||
|
||||
try {
|
||||
let res = await authorizeResolver( null, 'foo', 'bar' )
|
||||
assert.fail( 'resolver authorization should have thrown' )
|
||||
} catch ( e ) {
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
let res = await authorizeResolver( 'foo', 'bar', 'streams:read' )
|
||||
assert.fail( 'resolver authorization should have thrown' )
|
||||
} catch ( e ) {
|
||||
|
||||
}
|
||||
|
||||
} )
|
||||
|
||||
} )
|
||||
@@ -150,7 +150,7 @@ describe( 'GraphQL API Core', ( ) => {
|
||||
|
||||
it( 'Should grant some permissions', async ( ) => {
|
||||
const res = await sendRequest( userA.token, { query: `mutation{ streamGrantPermission( streamId: "${ts1}", userId: "${userB.id}" role: "stream:owner") }` } )
|
||||
|
||||
|
||||
expect( res ).to.be.json
|
||||
expect( res.body.errors ).to.not.exist
|
||||
expect( res.body.data.streamGrantPermission ).to.equal( true )
|
||||
@@ -195,7 +195,7 @@ describe( 'GraphQL API Core', ( ) => {
|
||||
const resNotAuth = await sendRequest( userC.token, { query: `query { stream(id:"${ts3}") { id name role } }` } )
|
||||
expect( resNotAuth ).to.be.json
|
||||
expect( resNotAuth.body.errors ).to.exist
|
||||
|
||||
|
||||
} )
|
||||
|
||||
it( 'Should fail to edit/write on a public stream if no access is provided', async ( ) => {
|
||||
@@ -600,7 +600,43 @@ describe( 'GraphQL API Core', ( ) => {
|
||||
} )
|
||||
|
||||
} )
|
||||
} )
|
||||
|
||||
describe( 'Server Info', ( ) => {
|
||||
it( 'Should return a valid server information object', async ( ) => {
|
||||
let q = `
|
||||
query{
|
||||
serverInfo{
|
||||
name
|
||||
adminContact
|
||||
tos
|
||||
description
|
||||
roles{
|
||||
name
|
||||
description
|
||||
resourceTarget
|
||||
}
|
||||
scopes{
|
||||
name
|
||||
description
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
let res = await sendRequest( null, { query: q } )
|
||||
|
||||
expect( res ).to.be.json
|
||||
expect( res.body.errors ).to.not.exist
|
||||
expect( res.body.data.serverInfo ).to.be.an( 'object' )
|
||||
|
||||
let si = res.body.data.serverInfo
|
||||
expect( si.name ).to.be.a( 'string' )
|
||||
expect( si.adminContact ).to.be.a( 'string' )
|
||||
expect( si.tos ).to.be.a( 'string' )
|
||||
expect( si.description ).to.be.a( 'string' )
|
||||
expect( si.roles ).to.be.a( 'array' )
|
||||
expect( si.scopes ).to.be.a( 'array' )
|
||||
} )
|
||||
} )
|
||||
} )
|
||||
|
||||
|
||||
+11
-7
@@ -13,18 +13,22 @@ const { validateToken } = require( `${root}/modules/core/services/tokens` )
|
||||
|
||||
async function contextApiTokenHelper( { req, res } ) {
|
||||
// TODO: Cache results for 5 minutes
|
||||
if ( req.headers.authorization ) {
|
||||
if ( req.headers.authorization != null ) {
|
||||
try {
|
||||
let token = req.headers.authorization.split( ' ' )[ 1 ]
|
||||
|
||||
let token = req.headers.authorization.split( ' ' )[ 1 ]
|
||||
let { valid, scopes, userId } = await validateToken( token )
|
||||
|
||||
let { valid, scopes, userId } = await validateToken( token )
|
||||
if ( !valid ) {
|
||||
return { auth: false }
|
||||
}
|
||||
|
||||
if ( !valid ) {
|
||||
return { auth: false }
|
||||
return { auth: true, userId, token, scopes }
|
||||
} catch ( e ) {
|
||||
return { auth: false, err: e }
|
||||
}
|
||||
|
||||
return { auth: true, userId, token, scopes }
|
||||
}
|
||||
return { auth: false }
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"test": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test nyc nyc --reporter=html mocha -s 0 --exit",
|
||||
"test-watch": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test mocha --watch -s 0 --exit",
|
||||
"test-graph": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test mocha ./modules/core/tests/graph.spec.js --watch -s 0 --exit --no-config",
|
||||
"test-generic": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test mocha ./modules/core/tests/generic.spec.js --watch -s 0 --exit --no-config",
|
||||
"test-objects": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test mocha ./modules/core/tests/objects.spec.js --watch -s 0 --exit --no-config",
|
||||
"test-streams": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test mocha ./modules/core/tests/streams.spec.js --watch -s 0 --exit --no-config",
|
||||
"test-references": "PORT=3001 DEBUG=speckle:test,speckle:errors NODE_ENV=test mocha ./modules/core/tests/references.spec.js --watch -s 0 --exit --no-config",
|
||||
|
||||
Reference in New Issue
Block a user