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
			| 
											3 years ago
										 | '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') |