282 lines
8.1 KiB
JavaScript
282 lines
8.1 KiB
JavaScript
/* istanbul ignore file */
|
|
const expect = require('chai').expect
|
|
const appRoot = require('app-root-path')
|
|
|
|
const { createUser } = require(`${appRoot}/modules/core/services/users`)
|
|
const { validateToken } = require(`${appRoot}/modules/core/services/tokens`)
|
|
const { beforeEachContext } = require(`${appRoot}/test/hooks`)
|
|
const {
|
|
getApp,
|
|
getAllPublicApps,
|
|
createApp,
|
|
updateApp,
|
|
deleteApp,
|
|
createAuthorizationCode,
|
|
createAppTokenFromAccessCode,
|
|
refreshAppToken,
|
|
revokeExistingAppCredentialsForUser
|
|
} = require('../services/apps')
|
|
|
|
describe('Services @apps-services', () => {
|
|
const actor = {
|
|
name: 'Dimitrie Stefanescu',
|
|
email: 'didimitrie@gmail.com',
|
|
password: 'wtfwtfwtf'
|
|
}
|
|
|
|
before(async () => {
|
|
await beforeEachContext()
|
|
actor.id = await createUser(actor)
|
|
})
|
|
|
|
it('Should get the frontend main app', async () => {
|
|
const app = await getApp({ id: 'spklwebapp' })
|
|
expect(app).to.be.an('object')
|
|
expect(app.redirectUrl).to.be.a('string')
|
|
expect(app.scopes).to.be.a('array')
|
|
})
|
|
|
|
it('Should get the desktop manager app', async () => {
|
|
const app = await getApp({ id: 'sdm' })
|
|
expect(app).to.be.an('object')
|
|
expect(app.redirectUrl).to.be.a('string')
|
|
expect(app.scopes).to.be.a('array')
|
|
})
|
|
|
|
it('Should get the explorer app', async () => {
|
|
const app = await getApp({ id: 'explorer' })
|
|
expect(app).to.be.an('object')
|
|
expect(app.redirectUrl).to.be.a('string')
|
|
expect(app.scopes).to.be.a('array')
|
|
})
|
|
|
|
it('Should get the excel app', async () => {
|
|
const app = await getApp({ id: 'spklexcel' })
|
|
expect(app).to.be.an('object')
|
|
expect(app.redirectUrl).to.be.a('string')
|
|
expect(app.scopes).to.be.a('array')
|
|
})
|
|
|
|
let myTestApp = null
|
|
|
|
it('Should register an app', async () => {
|
|
const res = await createApp({
|
|
name: 'test application',
|
|
public: true,
|
|
scopes: ['streams:read'],
|
|
redirectUrl: 'http://localhost:1335'
|
|
})
|
|
|
|
expect(res).to.have.property('id')
|
|
expect(res).to.have.property('secret')
|
|
|
|
expect(res.id).to.be.a('string')
|
|
expect(res.secret).to.be.a('string')
|
|
|
|
const app = await getApp({ id: res.id })
|
|
expect(app.id).to.equal(res.id)
|
|
myTestApp = app
|
|
})
|
|
|
|
it('Should get all the public apps on this server', async () => {
|
|
const apps = await getAllPublicApps()
|
|
expect(apps).to.be.an('array')
|
|
expect(apps.length).to.equal(6)
|
|
})
|
|
|
|
it('Should fail to register an app with no scopes', async () => {
|
|
await createApp({ name: 'test application2', redirectUrl: 'http://localhost:1335' })
|
|
.then(() => {
|
|
throw new Error('this should have been rejected')
|
|
})
|
|
.catch((err) =>
|
|
expect(err.message).to.equal('Cannot create an app with no scopes.')
|
|
)
|
|
})
|
|
|
|
it('Should update an app', async () => {
|
|
const res = await updateApp({
|
|
app: {
|
|
name: 'updated test application',
|
|
id: myTestApp.id,
|
|
scopes: ['streams:read', 'users:read']
|
|
}
|
|
})
|
|
expect(res).to.be.a('string')
|
|
|
|
const app = await getApp({ id: myTestApp.id })
|
|
expect(app.name).to.equal('updated test application')
|
|
expect(app.scopes).to.be.an('array')
|
|
expect(app.scopes.map((s) => s.name)).to.include('users:read')
|
|
expect(app.scopes.map((s) => s.name)).to.include('streams:read')
|
|
})
|
|
|
|
const challenge = 'random'
|
|
let authorizationCode = null
|
|
|
|
it('Should get an authorization code for the app', async () => {
|
|
authorizationCode = await createAuthorizationCode({
|
|
appId: myTestApp.id,
|
|
userId: actor.id,
|
|
challenge
|
|
})
|
|
expect(authorizationCode).to.be.a('string')
|
|
})
|
|
|
|
let tokenCreateResponse = null
|
|
|
|
it('Should get an api token in exchange for the authorization code ', async () => {
|
|
const response = await createAppTokenFromAccessCode({
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
accessCode: authorizationCode,
|
|
challenge: 'random'
|
|
})
|
|
expect(response).to.have.property('token')
|
|
expect(response.token).to.be.a('string')
|
|
expect(response).to.have.property('refreshToken')
|
|
expect(response.refreshToken).to.be.a('string')
|
|
|
|
tokenCreateResponse = response
|
|
|
|
const validation = await validateToken(response.token)
|
|
expect(validation.valid).to.equal(true)
|
|
expect(validation.userId).to.equal(actor.id)
|
|
expect(validation.scopes[0]).to.equal('streams:read')
|
|
})
|
|
|
|
it('Should refresh the token using the refresh token, and get a fresh refresh token and token', async () => {
|
|
const res = await refreshAppToken({
|
|
refreshToken: tokenCreateResponse.refreshToken,
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
userId: actor.id
|
|
})
|
|
|
|
expect(res.token).to.be.a('string')
|
|
expect(res.refreshToken).to.be.a('string')
|
|
|
|
const validation = await validateToken(res.token)
|
|
expect(validation.valid).to.equal(true)
|
|
expect(validation.userId).to.equal(actor.id)
|
|
})
|
|
|
|
it('Should invalidate all tokens, refresh tokens and access codes for an app if it is updated', async () => {
|
|
const unusedAccessCode = await createAuthorizationCode({
|
|
appId: myTestApp.id,
|
|
userId: actor.id,
|
|
challenge
|
|
})
|
|
const usedAccessCode = await createAuthorizationCode({
|
|
appId: myTestApp.id,
|
|
userId: actor.id,
|
|
challenge
|
|
})
|
|
const apiTokenResponse = await createAppTokenFromAccessCode({
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
accessCode: usedAccessCode,
|
|
challenge
|
|
})
|
|
|
|
// We now have one unused access code, an api token and a refresh token.
|
|
// Proceed to update the app:
|
|
await updateApp({
|
|
app: {
|
|
name: 'updated test application',
|
|
id: myTestApp.id,
|
|
scopes: ['streams:write', 'users:read']
|
|
}
|
|
})
|
|
|
|
const validationResponse = await validateToken(apiTokenResponse.token)
|
|
expect(validationResponse.valid).to.equal(false)
|
|
|
|
await refreshAppToken({
|
|
refreshToken: apiTokenResponse.refreshToken,
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret
|
|
})
|
|
.then(() => {
|
|
throw new Error('this should have been rejected')
|
|
})
|
|
.catch((err) => expect(err.message).to.equal('Invalid request'))
|
|
|
|
await createAppTokenFromAccessCode({
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
accessCode: unusedAccessCode,
|
|
challenge: 'random'
|
|
})
|
|
.then(() => {
|
|
throw new Error('this should have been rejected')
|
|
})
|
|
.catch((err) => expect(err.message).to.equal('Access code not found.'))
|
|
})
|
|
|
|
it('Should revoke access for a given user', async () => {
|
|
const secondUser = {
|
|
name: 'Dimitrie Stefanescu',
|
|
email: 'didimitrie.wow@gmail.com',
|
|
password: 'wtfwtfwtf'
|
|
}
|
|
|
|
secondUser.id = await createUser(secondUser)
|
|
const accessCode = await createAuthorizationCode({
|
|
appId: myTestApp.id,
|
|
userId: secondUser.id,
|
|
challenge
|
|
})
|
|
const apiTokenResponse = await createAppTokenFromAccessCode({
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
accessCode,
|
|
challenge
|
|
})
|
|
|
|
await revokeExistingAppCredentialsForUser({
|
|
appId: myTestApp.id,
|
|
userId: secondUser.id
|
|
})
|
|
|
|
await refreshAppToken({
|
|
refreshToken: apiTokenResponse.refreshToken,
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret
|
|
})
|
|
.then(() => {
|
|
throw new Error('this should have been rejected')
|
|
})
|
|
.catch((err) => expect(err.message).to.equal('Invalid request'))
|
|
|
|
const unusedAccessCode = await createAuthorizationCode({
|
|
appId: myTestApp.id,
|
|
userId: actor.id,
|
|
challenge
|
|
})
|
|
|
|
await createAppTokenFromAccessCode({
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
accessCode: unusedAccessCode,
|
|
challenge: 'random'
|
|
})
|
|
|
|
await createAppTokenFromAccessCode({
|
|
appId: myTestApp.id,
|
|
appSecret: myTestApp.secret,
|
|
accessCode: unusedAccessCode,
|
|
challenge: 'random'
|
|
})
|
|
.then(() => {
|
|
throw new Error('this should have been rejected')
|
|
})
|
|
.catch((err) => expect(err.message).to.equal('Access code not found.'))
|
|
})
|
|
|
|
it('Should delete an app', async () => {
|
|
const res = await deleteApp({ id: myTestApp.id })
|
|
expect(res).to.equal(1)
|
|
})
|
|
})
|