mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-31 15:53:33 +00:00 
			
		
		
		
	add access list clients to back-end
This commit is contained in:
		| @@ -1,14 +1,15 @@ | ||||
| const _                   = require('lodash'); | ||||
| const fs                  = require('fs'); | ||||
| const batchflow           = require('batchflow'); | ||||
| const logger              = require('../logger').access; | ||||
| const error               = require('../lib/error'); | ||||
| const accessListModel     = require('../models/access_list'); | ||||
| const accessListAuthModel = require('../models/access_list_auth'); | ||||
| const proxyHostModel      = require('../models/proxy_host'); | ||||
| const internalAuditLog    = require('./audit-log'); | ||||
| const internalNginx       = require('./nginx'); | ||||
| const utils               = require('../lib/utils'); | ||||
| const _                     = require('lodash'); | ||||
| const fs                    = require('fs'); | ||||
| const batchflow             = require('batchflow'); | ||||
| const logger                = require('../logger').access; | ||||
| const error                 = require('../lib/error'); | ||||
| const accessListModel       = require('../models/access_list'); | ||||
| const accessListAuthModel   = require('../models/access_list_auth'); | ||||
| const accessListClientModel = require('../models/access_list_client'); | ||||
| const proxyHostModel        = require('../models/proxy_host'); | ||||
| const internalAuditLog      = require('./audit-log'); | ||||
| const internalNginx         = require('./nginx'); | ||||
| const utils                 = require('../lib/utils'); | ||||
|  | ||||
| function omissions () { | ||||
| 	return ['is_deleted']; | ||||
| @@ -35,8 +36,9 @@ const internalAccessList = { | ||||
| 			.then((row) => { | ||||
| 				data.id = row.id; | ||||
|  | ||||
| 				// Now add the items | ||||
| 				let promises = []; | ||||
|  | ||||
| 				// Now add the items | ||||
| 				data.items.map((item) => { | ||||
| 					promises.push(accessListAuthModel | ||||
| 						.query() | ||||
| @@ -48,13 +50,27 @@ const internalAccessList = { | ||||
| 					); | ||||
| 				}); | ||||
|  | ||||
| 				// Now add the clients | ||||
| 				if (typeof data.clients !== 'undefined' && data.clients) { | ||||
| 					data.clients.map((client) => { | ||||
| 						promises.push(accessListClientModel | ||||
| 							.query() | ||||
| 							.insert({ | ||||
| 								access_list_id: row.id, | ||||
| 								address:        client.address, | ||||
| 								directive:      client.directive | ||||
| 							}) | ||||
| 						); | ||||
| 					}); | ||||
| 				} | ||||
|  | ||||
| 				return Promise.all(promises); | ||||
| 			}) | ||||
| 			.then(() => { | ||||
| 				// re-fetch with expansions | ||||
| 				return internalAccessList.get(access, { | ||||
| 					id:     data.id, | ||||
| 					expand: ['owner', 'items'] | ||||
| 					expand: ['owner', 'items', 'clients'] | ||||
| 				}, true /* <- skip masking */); | ||||
| 			}) | ||||
| 			.then((row) => { | ||||
| @@ -152,6 +168,37 @@ const internalAccessList = { | ||||
| 							} | ||||
| 						}); | ||||
| 				} | ||||
|  | ||||
| 				// Check for clients and add/update/remove them | ||||
| 				if (typeof data.clients !== 'undefined' && data.clients) { | ||||
| 					let promises = []; | ||||
|  | ||||
| 					data.clients.map(function (client) { | ||||
| 						if (client.address) { | ||||
| 							promises.push(accessListAuthModel | ||||
| 								.query() | ||||
| 								.insert({ | ||||
| 									access_list_id: data.id, | ||||
| 									address:        client.address, | ||||
| 									directive:      client.directive | ||||
| 								}) | ||||
| 							); | ||||
| 						} | ||||
| 					}); | ||||
|  | ||||
| 					let query = accessListClientModel | ||||
| 						.query() | ||||
| 						.delete() | ||||
| 						.where('access_list_id', data.id); | ||||
|  | ||||
| 					return query | ||||
| 						.then(() => { | ||||
| 							// Add new items | ||||
| 							if (promises.length) { | ||||
| 								return Promise.all(promises); | ||||
| 							} | ||||
| 						}); | ||||
| 				} | ||||
| 			}) | ||||
| 			.then(() => { | ||||
| 				// Add to audit log | ||||
| @@ -166,7 +213,7 @@ const internalAccessList = { | ||||
| 				// re-fetch with expansions | ||||
| 				return internalAccessList.get(access, { | ||||
| 					id:     data.id, | ||||
| 					expand: ['owner', 'items'] | ||||
| 					expand: ['owner', 'items', 'clients'] | ||||
| 				}, true /* <- skip masking */); | ||||
| 			}) | ||||
| 			.then((row) => { | ||||
| @@ -204,7 +251,7 @@ const internalAccessList = { | ||||
| 					.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0') | ||||
| 					.where('access_list.is_deleted', 0) | ||||
| 					.andWhere('access_list.id', data.id) | ||||
| 					.allowEager('[owner,items,proxy_hosts]') | ||||
| 					.allowEager('[owner,items,clients,proxy_hosts]') | ||||
| 					.omit(['access_list.is_deleted']) | ||||
| 					.first(); | ||||
|  | ||||
| @@ -246,7 +293,7 @@ const internalAccessList = { | ||||
| 	delete: (access, data) => { | ||||
| 		return access.can('access_lists:delete', data.id) | ||||
| 			.then(() => { | ||||
| 				return internalAccessList.get(access, {id: data.id, expand: ['proxy_hosts', 'items']}); | ||||
| 				return internalAccessList.get(access, {id: data.id, expand: ['proxy_hosts', 'items', 'clients']}); | ||||
| 			}) | ||||
| 			.then((row) => { | ||||
| 				if (!row) { | ||||
| @@ -330,7 +377,7 @@ const internalAccessList = { | ||||
| 					.where('access_list.is_deleted', 0) | ||||
| 					.groupBy('access_list.id') | ||||
| 					.omit(['access_list.is_deleted']) | ||||
| 					.allowEager('[owner,items]') | ||||
| 					.allowEager('[owner,items,clients]') | ||||
| 					.orderBy('access_list.name', 'ASC'); | ||||
|  | ||||
| 				if (access_data.permission_visibility !== 'all') { | ||||
|   | ||||
							
								
								
									
										46
									
								
								backend/migrations/20200410143839_access_list_client.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								backend/migrations/20200410143839_access_list_client.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| const migrate_name = 'access_list_client'; | ||||
| const logger       = require('../logger').migrate; | ||||
|  | ||||
| /** | ||||
|  * Migrate | ||||
|  * | ||||
|  * @see http://knexjs.org/#Schema | ||||
|  * | ||||
|  * @param   {Object}  knex | ||||
|  * @param   {Promise} Promise | ||||
|  * @returns {Promise} | ||||
|  */ | ||||
| exports.up = function (knex/*, Promise*/) { | ||||
|  | ||||
| 	logger.info('[' + migrate_name + '] Migrating Up...'); | ||||
|  | ||||
| 	return knex.schema.createTable('access_list_client', (table) => { | ||||
| 		table.increments().primary(); | ||||
| 		table.dateTime('created_on').notNull(); | ||||
| 		table.dateTime('modified_on').notNull(); | ||||
| 		table.integer('access_list_id').notNull().unsigned(); | ||||
| 		table.string('address').notNull(); | ||||
| 		table.string('directive').notNull(); | ||||
| 		table.json('meta').notNull(); | ||||
|  | ||||
| 	}) | ||||
| 		.then(function () { | ||||
| 			logger.info('[' + migrate_name + '] access_list_client Table created'); | ||||
| 		}); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Undo Migrate | ||||
|  * | ||||
|  * @param {Object} knex | ||||
|  * @param {Promise} Promise | ||||
|  * @returns {Promise} | ||||
|  */ | ||||
| exports.down = function (knex/*, Promise*/) { | ||||
| 	logger.info('[' + migrate_name + '] Migrating Down...'); | ||||
|  | ||||
| 	return knex.schema.dropTable('access_list_client') | ||||
| 		.then(() => { | ||||
| 			logger.info('[' + migrate_name + '] access_list_client Table dropped'); | ||||
| 		}); | ||||
| }; | ||||
| @@ -1,10 +1,11 @@ | ||||
| // Objection Docs: | ||||
| // http://vincit.github.io/objection.js/ | ||||
|  | ||||
| const db             = require('../db'); | ||||
| const Model          = require('objection').Model; | ||||
| const User           = require('./user'); | ||||
| const AccessListAuth = require('./access_list_auth'); | ||||
| const db               = require('../db'); | ||||
| const Model            = require('objection').Model; | ||||
| const User             = require('./user'); | ||||
| const AccessListAuth   = require('./access_list_auth'); | ||||
| const AccessListClient = require('./access_list_client'); | ||||
|  | ||||
| Model.knex(db); | ||||
|  | ||||
| @@ -62,6 +63,17 @@ class AccessList extends Model { | ||||
| 					qb.omit(['id', 'created_on', 'modified_on', 'access_list_id', 'meta']); | ||||
| 				} | ||||
| 			}, | ||||
| 			clients: { | ||||
| 				relation:   Model.HasManyRelation, | ||||
| 				modelClass: AccessListClient, | ||||
| 				join:       { | ||||
| 					from: 'access_list.id', | ||||
| 					to:   'access_list_client.access_list_id' | ||||
| 				}, | ||||
| 				modify: function (qb) { | ||||
| 					qb.omit(['id', 'created_on', 'modified_on', 'access_list_id', 'meta']); | ||||
| 				} | ||||
| 			}, | ||||
| 			proxy_hosts: { | ||||
| 				relation:   Model.HasManyRelation, | ||||
| 				modelClass: ProxyHost, | ||||
|   | ||||
							
								
								
									
										54
									
								
								backend/models/access_list_client.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								backend/models/access_list_client.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| // Objection Docs: | ||||
| // http://vincit.github.io/objection.js/ | ||||
|  | ||||
| const db    = require('../db'); | ||||
| const Model = require('objection').Model; | ||||
|  | ||||
| Model.knex(db); | ||||
|  | ||||
| class AccessListClient extends Model { | ||||
| 	$beforeInsert () { | ||||
| 		this.created_on  = Model.raw('NOW()'); | ||||
| 		this.modified_on = Model.raw('NOW()'); | ||||
|  | ||||
| 		// Default for meta | ||||
| 		if (typeof this.meta === 'undefined') { | ||||
| 			this.meta = {}; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	$beforeUpdate () { | ||||
| 		this.modified_on = Model.raw('NOW()'); | ||||
| 	} | ||||
|  | ||||
| 	static get name () { | ||||
| 		return 'AccessListClient'; | ||||
| 	} | ||||
|  | ||||
| 	static get tableName () { | ||||
| 		return 'access_list_client'; | ||||
| 	} | ||||
|  | ||||
| 	static get jsonAttributes () { | ||||
| 		return ['meta']; | ||||
| 	} | ||||
|  | ||||
| 	static get relationMappings () { | ||||
| 		return { | ||||
| 			access_list: { | ||||
| 				relation:   Model.HasOneRelation, | ||||
| 				modelClass: require('./access_list'), | ||||
| 				join:       { | ||||
| 					from: 'access_list_client.access_list_id', | ||||
| 					to:   'access_list.id' | ||||
| 				}, | ||||
| 				modify: function (qb) { | ||||
| 					qb.where('access_list.is_deleted', 0); | ||||
| 					qb.omit(['created_on', 'modified_on', 'is_deleted', 'access_list_id']); | ||||
| 				} | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = AccessListClient; | ||||
| @@ -19,6 +19,14 @@ | ||||
|       "type": "string", | ||||
|       "description": "Name of the Access List" | ||||
|     }, | ||||
|     "directive": { | ||||
|       "type": "string", | ||||
|       "enum": ["allow", "deny"] | ||||
|     }, | ||||
|     "address": { | ||||
|       "type": "string", | ||||
|       "format": "ipv4" | ||||
|     }, | ||||
|     "meta": { | ||||
|       "type": "object" | ||||
|     } | ||||
| @@ -96,6 +104,22 @@ | ||||
|               } | ||||
|             } | ||||
|           }, | ||||
|           "clients": { | ||||
|             "type": "array", | ||||
|             "minItems": 0, | ||||
|             "items": { | ||||
|               "type": "object", | ||||
|               "additionalProperties": false, | ||||
|               "properties": { | ||||
|                 "address": { | ||||
|                   "$ref": "#/definitions/address" | ||||
|                 }, | ||||
|                 "directive": { | ||||
|                   "$ref": "#/definitions/directive" | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           }, | ||||
|           "meta": { | ||||
|             "$ref": "#/definitions/meta" | ||||
|           } | ||||
| @@ -141,6 +165,22 @@ | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           }, | ||||
|           "clients": { | ||||
|             "type": "array", | ||||
|             "minItems": 0, | ||||
|             "items": { | ||||
|               "type": "object", | ||||
|               "additionalProperties": false, | ||||
|               "properties": { | ||||
|                 "address": { | ||||
|                   "$ref": "#/definitions/address" | ||||
|                 }, | ||||
|                 "directive": { | ||||
|                   "$ref": "#/definitions/directive" | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user