You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							122 lines
						
					
					
						
							2.8 KiB
						
					
					
				
			
		
		
	
	
							122 lines
						
					
					
						
							2.8 KiB
						
					
					
				| 'use strict'
 | |
| 
 | |
| const fp = require('fastify-plugin')
 | |
| const reusify = require('reusify')
 | |
| 
 | |
| function checkAuth (fastify, opts, next) {
 | |
|   fastify.decorate('auth', auth)
 | |
|   next()
 | |
| }
 | |
| 
 | |
| function auth (functions, opts) {
 | |
|   if (!Array.isArray(functions)) {
 | |
|     throw new Error('You must give an array of functions to the auth function')
 | |
|   }
 | |
|   if (!functions.length) {
 | |
|     throw new Error('Missing auth functions')
 | |
|   }
 | |
| 
 | |
|   const options = Object.assign({
 | |
|     relation: 'or',
 | |
|     run: null
 | |
|   }, opts)
 | |
| 
 | |
|   if (options.relation !== 'or' && options.relation !== 'and') {
 | |
|     throw new Error('The value of options.relation should be one of [\'or\', \'and\']')
 | |
|   }
 | |
|   if (options.run && options.run !== 'all') {
 | |
|     throw new Error('The value of options.run must be \'all\'')
 | |
|   }
 | |
| 
 | |
|   /* eslint-disable-next-line no-var */
 | |
|   for (var i = 0; i < functions.length; i++) {
 | |
|     functions[i] = functions[i].bind(this)
 | |
|   }
 | |
| 
 | |
|   const instance = reusify(Auth)
 | |
| 
 | |
|   function _auth (request, reply, done) {
 | |
|     const obj = instance.get()
 | |
| 
 | |
|     obj.request = request
 | |
|     obj.reply = reply
 | |
|     obj.done = done
 | |
|     obj.functions = this.functions
 | |
|     obj.options = this.options
 | |
|     obj.i = 0
 | |
|     obj.start = true
 | |
|     obj.firstResult = null
 | |
| 
 | |
|     obj.nextAuth()
 | |
|   }
 | |
| 
 | |
|   return _auth.bind({ functions, options })
 | |
| 
 | |
|   function Auth () {
 | |
|     this.next = null
 | |
|     this.i = 0
 | |
|     this.start = true
 | |
|     this.functions = []
 | |
|     this.options = {}
 | |
|     this.request = null
 | |
|     this.reply = null
 | |
|     this.done = null
 | |
|     this.firstResult = null
 | |
| 
 | |
|     const that = this
 | |
| 
 | |
|     this.nextAuth = function nextAuth (err) {
 | |
|       const func = that.functions[that.i++]
 | |
| 
 | |
|       if (!func) {
 | |
|         that.completeAuth(err)
 | |
|         return
 | |
|       }
 | |
| 
 | |
|       const maybePromise = func(that.request, that.reply, that.onAuth)
 | |
| 
 | |
|       if (maybePromise && typeof maybePromise.then === 'function') {
 | |
|         maybePromise.then(results => that.onAuth(null, results), that.onAuth)
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     this.onAuth = function onAuth (err, results) {
 | |
|       if (that.options.relation === 'or') {
 | |
|         if (err) {
 | |
|           return that.nextAuth(err)
 | |
|         }
 | |
| 
 | |
|         return that.completeAuth()
 | |
|       } else {
 | |
|         if (err) {
 | |
|           return that.completeAuth(err)
 | |
|         }
 | |
| 
 | |
|         return that.nextAuth(err)
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     this.completeAuth = function (err) {
 | |
|       if (that.start) {
 | |
|         that.start = false
 | |
|         that.firstResult = err
 | |
|       }
 | |
| 
 | |
|       if (that.options.run === 'all' && that.i < that.functions.length) {
 | |
|         return that.nextAuth(err)
 | |
|       }
 | |
| 
 | |
|       if (that.firstResult && (!that.reply.raw.statusCode || that.reply.raw.statusCode < 400)) {
 | |
|         that.reply.code(401)
 | |
|       } else if (!that.firstResult && that.reply.raw.statusCode && that.reply.raw.statusCode >= 400) {
 | |
|         that.reply.code(200)
 | |
|       }
 | |
| 
 | |
|       that.done(that.firstResult)
 | |
|       instance.release(that)
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| module.exports = fp(checkAuth, '3.x')
 |