UNPKG

@quarks/quarks-iam

Version:

A modern authorization server built to authenticate your users and protect your APIs

340 lines (235 loc) 8.12 kB
# Test dependencies cwd = process.cwd() path = require 'path' chai = require 'chai' sinon = require 'sinon' sinonChai = require 'sinon-chai' mockMulti = require '../lib/multi' expect = chai.expect # Configure Chai and Sinon chai.use sinonChai chai.should() # Code under test OneTimeToken = require path.join(cwd, 'models/OneTimeToken') # Redis lib for spying and stubbing Redis = require('ioredis') rclient = Redis.prototype {client,multi} = {} describe 'OneTimeToken', -> before -> client = new Redis(12345) multi = mockMulti(rclient) after -> rclient.multi.restore() describe 'constructor', -> {options,token} = {} beforeEach -> options = exp: Math.round(Date.now() / 1000) + 3600 use: 'test' sub: 'dim_sum' token = new OneTimeToken options it 'should generate a collision-free random id', -> token2 = new OneTimeToken options token._id.should.not.equal token2._id it 'should set the exp from options', -> token.exp.should.equal options.exp it 'should calculate the exp from ttl', -> options2 = ttl: 3600 use: options.use sub: options.sub exp = Math.round(Date.now() / 1000) + 3600 token2 = new OneTimeToken options2 expect(token2.exp).to.be.within(exp - 100, exp + 100) it 'should set the use from options', -> token.use.should.equal options.use it 'should set the sub from options', -> token.sub.should.equal options.sub describe 'peek', -> {rawToken, rawExpiredToken} = {} before -> sinon.stub(rclient, 'get').callsFake((key, callback) -> key = key.split(':')[1] if (key == 'valid') callback null, JSON.stringify(rawToken) else if (key == 'expired') callback null, JSON.stringify(rawExpiredToken) else if (key == 'malformed') callback null, 'banh_mi' else callback null, null) after -> rclient.get.restore() beforeEach -> rawToken = _id: '4f7c3891d95a479c6385720d240916d27e12708500471a50a4b2715a9e7a5576' exp: Math.round(Date.now() / 1000) + 3600 use: 'test' sub: 'spring_roll' rawExpiredToken = _id: '4f7c3891d95a479c6385720d240916d27e12708500471a50a4b2715a9e7a5576' exp: Math.round(Date.now() / 1000) - 3600 use: 'test' sub: 'pho' describe 'with unknown token', -> {err,token} = {} before (done) -> OneTimeToken.peek 'unknown', (error,result) -> err = error token = result done() it 'should provide a null error', -> expect(err).to.be.null it 'should provide a null value', -> expect(token).to.be.null describe 'with expired token', -> {err,token} = {} before (done) -> OneTimeToken.peek 'expired', (error,result) -> err = error token = result done() it 'should provide a null error', -> expect(err).to.be.null it 'should provide a null value', -> expect(token).to.be.null describe 'with malformed result', -> {err,token} = {} before (done) -> OneTimeToken.peek 'malformed', (error,result) -> err = error token = result done() it 'should provide an error', -> expect(err).to.be.an.instanceof Error it 'should not provide a value', -> expect(token).to.be.undefined describe 'with valid token', -> {err,token} = {} before (done) -> OneTimeToken.peek 'valid', (error,result) -> err = error token = result done() it 'should provide a null error', -> expect(err).to.be.null it 'should provide a OneTimeToken instance', -> expect(token).to.be.an.instanceof OneTimeToken token._id.should.equal rawToken._id token.exp.should.be.within(rawToken.exp - 100, rawToken.exp + 100) token.sub.should.equal rawToken.sub token.use.should.equal rawToken.use describe 'revoke', -> {err} = {} before (done) -> sinon.stub(rclient, 'del').callsArgWith 1, null OneTimeToken.revoke 'id', (error) -> err = error done() after -> rclient.del.restore() it 'should provide a falsy error', -> expect(err).to.not.be.ok it 'should delete the token', -> rclient.del.should.have.been.called describe 'consume', -> {err,token} = {} rawToken = _id: 'valid' exp: Math.round(Date.now() / 1000) + 3600 use: 'test' sub: 'nhung_dam' before (done) -> sinon.stub(OneTimeToken, 'peek') .callsArgWith 1, null, new OneTimeToken rawToken sinon.stub(OneTimeToken, 'revoke') .callsArgWith 1, null OneTimeToken.consume 'valid', (error,result) -> err = error token = result done() after -> OneTimeToken.peek.restore() OneTimeToken.revoke.restore() it 'should provide a null error', -> expect(err).to.be.null it 'should provide a OneTimeToken instance', -> expect(token).to.be.an.instanceof OneTimeToken token._id.should.equal rawToken._id token.exp.should.be.within(rawToken.exp - 100, rawToken.exp + 100) token.use.should.equal rawToken.use token.sub.should.equal rawToken.sub it 'should revoke the token', -> OneTimeToken.revoke.should.have.been.calledWith token._id describe 'issue', -> {err,token} = {} rawToken = exp: Math.round(Date.now() / 1000) + 3600 use: 'test' sub: 'nem_nuong' otToken = new OneTimeToken rawToken noexpToken = use: 'test' sub: 'banh_flan' beforeEach -> sinon.stub multi, 'set' sinon.stub multi, 'expireat' sinon.stub(multi, 'exec').callsArgWith 0, null, [] afterEach -> multi.set.restore() multi.expireat.restore() multi.exec.restore() describe 'with raw token data', -> {err,token} = {} beforeEach (done) -> OneTimeToken.issue rawToken, (error, result) -> err = error token = result done() it 'should provide a null error', -> expect(err).to.be.null it 'should store the token', -> multi.set.should.have.been.called multi.exec.should.have.been.called it 'should set the token to expire', -> multi.expireat.should.have.been.called it 'should provide a OneTimeToken instance', -> expect(token).to.be.an.instanceof OneTimeToken token.exp.should.be.within rawToken.exp - 100, rawToken.exp + 100 token.use.should.equal rawToken.use token.sub.should.equal rawToken.sub describe 'with OneTimeToken instance', -> {err,token} = {} beforeEach (done) -> OneTimeToken.issue otToken, (error, result) -> err = error token = result done() it 'should provide a null error', -> expect(err).to.be.null it 'should store the token', -> multi.set.should.have.been.calledWith( 'onetimetoken:' + otToken._id, JSON.stringify(otToken) ) it 'should set the token to expire', -> multi.expireat.should.have.been.called it 'should provide the same OneTimeToken instance', -> token.should.eql otToken describe 'without expiration date', -> {err,token} = {} beforeEach (done) -> OneTimeToken.issue noexpToken, (error, result) -> err = error token = result done() it 'should provide a null error', -> expect(err).to.be.null it 'should store the token', -> multi.set.should.have.been.called multi.exec.should.have.been.called it 'should not set the token to expire', -> multi.expireat.should.not.have.been.called it 'should provide a OneTimeToken instance', -> expect(token).to.be.an.instanceof OneTimeToken