diff --git a/app.js b/app.js index 59c8edd92..4c4ba875d 100644 --- a/app.js +++ b/app.js @@ -42,7 +42,6 @@ exports.init = async ( ) => { } if ( process.env.COMPRESSION ) { - debug( `speckle:startup` )( 'Using app level compression. Consider enabling this at a proxy level.' ) app.use( compression( ) ) } @@ -77,7 +76,9 @@ exports.init = async ( ) => { plugins: [ require( `${appRoot}/logging/apolloPlugin` ) ], - tracing: process.env.NODE_ENV === 'development' + tracing: process.env.NODE_ENV === 'development', + introspection: true, + playground: true } ) graphqlServer.applyMiddleware( { app: app } ) @@ -106,8 +107,7 @@ exports.startHttp = async ( app ) => { debug( 'speckle:http-startup' )( '✨ Proxying frontend (dev mode):' ) debug( 'speckle:http-startup' )( `👉 main application: http://localhost:${port}/` ) - debug( 'speckle:http-startup' )( `👉 auth application: http://localhost:${port}/auth` ) - debug( 'speckle:hint' )( ` â„šī¸ Don't forget to run "npm run dev:frontend" in a different terminal to start the vue application.` ) + debug( 'speckle:hint' )( 'â„šī¸ Don\'t forget to run "npm run dev:frontend" in a different terminal to start the vue application.' ) } // Production mode -> serve things statically. @@ -136,7 +136,7 @@ exports.startHttp = async ( app ) => { app.use( Sentry.Handlers.errorHandler( ) ) server.on( 'listening', ( ) => { - debug( `speckle:startup` )( ` 🚀 My name is Spockle Server, and I'm running at ${server.address().port}` ) + debug( 'speckle:startup' )( ` 🚀 My name is Spockle Server, and I'm running at ${server.address().port}` ) } ) server.listen( port ) diff --git a/frontend/src/auth-helpers.js b/frontend/src/auth-helpers.js index b7c320a61..2eb40c6ae 100644 --- a/frontend/src/auth-helpers.js +++ b/frontend/src/auth-helpers.js @@ -13,7 +13,6 @@ export async function checkAccessCodeAndGetTokens() { let response = await getTokenFromAccessCode(accessCode) // eslint-disable-next-line no-prototype-builtins if (response.hasOwnProperty('token')) { - localStorage.clear() localStorage.setItem('AuthToken', response.token) localStorage.setItem('RefreshToken', response.refreshToken) window.history.replaceState({}, document.title, '/') @@ -68,14 +67,6 @@ export async function getTokenFromAccessCode(accessCode) { return data } -export function redirectToAuth() { - // Reaching this stage means we're initialising a full new auth flow, - // TIP: also means we need to refresh the app challenge as well. - localStorage.setItem('appChallenge', crs({ length: 10 })) - // Finally, redirect to the auth lock. - window.location = `/auth?appId=${appId}&challenge=${localStorage.getItem('appChallenge')}` -} - /** * Signs out the current session * @return {null} diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 6d8322d07..70da9c5e1 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -161,38 +161,23 @@ const router = new VueRouter({ router.beforeEach((to, from, next) => { let uuid = localStorage.getItem('uuid') let redirect = localStorage.getItem('shouldRedirectTo') - let path = to.path - let name = to.name - console.log(uuid, redirect, path, name) + if (!uuid && to.name !== 'Login' && to.name !== 'Register') { + localStorage.setItem('shouldRedirectTo', to.path) - if (!uuid && (to.name !== 'Login' && to.name !== 'Register')) return next({ name: 'Login' }) + return next({ name: 'Login' }) + } + + if ((to.name === 'Login' || to.name === 'Register') && uuid) { + return next({ name: 'home' }) + } + + if (uuid && redirect && redirect !== to.path) { + localStorage.removeItem('shouldRedirectTo') + return next({ path: redirect }) + } return next() - // if (!(to.name === 'Login' || to.name === 'Register') && !localStorage.getItem('uuid')) { - // localStorage.setItem('shouldRedirectTo', to.path) - // return next({ name: 'Login' }) - // } else if ( - // (to.name === 'Login' || to.name === 'Register') && - // !!localStorage.getItem('uuid') && - // !!localStorage.getItem('shouldRedirectTo') - // ) { - // return next({ name: 'home' }) - // } else if (localStorage.getItem('shouldRedirectTo')) { - // let path = localStorage.getItem('shouldRedirectTo') - // localStorage.removeItem('shouldRedirectTo') - // return next({ path }) - // } else { - // return next() - // } - - // else if (localStorage.getItem('uuid')) { - // let shouldRedirectTo = localStorage.getItem('shouldRedirectTo') - // localStorage.removeItem('shouldRedirectTo') - // if (shouldRedirectTo) { - // return next() // TODO: redirect to prev url - // } else return next() - // } }) //TODO: include stream name in page title eg `My Cool Stream | Speckle` diff --git a/modules/apiexplorer/explorer.html b/modules/apiexplorer/explorer.html index e100e6126..e856ef3f0 100644 --- a/modules/apiexplorer/explorer.html +++ b/modules/apiexplorer/explorer.html @@ -25,127 +25,127 @@ + + let data = await response.json( ) + + if ( data.hasOwnProperty( 'token' ) ) { + localStorage.removeItem( 'challenge' ) + localStorage.setItem( 'AuthToken', data.token ) + localStorage.setItem( 'RefreshToken', data.refreshToken ) + await setUserName( ) + await initGQL( data.token ) + } + +} + +async function initGQL( token ) { + // GraphQLPlayground.init( document.getElementById( 'root' ), { + // endpointUrl: '/graphql', + // headers: { + // 'Authorization': 'Bearer ' + token + // } + // } ) + ReactDOM.render( + React.createElement( GraphiQL, { fetcher: graphQLFetcher } ), + document.getElementById( 'graphiql' ), + ) + await setServerInfo( ) +} + +async function setUserName( ) { + let testResponse = await fetch( '/graphql', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem( 'AuthToken' ), + 'Content-Type': 'application/json' + }, + body: JSON.stringify( { query: `{ user { name } }` } ) + } ) + + let data = ( await testResponse.json( ) ).data + document.getElementById( 'username' ).innerHTML = data.user.name +} + +async function setServerInfo( ) { + let testResponse = await fetch( '/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify( { query: `{ serverInfo { name company } }` } ) + } ) + + let data = ( await testResponse.json( ) ).data + document.getElementById( 'serverDetails' ).innerHTML = `${data.serverInfo.name} deployed by ${data.serverInfo.company}` +} + +function logout( ) { + localStorage.removeItem( 'AuthToken' ) + localStorage.removeItem( 'RefreshToken' ) + window.location = '/explorer' +} + +window.addEventListener( 'load', async function ( event ) { + let urlParams = new URLSearchParams( window.location.search ) + let accessCode = urlParams.get( 'access_code' ) + + if ( accessCode ) { + accessCodeExchange( accessCode ) + } else { + let token = localStorage.getItem( 'AuthToken' ) + if ( token ) { + let testResponse = await fetch( '/graphql', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + token, + 'Content-Type': 'application/json' + }, + body: JSON.stringify( { query: '{ user { name } }' } ) + } ) + + let data = ( await testResponse.json( ) ).data + // if res.data.user is non null, means the ping was ok & token is valid + if ( data.user ) { + console.log( data.user ) + document.getElementById( 'username' ).innerHTML = data.user.name + await initGQL( token ) + + } + } else { + redirectToAuth( ) + } + } +} ) + - \ No newline at end of file + diff --git a/modules/auth/graph/schemas/apps.graphql b/modules/auth/graph/schemas/apps.graphql index 9d724e210..03586eeb6 100644 --- a/modules/auth/graph/schemas/apps.graphql +++ b/modules/auth/graph/schemas/apps.graphql @@ -38,6 +38,7 @@ type ServerAppListItem { type AppAuthor { name: String id: String + avatar: String } extend type User { diff --git a/modules/auth/index.js b/modules/auth/index.js index ea1c12d2e..63a490045 100644 --- a/modules/auth/index.js +++ b/modules/auth/index.js @@ -8,8 +8,10 @@ const passport = require( 'passport' ) const debug = require( 'debug' ) const sentry = require( `${appRoot}/logging/sentryHelper` ) -const { getApp, createAuthorizationCode, createAppTokenFromAccessCode, refreshAppToken } = require( './services/apps' ) -const { createPersonalAccessToken } = require( `${appRoot}/modules/core/services/tokens` ) +const { getApp, getAllAppsAuthorizedByUser, createAuthorizationCode, createAppTokenFromAccessCode, refreshAppToken } = require( './services/apps' ) +const { createPersonalAccessToken, validateToken, revokeTokenById } = require( `${appRoot}/modules/core/services/tokens` ) +const { revokeRefreshToken } = require( `${appRoot}/modules/auth/services/apps` ) +const { validateScopes, contextMiddleware } = require( `${appRoot}/modules/shared` ) let authStrategies = [ ] @@ -31,61 +33,95 @@ exports.init = ( app, options ) => { cookie: { maxAge: 1000 * 60 * 3 } // 3 minutes } ) - let sessionAppId = ( req, res, next ) => { - - req.session.appId = req.query.appId + let sessionStorage = ( req, res, next ) => { req.session.challenge = req.query.challenge - if ( req.query.suuid ) { req.session.suuid = req.query.suuid } - next( ) } + /* + Finalizes authentication for the main frontend application. + */ let finalizeAuth = async ( req, res, next ) => { - - if ( req.session.appId ) { - - try { - - let app = await getApp( { id: req.session.appId } ) - let ac = await createAuthorizationCode( { appId: app.id, userId: req.user.id, challenge: req.session.challenge } ) - - if ( req.session ) req.session.destroy( ) - return res.redirect( `/auth/finalize?appId=${app.id}&access_code=${ac}` ) - - - } catch ( err ) { - - sentry( { err } ) - if ( req.session ) req.session.destroy( ) - return res.status( 401 ).send( 'Invalid request.' ) - - } - - } else { - - if ( process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ) { - - let token = await createPersonalAccessToken( req.user.id, 'test token', [ 'streams:write', 'streams:read', 'profile:read', 'profile:email', 'users:read', 'users:email' ] ) - if ( req.session ) req.session.destroy( ) - return res.status( 200 ).send( { userId: req.user.id, apiToken: token } ) - - - } + try { + let app = await getApp( { id: 'spklwebapp' } ) + let ac = await createAuthorizationCode( { appId: 'spklwebapp', userId: req.user.id, challenge: req.session.challenge } ) if ( req.session ) req.session.destroy( ) - return res.status( 200 ).end( ) - + return res.redirect( `${app.redirectUrl}?access_code=${ac}` ) + } catch ( err ) { + sentry( { err } ) + if ( req.session ) req.session.destroy( ) + return res.status( 401 ).send( 'Invalid request.' ) } } - // TODO: add cors - app.post( '/auth/token', async ( req, res, next ) => { + /* + Strategies initialisation & listing + */ + let strategyCount = 0 + + if ( process.env.STRATEGY_GOOGLE === 'true' ) { + let googStrategy = require( './strategies/google' )( app, session, sessionStorage, finalizeAuth ) + authStrategies.push( googStrategy ) + strategyCount++ + } + + if ( process.env.STRATEGY_GITHUB === 'true' ) { + let githubStrategy = require( './strategies/github' )( app, session, sessionStorage, finalizeAuth ) + authStrategies.push( githubStrategy ) + strategyCount++ + } + + // Note: always leave the local strategy init for last so as to be able to + // force enable it in case no others are present. + if ( process.env.STRATEGY_LOCAL === 'true' || strategyCount === 0 ) { + let localStrategy = require( './strategies/local' )( app, session, sessionStorage, finalizeAuth ) + authStrategies.push( localStrategy ) + } + + /* + Auth routes + */ + + /* + Generates an access code for an app. + */ + app.get( '/auth/accesscode', async( req, res, next ) => { try { + let appId = req.query.appId + let app = await getApp( { id: appId } ) + if ( !app ) throw new Error( 'App does not exist.' ) + let challenge = req.query.challenge + let userToken = req.query.token + + // 1. Validate token + let { valid, scopes, userId, role } = await validateToken( userToken ) + if ( !valid ) throw new Error( 'Invalid token' ) + + // 2. Validate token scopes + await validateScopes( scopes, 'tokens:write' ) + + let ac = await createAuthorizationCode( { appId, userId, challenge } ) + return res.redirect( `${app.redirectUrl}?access_code=${ac}` ) + + } catch ( err ) { + sentry( { err } ) + debug( 'speckle:errors' )( err ) + return res.status( 400 ).send( err.message ) + } + } ) + + /* + Generates a new api token: (1) either via a valid refresh token or (2) via a valid access token + */ + app.post( '/auth/token', async ( req, res, next ) => { + try { + // Token refresh if ( req.body.refreshToken ) { if ( !req.body.appId || !req.body.appSecret ) throw new Error( 'Invalid request - refresh token' ) @@ -94,46 +130,37 @@ exports.init = ( app, options ) => { return res.send( authResponse ) } + // Access-code - token exchange if ( !req.body.appId || !req.body.appSecret || !req.body.accessCode || !req.body.challenge ) throw new Error( 'Invalid request' + JSON.stringify( req.body ) ) let authResponse = await createAppTokenFromAccessCode( { appId: req.body.appId, appSecret: req.body.appSecret, accessCode: req.body.accessCode, challenge: req.body.challenge } ) return res.send( authResponse ) - } catch ( err ) { - sentry( { err } ) return res.status( 401 ).send( { err: err.message } ) - } - } ) - // TODO: add logout route + /* + Ensures a user is logged out by invalidating their token and refresh token. + */ + app.post( '/auth/logout', async ( req, res, next ) => { + try { + let token = req.body.token + let refreshToken = req.body.refreshToken + if ( !token ) throw new Error( 'Invalid request' ) + await revokeTokenById( token ) - // Strategies initialisation & listing - // NOTE: if no strategies are defined, the local one will be enabled. + if ( refreshToken ) + revokeRefreshToken( { tokenId:refreshToken } ) - let strategyCount = 0 - - if ( process.env.STRATEGY_GITHUB === 'true' ) { - let githubStrategy = require( './strategies/github' )( app, session, sessionAppId, finalizeAuth ) - authStrategies.push( githubStrategy ) - strategyCount++ - } - - if ( process.env.STRATEGY_GOOGLE === 'true' ) { - let googStrategy = require( './strategies/google' )( app, session, sessionAppId, finalizeAuth ) - authStrategies.push( googStrategy ) - strategyCount++ - } - - // Note: always leave the local strategy init for last so as to be able to - // force enable it in case no others are present. - if ( process.env.STRATEGY_LOCAL === 'true' || strategyCount === 0 ) { - let localStrategy = require( './strategies/local' )( app, session, sessionAppId, finalizeAuth ) - authStrategies.push( localStrategy ) - } + return res.status( 200 ).send( { message: 'You have logged out.' } ) + } catch ( err ){ + sentry( { err } ) + return res.status( 400 ).send( { err: err.message } ) + } + } ) } diff --git a/modules/auth/migrations/2020-09-18-defaultApps.js b/modules/auth/migrations/2020-09-18-defaultApps.js index 5d59fdae7..214e8ff97 100644 --- a/modules/auth/migrations/2020-09-18-defaultApps.js +++ b/modules/auth/migrations/2020-09-18-defaultApps.js @@ -20,10 +20,9 @@ exports.up = async knex => { const desktopConnectorScopes = [ { appId: 'sdm', scopeName: 'streams:read' }, - { appId: 'sdm', scopeName: 'streams:write' }, { appId: 'sdm', scopeName: 'profile:read' }, { appId: 'sdm', scopeName: 'profile:email' }, - { appId: 'sdm', scopeName: 'users:read' }, + { appId: 'sdm', scopeName: 'users:read' } ] await knex( 'server_apps_scopes' ).insert( desktopConnectorScopes ) @@ -39,7 +38,7 @@ exports.up = async knex => { `, trustByDefault: true, public: true, - redirectUrl: 'self' + redirectUrl: process.env.CANONICAL_URL } ) const scopes = await knex( 'scopes' ).select( '*' ) @@ -56,7 +55,7 @@ exports.up = async knex => { description: 'GraphQL Playground with authentication.', trustByDefault: true, public: true, - redirectUrl: '/explorer', + redirectUrl: `${process.env.CANONICAL_URL}/explorer` } ) const explorerScopes = scopes.filter( s => s.name !== 'server:setup' ).map( s => ( { appId: 'explorer', scopeName: s.name } ) ) @@ -70,10 +69,10 @@ exports.up = async knex => { secret: '12345', name: 'Mock Application', description: 'Lorem ipsum dolor sic amet.', - redirectUrl: 'http://localhost:1337', // ie, will just redirect to window.location + redirectUrl: 'http://localhost:1337' } ) - const mockAppScopes = [ { appId: 'mock', scopeName: 'streams:read' }, { appId: 'mock', scopeName: 'users:read' }, { appId: 'mock', scopeName: 'profile:email' } ] + const mockAppScopes = [ { appId: 'mock', scopeName: 'streams:read' }, { appId: 'mock', scopeName: 'streams:write' }, { appId: 'mock', scopeName: 'users:read' }, { appId: 'mock', scopeName: 'profile:email' } ] await knex( 'server_apps_scopes' ).insert( mockAppScopes ) } diff --git a/modules/auth/services/apps.js b/modules/auth/services/apps.js index 2e1f8091c..2f158987b 100644 --- a/modules/auth/services/apps.js +++ b/modules/auth/services/apps.js @@ -28,7 +28,7 @@ module.exports = { let appScopeNames = ( await ServerAppsScopes( ).select( 'scopeName' ).where( { appId: id } ) ).map( s => s.scopeName ) app.scopes = allScopes.filter( scope => appScopeNames.indexOf( scope.name ) !== -1 ) - app.author = await Users( ).select( 'id', 'name' ).where( { id: app.authorId } ).first( ) + app.author = await Users( ).select( 'id', 'name', 'avatar' ).where( { id: app.authorId } ).first( ) return app }, @@ -134,6 +134,15 @@ module.exports = { }, + async revokeRefreshToken( { tokenId } ) { + tokenId = tokenId.slice( 0, 10 ) + let delCount = await RefreshTokens( ).where( { id: tokenId } ).del( ) + + if ( delCount === 0 ) + throw new Error( 'Did not revoke token' ) + return true + }, + async revokeExistingAppCredentials( { appId } ) { let resAccessCodeDelete = await AuthorizationCodes( ).where( { appId: appId } ).del( ) diff --git a/modules/auth/strategies/github.js b/modules/auth/strategies/github.js index e1b4f973c..1e09f37ad 100644 --- a/modules/auth/strategies/github.js +++ b/modules/auth/strategies/github.js @@ -8,13 +8,13 @@ const appRoot = require( 'app-root-path' ) const { findOrCreateUser } = require( `${appRoot}/modules/core/services/users` ) const { getApp, createAuthorizationCode, createAppTokenFromAccessCode } = require( '../services/apps' ) -module.exports = ( app, session, sessionAppId, finalizeAuth ) => { +module.exports = ( app, session, sessionStorage, finalizeAuth ) => { const strategy = { id: 'github', name: 'Github', - icon: 'TODO', - color: 'grey darken-2', - url: `/auth/gh`, + icon: 'mdi-github', + color: 'grey darken-3', + url: '/auth/gh', callbackUrl: ( new URL( '/auth/gh/callback', process.env.CANONICAL_URL ) ).toString( ) } @@ -41,7 +41,7 @@ module.exports = ( app, session, sessionAppId, finalizeAuth ) => { passport.use( myStrategy ) - app.get( strategy.url, session, sessionAppId, passport.authenticate( 'github', { failureRedirect: '/auth/error' } ) ) + app.get( strategy.url, session, sessionStorage, passport.authenticate( 'github', { failureRedirect: '/auth/error' } ) ) app.get( '/auth/gh/callback', session, passport.authenticate( 'github', { failureRedirect: '/auth/error' } ), finalizeAuth ) return strategy diff --git a/modules/auth/strategies/google.js b/modules/auth/strategies/google.js index b76d833e0..5ddbd0741 100644 --- a/modules/auth/strategies/google.js +++ b/modules/auth/strategies/google.js @@ -7,12 +7,12 @@ const appRoot = require( 'app-root-path' ) const { findOrCreateUser } = require( `${appRoot}/modules/core/services/users` ) const { getApp, createAuthorizationCode, createAppTokenFromAccessCode } = require( '../services/apps' ) -module.exports = ( app, session, sessionAppId, finalizeAuth ) => { +module.exports = ( app, session, sessionStorage, finalizeAuth ) => { const strategy = { id: 'google', name: 'Google', - icon: 'TODO', - color: 'white red--text', + icon: 'mdi-google', + color: 'red darken-3', url: '/auth/goog', callbackUrl: '/auth/goog/callback' } @@ -40,7 +40,7 @@ module.exports = ( app, session, sessionAppId, finalizeAuth ) => { passport.use( myStrategy ) - app.get( strategy.url, session, sessionAppId, passport.authenticate( 'google' ) ) + app.get( strategy.url, session, sessionStorage, passport.authenticate( 'google' ) ) app.get( '/auth/goog/callback', session, passport.authenticate( 'google', { failureRedirect: '/auth/error' } ), finalizeAuth ) return strategy diff --git a/modules/auth/strategies/local.js b/modules/auth/strategies/local.js index d9083dca3..bba26b6ec 100644 --- a/modules/auth/strategies/local.js +++ b/modules/auth/strategies/local.js @@ -12,25 +12,28 @@ module.exports = ( app, session, sessionAppId, finalizeAuth ) => { name: 'Local', icon: 'TODO', color: 'accent', - url: `/auth/local` + url: '/auth/local' } app.post( '/auth/local/login', session, sessionAppId, async ( req, res, next ) => { - let valid = await validatePasssword( { email: req.body.email, password: req.body.password } ) + try { + let valid = await validatePasssword( { email: req.body.email, password: req.body.password } ) - if ( !valid ) { + if ( !valid ) throw new Error( 'Invalid credentials' ) + + let user = await getUserByEmail( { email: req.body.email } ) + if ( !user ) throw new Error( 'Invalid credentials' ) + + if ( req.body.suuid && user.suuid !== req.body.suuid ) { + await updateUser( user.id, { suuid: req.body.suuid } ) + } + + req.user = { id: user.id } + + next( ) + } catch ( err ){ return res.status( 401 ).send( { err: true, message: 'Invalid credentials' } ) } - - let user = await getUserByEmail( { email: req.body.email } ) - - if ( req.body.suuid && user.suuid !== req.body.suuid ) { - await updateUser( user.id, { suuid: req.body.suuid } ) - } - - req.user = { id: user.id } - - next( ) }, finalizeAuth ) app.post( '/auth/local/register', session, sessionAppId, async ( req, res, next ) => { diff --git a/modules/core/migrations/002-2020-05-18-scopes.js b/modules/core/migrations/002-2020-05-18-scopes.js index 5e3ea5072..b9a07c370 100644 --- a/modules/core/migrations/002-2020-05-18-scopes.js +++ b/modules/core/migrations/002-2020-05-18-scopes.js @@ -5,26 +5,26 @@ let debug = require( 'debug' )( 'speckle:modules' ) exports.up = async knex => { debug( 'Setting up core module scopes.' ) - let coreModuleScopes = [ + let coreModuleScopes = [ { name: 'streams:read', - description: 'Read your streams & and any associated information (branches, tags, comments, objects, etc.)' + description: 'Read your streams, and any associated information (branches, commits, objects).' }, { name: 'streams:write', - description: 'Create streams on your behalf and read your streams & any associated information (any associated information (branches, tags, comments, objects, etc.)' + description: 'Create streams on your behalf, and any associated data (branches, commits, objects).' }, { name: 'profile:read', - description: `Read your profile information.` + description: 'Read your profile information (name, bio, company).' }, { name: 'profile:email', - description: `Access your email.` + description: 'Grants access to the email address you registered with.' }, { name: 'users:read', - description: `Read other users' profile on your behalf.` + description: 'Read other users\' profile on your behalf.' }, { name: 'users:email', @@ -36,12 +36,12 @@ exports.up = async knex => { }, { name: 'tokens:read', - description: `Access your api tokens.` + description: 'Access your api tokens.' }, { name: 'tokens:write', - description: `Create and delete api tokens on your behalf.` - }] + description: 'Create and delete api tokens on your behalf.' + } ] await knex( 'scopes' ).insert( coreModuleScopes ) } diff --git a/modules/core/rest/upload.js b/modules/core/rest/upload.js index 1647839b7..2ab1214c4 100644 --- a/modules/core/rest/upload.js +++ b/modules/core/rest/upload.js @@ -11,7 +11,7 @@ const { createObjects, createObjectsBatched } = require( '../services/objects' ) module.exports = ( app ) => { app.post( '/objects/:streamId', contextMiddleware, async ( req, res ) => { - debug( 'speckle:upload-endpoint' )( `booom upload endpoint` ) + debug( 'speckle:upload-endpoint' )( 'booom upload endpoint' ) if ( !req.context || !req.context.auth ) { return res.status( 401 ).end( ) @@ -29,7 +29,7 @@ module.exports = ( app ) => { return res.status( 401 ).end( ) } - debug( 'speckle:upload-endpoint' )( `Upload started` ) + debug( 'speckle:upload-endpoint' )( 'Upload started' ) let busboy = new Busboy( { headers: req.headers } ) let totalProcessed = 0 @@ -57,7 +57,7 @@ module.exports = ( app ) => { objs = JSON.parse( gunzipedBuffer ) } catch ( e ) { requestDropped = true - return res.status( 400 ).send( `Failed to parse data.` ) + return res.status( 400 ).send( 'Failed to parse data.' ) } last = objs[ objs.length - 1 ] @@ -82,7 +82,7 @@ module.exports = ( app ) => { objs = JSON.parse( buffer ) } catch ( e ) { requestDropped = true - return res.status( 400 ).send( `Failed to parse data.` ) + return res.status( 400 ).send( 'Failed to parse data.' ) } last = objs[ objs.length - 1 ] totalProcessed += objs.length @@ -94,7 +94,7 @@ module.exports = ( app ) => { } ) } else { requestDropped = true - return res.status( 400 ).send( `Invalid ContentType header. This route only accepts "application/gzip", "text/plain" or "application/json".` ) + return res.status( 400 ).send( 'Invalid ContentType header. This route only accepts "application/gzip", "text/plain" or "application/json".' ) } } ) @@ -105,7 +105,7 @@ module.exports = ( app ) => { await Promise.all( promises ) - debug( 'speckle:upload-endpoint' )( `Upload ended` ) + debug( 'speckle:upload-endpoint' )( 'Upload ended' ) res.status( 201 ).end( ) } ) diff --git a/modules/core/services/tokens.js b/modules/core/services/tokens.js index 8fb6acad5..8c1c83ccc 100644 --- a/modules/core/services/tokens.js +++ b/modules/core/services/tokens.js @@ -92,7 +92,6 @@ module.exports = { async revokeToken( tokenId, userId ) { tokenId = tokenId.slice( 0, 10 ) - let token = await ApiTokens( ).where( { id: tokenId } ).select( "*" ) let delCount = await ApiTokens( ).where( { id: tokenId, owner: userId } ).del( ) if ( delCount === 0 ) diff --git a/modules/shared/index.js b/modules/shared/index.js index 06960b17f..8e585d547 100644 --- a/modules/shared/index.js +++ b/modules/shared/index.js @@ -29,8 +29,8 @@ async function contextApiTokenHelper( { req, res, connection } ) { token = req.headers.authorization } - if ( token && token.includes( "Bearer " ) ) { - token = token.split( " " )[ 1 ] + if ( token && token.includes( 'Bearer ' ) ) { + token = token.split( ' ' )[ 1 ] } if ( token === null )