mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-30 23:33:34 +00:00 
			
		
		
		
	Add a field to specify a list of allowed emails when using OpenID Connect auth.
This commit is contained in:
		
							
								
								
									
										40
									
								
								backend/migrations/20200522144240_openid_allowed_users.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								backend/migrations/20200522144240_openid_allowed_users.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| const migrate_name = 'openid_allowed_users'; | ||||
| 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.table('proxy_host', function (proxy_host) { | ||||
| 		proxy_host.integer('openidc_restrict_users_enabled').notNull().unsigned().defaultTo(0); | ||||
| 		proxy_host.json('openidc_allowed_users').notNull().defaultTo([]); | ||||
| 	}) | ||||
| 		.then(() => { | ||||
| 			logger.info('[' + migrate_name + '] proxy_host Table altered'); | ||||
| 		}); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Undo Migrate | ||||
|  * | ||||
|  * @param   {Object}  knex | ||||
|  * @param   {Promise} Promise | ||||
|  * @returns {Promise} | ||||
|  */ | ||||
| exports.down = function (knex/*, Promise*/) { | ||||
| 	return knex.schema.table('proxy_host', function (proxy_host) { | ||||
| 		proxy_host.dropColumn('openidc_restrict_users_enabled'); | ||||
| 		proxy_host.dropColumn('openidc_allowed_users'); | ||||
| 	}) | ||||
| 		.then(() => { | ||||
| 			logger.info('[' + migrate_name + '] proxy_host Table altered'); | ||||
| 		}); | ||||
| }; | ||||
| @@ -20,12 +20,18 @@ class ProxyHost extends Model { | ||||
| 			this.domain_names = []; | ||||
| 		} | ||||
|  | ||||
| 		// Default for openidc_allowed_users | ||||
| 		if (typeof this.openidc_allowed_users === 'undefined') { | ||||
| 			this.openidc_allowed_users = []; | ||||
| 		} | ||||
|  | ||||
| 		// Default for meta | ||||
| 		if (typeof this.meta === 'undefined') { | ||||
| 			this.meta = {}; | ||||
| 		} | ||||
|  | ||||
| 		this.domain_names.sort(); | ||||
| 		this.openidc_allowed_users.sort(); | ||||
| 	} | ||||
|  | ||||
| 	$beforeUpdate () { | ||||
| @@ -35,6 +41,11 @@ class ProxyHost extends Model { | ||||
| 		if (typeof this.domain_names !== 'undefined') { | ||||
| 			this.domain_names.sort(); | ||||
| 		} | ||||
|  | ||||
| 		// Sort openidc_allowed_users | ||||
| 		if (typeof this.openidc_allowed_users !== 'undefined') { | ||||
| 			this.openidc_allowed_users.sort(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static get name () { | ||||
| @@ -46,7 +57,7 @@ class ProxyHost extends Model { | ||||
| 	} | ||||
|  | ||||
| 	static get jsonAttributes () { | ||||
| 		return ['domain_names', 'meta', 'locations']; | ||||
| 		return ['domain_names', 'meta', 'locations', 'openidc_allowed_users']; | ||||
| 	} | ||||
|  | ||||
| 	static get relationMappings () { | ||||
|   | ||||
| @@ -256,6 +256,22 @@ | ||||
|     }, | ||||
|     "openidc_client_secret": { | ||||
|       "type": "string" | ||||
|     }, | ||||
|     "openidc_restrict_users_enabled": { | ||||
|       "description": "Only allow a specific set of OpenID Connect emails to access the resource", | ||||
|       "example": true, | ||||
|       "type": "boolean" | ||||
|     }, | ||||
|     "openidc_allowed_users": { | ||||
|       "type": "array", | ||||
|       "minItems": 0, | ||||
|       "items": { | ||||
|         "type": "string", | ||||
|         "description": "Email Address", | ||||
|         "example": "john@example.com", | ||||
|         "format": "email", | ||||
|         "minLength": 1 | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -82,6 +82,12 @@ | ||||
|     "openidc_client_secret": { | ||||
|       "$ref": "../definitions.json#/definitions/openidc_client_secret" | ||||
|     }, | ||||
|     "openidc_restrict_users_enabled": { | ||||
|       "$ref": "../definitions.json#/definitions/openidc_restrict_users_enabled" | ||||
|     }, | ||||
|     "openidc_allowed_users": { | ||||
|       "$ref": "../definitions.json#/definitions/openidc_allowed_users" | ||||
|     }, | ||||
|     "enabled": { | ||||
|       "$ref": "../definitions.json#/definitions/enabled" | ||||
|     }, | ||||
| @@ -197,6 +203,12 @@ | ||||
|     "openidc_client_secret": { | ||||
|       "$ref": "#/definitions/openidc_client_secret" | ||||
|     }, | ||||
|     "openidc_restrict_users_enabled": { | ||||
|       "$ref": "#/definitions/openidc_restrict_users_enabled" | ||||
|     }, | ||||
|     "openidc_allowed_users": { | ||||
|       "$ref": "#/definitions/openidc_allowed_users" | ||||
|     }, | ||||
|     "enabled": { | ||||
|       "$ref": "#/definitions/enabled" | ||||
|     }, | ||||
| @@ -305,6 +317,12 @@ | ||||
|           "openidc_client_secret": { | ||||
|             "$ref": "#/definitions/openidc_client_secret" | ||||
|           }, | ||||
|           "openidc_restrict_users_enabled": { | ||||
|             "$ref": "#/definitions/openidc_restrict_users_enabled" | ||||
|           }, | ||||
|           "openidc_allowed_users": { | ||||
|             "$ref": "#/definitions/openidc_allowed_users" | ||||
|           }, | ||||
|           "enabled": { | ||||
|             "$ref": "#/definitions/enabled" | ||||
|           }, | ||||
| @@ -396,6 +414,12 @@ | ||||
|           "openidc_client_secret": { | ||||
|             "$ref": "#/definitions/openidc_client_secret" | ||||
|           }, | ||||
|           "openidc_restrict_users_enabled": { | ||||
|             "$ref": "#/definitions/openidc_restrict_users_enabled" | ||||
|           }, | ||||
|           "openidc_allowed_users": { | ||||
|             "$ref": "#/definitions/openidc_allowed_users" | ||||
|           }, | ||||
|           "enabled": { | ||||
|             "$ref": "#/definitions/enabled" | ||||
|           }, | ||||
|   | ||||
| @@ -280,7 +280,7 @@ | ||||
|                                 <label class="custom-switch"> | ||||
|                                     <input type="checkbox" class="custom-switch-input" name="openidc_enabled" value="1"<%- openidc_enabled ? ' checked' : '' %>> | ||||
|                                     <span class="custom-switch-indicator"></span> | ||||
|                                     <span class="custom-switch-description">Use OpenID Connect authentication <span class="form-required">*</span></span> | ||||
|                                     <span class="custom-switch-description">Use OpenID Connect authentication</span> | ||||
|                                 </label> | ||||
|                             </div> | ||||
|                         </div> | ||||
| @@ -317,6 +317,23 @@ | ||||
|                                 <input type="text" name="openidc_client_secret" class="form-control text-monospace" placeholder="" value="<%- openidc_client_secret %>" autocomplete="off" maxlength="255" required> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="openidc"> | ||||
|                             <div class="col-sm-12 col-md-12"> | ||||
|                                 <div class="form-group"> | ||||
|                                     <label class="custom-switch"> | ||||
|                                         <input type="checkbox" class="custom-switch-input" name="openidc_restrict_users_enabled" value="1"<%- openidc_restrict_users_enabled ? ' checked' : '' %>> | ||||
|                                         <span class="custom-switch-indicator"></span> | ||||
|                                         <span class="custom-switch-description">Allow only these user emails</span> | ||||
|                                     </label> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                             <div class="col-sm-12 col-md-12 openidc_users"> | ||||
|                                 <div class="form-group"> | ||||
|                                     <label class="form-label">Allowed email addresses<span class="form-required">*</span></label> | ||||
|                                     <input type="text" name="openidc_allowed_users" class="form-control" id="openidc_allowed_users" value="<%- openidc_allowed_users.join(',') %>" required> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
| @@ -21,31 +21,34 @@ module.exports = Mn.View.extend({ | ||||
|     locationsCollection: new ProxyLocationModel.Collection(), | ||||
|  | ||||
|     ui: { | ||||
|         form:                     'form', | ||||
|         domain_names:             'input[name="domain_names"]', | ||||
|         forward_host:             'input[name="forward_host"]', | ||||
|         buttons:                  '.modal-footer button', | ||||
|         cancel:                   'button.cancel', | ||||
|         save:                     'button.save', | ||||
|         add_location_btn:         'button.add_location', | ||||
|         locations_container:      '.locations_container', | ||||
|         le_error_info:            '#le-error-info', | ||||
|         certificate_select:       'select[name="certificate_id"]', | ||||
|         access_list_select:       'select[name="access_list_id"]', | ||||
|         ssl_forced:               'input[name="ssl_forced"]', | ||||
|         hsts_enabled:             'input[name="hsts_enabled"]', | ||||
|         hsts_subdomains:          'input[name="hsts_subdomains"]', | ||||
|         http2_support:            'input[name="http2_support"]', | ||||
|         dns_challenge_switch:     'input[name="meta[dns_challenge]"]', | ||||
|         dns_challenge_content:    '.dns-challenge', | ||||
|         dns_provider:             'select[name="meta[dns_provider]"]', | ||||
|         credentials_file_content: '.credentials-file-content', | ||||
|         dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]', | ||||
|         propagation_seconds:      'input[name="meta[propagation_seconds]"]', | ||||
|         forward_scheme:           'select[name="forward_scheme"]', | ||||
|         letsencrypt:              '.letsencrypt', | ||||
|         openidc_enabled:          'input[name="openidc_enabled"]', | ||||
|         openidc:                  '.openidc' | ||||
|         form:                           'form', | ||||
|         domain_names:                   'input[name="domain_names"]', | ||||
|         forward_host:                   'input[name="forward_host"]', | ||||
|         buttons:                        '.modal-footer button', | ||||
|         cancel:                         'button.cancel', | ||||
|         save:                           'button.save', | ||||
|         add_location_btn:               'button.add_location', | ||||
|         locations_container:            '.locations_container', | ||||
|         le_error_info:                  '#le-error-info', | ||||
|         certificate_select:             'select[name="certificate_id"]', | ||||
|         access_list_select:             'select[name="access_list_id"]', | ||||
|         ssl_forced:                     'input[name="ssl_forced"]', | ||||
|         hsts_enabled:                   'input[name="hsts_enabled"]', | ||||
|         hsts_subdomains:                'input[name="hsts_subdomains"]', | ||||
|         http2_support:                  'input[name="http2_support"]', | ||||
|         dns_challenge_switch:           'input[name="meta[dns_challenge]"]', | ||||
|         dns_challenge_content:          '.dns-challenge', | ||||
|         dns_provider:                   'select[name="meta[dns_provider]"]', | ||||
|         credentials_file_content:       '.credentials-file-content', | ||||
|         dns_provider_credentials:       'textarea[name="meta[dns_provider_credentials]"]', | ||||
|         propagation_seconds:            'input[name="meta[propagation_seconds]"]', | ||||
|         forward_scheme:                 'select[name="forward_scheme"]', | ||||
|         letsencrypt:                    '.letsencrypt', | ||||
|         openidc_enabled:                'input[name="openidc_enabled"]', | ||||
|         openidc_restrict_users_enabled: 'input[name="openidc_restrict_users_enabled"]', | ||||
|         openidc_allowed_users:          'input[name="openidc_allowed_users"]', | ||||
|         openidc:                        '.openidc', | ||||
|         openidc_users:                  '.openidc_users', | ||||
|     }, | ||||
|  | ||||
|     regions: { | ||||
| @@ -135,9 +138,18 @@ module.exports = Mn.View.extend({ | ||||
|             let checked = this.ui.openidc_enabled.prop('checked'); | ||||
|  | ||||
|             if (checked) { | ||||
|                 this.ui.openidc.show().find('input').prop('required', true); | ||||
|                 this.ui.openidc.show().find('input').prop('disabled', false); | ||||
|             } else { | ||||
|                 this.ui.openidc.hide().find('input').prop('required', false); | ||||
|                 this.ui.openidc.hide().find('input').prop('disabled', true); | ||||
|             } | ||||
|         }, | ||||
|  | ||||
|         'change @ui.openidc_restrict_users_enabled': function () { | ||||
|             let checked = this.ui.openidc_restrict_users_enabled.prop('checked'); | ||||
|             if (checked) { | ||||
|                 this.ui.openidc_users.show().find('input').prop('disabled', false); | ||||
|             } else { | ||||
|                 this.ui.openidc_users.hide().find('input').prop('disabled', true); | ||||
|             } | ||||
|         }, | ||||
|  | ||||
| @@ -180,6 +192,13 @@ module.exports = Mn.View.extend({ | ||||
|             data.hsts_subdomains         = !!data.hsts_subdomains; | ||||
|             data.ssl_forced              = !!data.ssl_forced; | ||||
|             data.openidc_enabled         = data.openidc_enabled === '1'; | ||||
|             data.openidc_restrict_users_enabled = data.openidc_restrict_users_enabled === '1'; | ||||
|  | ||||
|             if (data.openidc_restrict_users_enabled) { | ||||
|                 if (typeof data.openidc_allowed_users === 'string' && data.openidc_allowed_users) { | ||||
|                     data.openidc_allowed_users = data.openidc_allowed_users.split(','); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (typeof data.meta === 'undefined') data.meta = {}; | ||||
|             data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1; | ||||
| @@ -365,8 +384,21 @@ module.exports = Mn.View.extend({ | ||||
|         }); | ||||
|  | ||||
|         // OpenID Connect | ||||
|         this.ui.openidc.hide().find('input').prop('required', false); | ||||
|         this.ui.openidc_allowed_users.selectize({ | ||||
|             delimiter:    ',', | ||||
|             persist:      false, | ||||
|             maxOptions:   15, | ||||
|             create:       function (input) { | ||||
|                 return { | ||||
|                     value: input, | ||||
|                     text:  input | ||||
|                 }; | ||||
|             } | ||||
|         }); | ||||
|         this.ui.openidc.hide().find('input').prop('disabled', true); | ||||
|         this.ui.openidc_users.hide().find('input').prop('disabled', true); | ||||
|         this.ui.openidc_enabled.trigger('change'); | ||||
|         this.ui.openidc_restrict_users_enabled.trigger('change'); | ||||
|     }, | ||||
|  | ||||
|     initialize: function (options) { | ||||
|   | ||||
| @@ -28,6 +28,8 @@ const model = Backbone.Model.extend({ | ||||
|             openidc_auth_method:     'client_secret_post', | ||||
|             openidc_client_id:       '', | ||||
|             openidc_client_secret:   '', | ||||
|             openidc_restrict_users_enabled: false, | ||||
|             openidc_allowed_users:   [], | ||||
|             enabled:                 true, | ||||
|             meta:                    {}, | ||||
|             // The following are expansions: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user