mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-31 07:43:33 +00:00 
			
		
		
		
	SSL certificate upload support
This commit is contained in:
		| @@ -3,6 +3,7 @@ | |||||||
| const path        = require('path'); | const path        = require('path'); | ||||||
| const express     = require('express'); | const express     = require('express'); | ||||||
| const bodyParser  = require('body-parser'); | const bodyParser  = require('body-parser'); | ||||||
|  | const fileUpload  = require('express-fileupload'); | ||||||
| const compression = require('compression'); | const compression = require('compression'); | ||||||
| const log         = require('./logger').express; | const log         = require('./logger').express; | ||||||
|  |  | ||||||
| @@ -10,6 +11,7 @@ const log         = require('./logger').express; | |||||||
|  * App |  * App | ||||||
|  */ |  */ | ||||||
| const app = express(); | const app = express(); | ||||||
|  | app.use(fileUpload()); | ||||||
| app.use(bodyParser.json()); | app.use(bodyParser.json()); | ||||||
| app.use(bodyParser.urlencoded({extended: true})); | app.use(bodyParser.urlencoded({extended: true})); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ const deadHostModel        = require('../models/dead_host'); | |||||||
|  |  | ||||||
| const internalHost = { | const internalHost = { | ||||||
|  |  | ||||||
|  |     allowed_ssl_files: ['other_certificate', 'other_certificate_key'], | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Internal use only, checks to see if the domain is already taken by any other record |      * Internal use only, checks to see if the domain is already taken by any other record | ||||||
|      * |      * | ||||||
| @@ -64,6 +66,21 @@ const internalHost = { | |||||||
|             }); |             }); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Cleans the ssl keys from the meta object and sets them to "true" | ||||||
|  |      * | ||||||
|  |      * @param   {Object}  meta | ||||||
|  |      * @returns {*} | ||||||
|  |      */ | ||||||
|  |     cleanMeta: function (meta) { | ||||||
|  |         internalHost.allowed_ssl_files.map(key => { | ||||||
|  |             if (typeof meta[key] !== 'undefined' && meta[key]) { | ||||||
|  |                 meta[key] = true; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         return meta; | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Private call only |      * Private call only | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -96,6 +96,7 @@ const internalProxyHost = { | |||||||
|                     .omit(omissions()) |                     .omit(omissions()) | ||||||
|                     .patchAndFetchById(row.id, data) |                     .patchAndFetchById(row.id, data) | ||||||
|                     .then(saved_row => { |                     .then(saved_row => { | ||||||
|  |                         saved_row.meta = internalHost.cleanMeta(saved_row.meta); | ||||||
|                         return _.omit(saved_row, omissions()); |                         return _.omit(saved_row, omissions()); | ||||||
|                     }); |                     }); | ||||||
|             }); |             }); | ||||||
| @@ -144,6 +145,7 @@ const internalProxyHost = { | |||||||
|             }) |             }) | ||||||
|             .then(row => { |             .then(row => { | ||||||
|                 if (row) { |                 if (row) { | ||||||
|  |                     row.meta = internalHost.cleanMeta(row.meta); | ||||||
|                     return _.omit(row, omissions()); |                     return _.omit(row, omissions()); | ||||||
|                 } else { |                 } else { | ||||||
|                     throw new error.ItemNotFoundError(data.id); |                     throw new error.ItemNotFoundError(data.id); | ||||||
| @@ -180,6 +182,32 @@ const internalProxyHost = { | |||||||
|             }); |             }); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @param   {Access}  access | ||||||
|  |      * @param   {Object}  data | ||||||
|  |      * @param   {Integer} data.id | ||||||
|  |      * @param   {Object}  data.files | ||||||
|  |      * @returns {Promise} | ||||||
|  |      */ | ||||||
|  |     setCerts: (access, data) => { | ||||||
|  |         return internalProxyHost.get(access, {id: data.id}) | ||||||
|  |             .then(row => { | ||||||
|  |                 _.map(data.files, (file, name) => { | ||||||
|  |                     if (internalHost.allowed_ssl_files.indexOf(name) !== -1) { | ||||||
|  |                         row.meta[name] = file.data.toString(); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 return internalProxyHost.update(access, { | ||||||
|  |                     id:   data.id, | ||||||
|  |                     meta: row.meta | ||||||
|  |                 }); | ||||||
|  |             }) | ||||||
|  |             .then(row => { | ||||||
|  |                 return _.pick(row.meta, internalHost.allowed_ssl_files); | ||||||
|  |             }); | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * All Hosts |      * All Hosts | ||||||
|      * |      * | ||||||
| @@ -215,6 +243,13 @@ const internalProxyHost = { | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 return query; |                 return query; | ||||||
|  |             }) | ||||||
|  |             .then(rows => { | ||||||
|  |                 rows.map(row => { | ||||||
|  |                     row.meta = internalHost.cleanMeta(row.meta); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |                 return rows; | ||||||
|             }); |             }); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -234,6 +234,8 @@ module.exports = function (token_string) { | |||||||
|             }); |             }); | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|  |         reloadObjects: this.loadObjects, | ||||||
|  |  | ||||||
|         /** |         /** | ||||||
|          * |          * | ||||||
|          * @param {String}  permission |          * @param {String}  permission | ||||||
| @@ -248,7 +250,6 @@ module.exports = function (token_string) { | |||||||
|                 return this.init() |                 return this.init() | ||||||
|                     .then(() => { |                     .then(() => { | ||||||
|                         // Initialised, token decoded ok |                         // Initialised, token decoded ok | ||||||
|  |  | ||||||
|                         return this.getObjectSchema(permission) |                         return this.getObjectSchema(permission) | ||||||
|                             .then(objectSchema => { |                             .then(objectSchema => { | ||||||
|                                 let data_schema = { |                                 let data_schema = { | ||||||
| @@ -275,9 +276,9 @@ module.exports = function (token_string) { | |||||||
|  |  | ||||||
|                                 permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json'); |                                 permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json'); | ||||||
|  |  | ||||||
|                                 //logger.debug('objectSchema:', JSON.stringify(objectSchema, null, 2)); |                                 // logger.info('objectSchema', JSON.stringify(objectSchema, null, 2)); | ||||||
|                                 //logger.debug('permissionSchema:', JSON.stringify(permissionSchema, null, 2)); |                                 // logger.info('permissionSchema', JSON.stringify(permissionSchema, null, 2)); | ||||||
|                                 //logger.debug('data_schema:', JSON.stringify(data_schema, null, 2)); |                                 // logger.info('data_schema', JSON.stringify(data_schema, null, 2)); | ||||||
|  |  | ||||||
|                                 let ajv = validator({ |                                 let ajv = validator({ | ||||||
|                                     verbose:      true, |                                     verbose:      true, | ||||||
| @@ -301,8 +302,9 @@ module.exports = function (token_string) { | |||||||
|                             }); |                             }); | ||||||
|                     }) |                     }) | ||||||
|                     .catch(err => { |                     .catch(err => { | ||||||
|                         logger.error(err.message); |                         err.permission      = permission; | ||||||
|                         logger.error(err.errors); |                         err.permission_data = data; | ||||||
|  |                         logger.error(permission, data, err.message); | ||||||
|  |  | ||||||
|                         throw new error.PermissionError('Permission Denied', err); |                         throw new error.PermissionError('Permission Denied', err); | ||||||
|                     }); |                     }); | ||||||
|   | |||||||
| @@ -147,4 +147,38 @@ router | |||||||
|             .catch(next); |             .catch(next); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Specific proxy-host Certificates | ||||||
|  |  * | ||||||
|  |  * /api/nginx/proxy-hosts/123/certificates | ||||||
|  |  */ | ||||||
|  | router | ||||||
|  |     .route('/:host_id/certificates') | ||||||
|  |     .options((req, res) => { | ||||||
|  |         res.sendStatus(204); | ||||||
|  |     }) | ||||||
|  |     .all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * POST /api/nginx/proxy-hosts/123/certificates | ||||||
|  |      * | ||||||
|  |      * Upload certifications | ||||||
|  |      */ | ||||||
|  |     .post((req, res, next) => { | ||||||
|  |         if (!req.files) { | ||||||
|  |             res.status(400) | ||||||
|  |                 .send({error: 'No files were uploaded'}); | ||||||
|  |         } else { | ||||||
|  |             internalProxyHost.setCerts(res.locals.access, { | ||||||
|  |                 id:    parseInt(req.params.host_id, 10), | ||||||
|  |                 files: req.files | ||||||
|  |             }) | ||||||
|  |                 .then(result => { | ||||||
|  |                     res.status(200) | ||||||
|  |                         .send(result); | ||||||
|  |                 }) | ||||||
|  |                 .catch(next); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |  | ||||||
| module.exports = router; | module.exports = router; | ||||||
|   | |||||||
| @@ -43,14 +43,19 @@ function fetch (verb, path, data, options) { | |||||||
|         let url     = api_url + path; |         let url     = api_url + path; | ||||||
|         let token   = Tokens.getTopToken(); |         let token   = Tokens.getTopToken(); | ||||||
|  |  | ||||||
|  |         if ((typeof options.contentType === 'undefined' || options.contentType.match(/json/im)) && typeof data === 'object') { | ||||||
|  |             data = JSON.stringify(data); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         $.ajax({ |         $.ajax({ | ||||||
|             url:         url, |             url:         url, | ||||||
|             data:        typeof data === 'object' ? JSON.stringify(data) : data, |             data:        typeof data === 'object' ? JSON.stringify(data) : data, | ||||||
|             type:        verb, |             type:        verb, | ||||||
|             dataType:    'json', |             dataType:    'json', | ||||||
|             contentType: 'application/json; charset=UTF-8', |             contentType: options.contentType || 'application/json; charset=UTF-8', | ||||||
|  |             processData: options.processData || true, | ||||||
|             crossDomain: true, |             crossDomain: true, | ||||||
|             timeout:     (options.timeout ? options.timeout : 15000), |             timeout:     options.timeout ? options.timeout : 15000, | ||||||
|             xhrFields:   { |             xhrFields:   { | ||||||
|                 withCredentials: true |                 withCredentials: true | ||||||
|             }, |             }, | ||||||
| @@ -123,6 +128,41 @@ function getAllObjects (path, expand, query) { | |||||||
|     return fetch('get', path + (params.length ? '?' + params.join('&') : '')); |     return fetch('get', path + (params.length ? '?' + params.join('&') : '')); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @param   {String}  path | ||||||
|  |  * @param   {FormData}  form_data | ||||||
|  |  * @returns {Promise} | ||||||
|  |  */ | ||||||
|  | function upload (path, form_data) { | ||||||
|  |     console.log('UPLOAD:', path, form_data); | ||||||
|  |     return fetch('post', path, form_data, { | ||||||
|  |         contentType: 'multipart/form-data', | ||||||
|  |         processData: false | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function FileUpload (path, fd) { | ||||||
|  |     return new Promise((resolve, reject) => { | ||||||
|  |         let xhr   = new XMLHttpRequest(); | ||||||
|  |         let token = Tokens.getTopToken(); | ||||||
|  |  | ||||||
|  |         xhr.open('POST', '/api/' + path); | ||||||
|  |         xhr.overrideMimeType('text/plain'); | ||||||
|  |         xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null)); | ||||||
|  |         xhr.send(fd); | ||||||
|  |  | ||||||
|  |         xhr.onreadystatechange = function () { | ||||||
|  |             if (this.readyState === XMLHttpRequest.DONE) { | ||||||
|  |                 if (xhr.status !== 200 && xhr.status !== 201) { | ||||||
|  |                     reject(new Error('Upload failed: ' + xhr.status)); | ||||||
|  |                 } else { | ||||||
|  |                     resolve(xhr.responseText); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     status: function () { |     status: function () { | ||||||
|         return fetch('get', ''); |         return fetch('get', ''); | ||||||
| @@ -283,6 +323,15 @@ module.exports = { | |||||||
|              */ |              */ | ||||||
|             delete: function (id) { |             delete: function (id) { | ||||||
|                 return fetch('delete', 'nginx/proxy-hosts/' + id); |                 return fetch('delete', 'nginx/proxy-hosts/' + id); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param  {Integer}  id | ||||||
|  |              * @param  {FormData} form_data | ||||||
|  |              * @params {Promise} | ||||||
|  |              */ | ||||||
|  |             setCerts: function (id, form_data) { | ||||||
|  |                 return FileUpload('nginx/proxy-hosts/' + id + '/certificates', form_data); | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
| @@ -294,6 +343,41 @@ module.exports = { | |||||||
|              */ |              */ | ||||||
|             getAll: function (expand, query) { |             getAll: function (expand, query) { | ||||||
|                 return getAllObjects('nginx/redirection-hosts', expand, query); |                 return getAllObjects('nginx/redirection-hosts', expand, query); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param {Object}  data | ||||||
|  |              */ | ||||||
|  |             create: function (data) { | ||||||
|  |                 return fetch('post', 'nginx/redirection-hosts', data); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param   {Object}   data | ||||||
|  |              * @param   {Integer}  data.id | ||||||
|  |              * @returns {Promise} | ||||||
|  |              */ | ||||||
|  |             update: function (data) { | ||||||
|  |                 let id = data.id; | ||||||
|  |                 delete data.id; | ||||||
|  |                 return fetch('put', 'nginx/redirection-hosts/' + id, data); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param   {Integer}  id | ||||||
|  |              * @returns {Promise} | ||||||
|  |              */ | ||||||
|  |             delete: function (id) { | ||||||
|  |                 return fetch('delete', 'nginx/redirection-hosts/' + id); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param  {Integer}  id | ||||||
|  |              * @param  {FormData} form_data | ||||||
|  |              * @params {Promise} | ||||||
|  |              */ | ||||||
|  |             setCerts: function (id, form_data) { | ||||||
|  |                 return upload('nginx/redirection-hosts/' + id + '/certificates', form_data); | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
| @@ -305,6 +389,32 @@ module.exports = { | |||||||
|              */ |              */ | ||||||
|             getAll: function (expand, query) { |             getAll: function (expand, query) { | ||||||
|                 return getAllObjects('nginx/streams', expand, query); |                 return getAllObjects('nginx/streams', expand, query); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param {Object}  data | ||||||
|  |              */ | ||||||
|  |             create: function (data) { | ||||||
|  |                 return fetch('post', 'nginx/streams', data); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param   {Object}   data | ||||||
|  |              * @param   {Integer}  data.id | ||||||
|  |              * @returns {Promise} | ||||||
|  |              */ | ||||||
|  |             update: function (data) { | ||||||
|  |                 let id = data.id; | ||||||
|  |                 delete data.id; | ||||||
|  |                 return fetch('put', 'nginx/streams/' + id, data); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param   {Integer}  id | ||||||
|  |              * @returns {Promise} | ||||||
|  |              */ | ||||||
|  |             delete: function (id) { | ||||||
|  |                 return fetch('delete', 'nginx/streams/' + id); | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
| @@ -316,6 +426,41 @@ module.exports = { | |||||||
|              */ |              */ | ||||||
|             getAll: function (expand, query) { |             getAll: function (expand, query) { | ||||||
|                 return getAllObjects('nginx/dead-hosts', expand, query); |                 return getAllObjects('nginx/dead-hosts', expand, query); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param {Object}  data | ||||||
|  |              */ | ||||||
|  |             create: function (data) { | ||||||
|  |                 return fetch('post', 'nginx/dead-hosts', data); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param   {Object}   data | ||||||
|  |              * @param   {Integer}  data.id | ||||||
|  |              * @returns {Promise} | ||||||
|  |              */ | ||||||
|  |             update: function (data) { | ||||||
|  |                 let id = data.id; | ||||||
|  |                 delete data.id; | ||||||
|  |                 return fetch('put', 'nginx/dead-hosts/' + id, data); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param   {Integer}  id | ||||||
|  |              * @returns {Promise} | ||||||
|  |              */ | ||||||
|  |             delete: function (id) { | ||||||
|  |                 return fetch('delete', 'nginx/dead-hosts/' + id); | ||||||
|  |             }, | ||||||
|  |  | ||||||
|  |             /** | ||||||
|  |              * @param  {Integer}  id | ||||||
|  |              * @param  {FormData} form_data | ||||||
|  |              * @params {Promise} | ||||||
|  |              */ | ||||||
|  |             setCerts: function (id, form_data) { | ||||||
|  |                 return upload('nginx/dead-hosts/' + id + '/certificates', form_data); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| @@ -328,6 +473,32 @@ module.exports = { | |||||||
|          */ |          */ | ||||||
|         getAll: function (expand, query) { |         getAll: function (expand, query) { | ||||||
|             return getAllObjects('access-lists', expand, query); |             return getAllObjects('access-lists', expand, query); | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @param {Object}  data | ||||||
|  |          */ | ||||||
|  |         create: function (data) { | ||||||
|  |             return fetch('post', 'access-lists', data); | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @param   {Object}   data | ||||||
|  |          * @param   {Integer}  data.id | ||||||
|  |          * @returns {Promise} | ||||||
|  |          */ | ||||||
|  |         update: function (data) { | ||||||
|  |             let id = data.id; | ||||||
|  |             delete data.id; | ||||||
|  |             return fetch('put', 'access-lists/' + id, data); | ||||||
|  |         }, | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * @param   {Integer}  id | ||||||
|  |          * @returns {Promise} | ||||||
|  |          */ | ||||||
|  |         delete: function (id) { | ||||||
|  |             return fetch('delete', 'access-lists/' + id); | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ | |||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <div class="form-label"><%- i18n('all-hosts', 'other-certificate') %></div> |                                 <div class="form-label"><%- i18n('all-hosts', 'other-certificate') %></div> | ||||||
|                                 <div class="custom-file"> |                                 <div class="custom-file"> | ||||||
|                                     <input type="file" class="custom-file-input" name="meta[other_ssl_certificate]"> |                                     <input type="file" class="custom-file-input" name="meta[other_ssl_certificate]" id="other_ssl_certificate"> | ||||||
|                                     <label class="custom-file-label"><%- i18n('str', 'choose-file') %></label> |                                     <label class="custom-file-label"><%- i18n('str', 'choose-file') %></label> | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
| @@ -103,7 +103,7 @@ | |||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <div class="form-label"><%- i18n('all-hosts', 'other-certificate-key') %></div> |                                 <div class="form-label"><%- i18n('all-hosts', 'other-certificate-key') %></div> | ||||||
|                                 <div class="custom-file"> |                                 <div class="custom-file"> | ||||||
|                                     <input type="file" class="custom-file-input" name="meta[other_ssl_certificate_key]"> |                                     <input type="file" class="custom-file-input" name="meta[other_ssl_certificate_key]" id="other_ssl_certificate_key"> | ||||||
|                                     <label class="custom-file-label"><%- i18n('str', 'choose-file') %></label> |                                     <label class="custom-file-label"><%- i18n('str', 'choose-file') %></label> | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|   | |||||||
| @@ -13,17 +13,20 @@ require('selectize'); | |||||||
| module.exports = Mn.View.extend({ | module.exports = Mn.View.extend({ | ||||||
|     template:  template, |     template:  template, | ||||||
|     className: 'modal-dialog', |     className: 'modal-dialog', | ||||||
|  |     max_file_size: 5120, | ||||||
|  |  | ||||||
|     ui: { |     ui: { | ||||||
|         form:         'form', |         form:                      'form', | ||||||
|         domain_names: 'input[name="domain_names"]', |         domain_names:              'input[name="domain_names"]', | ||||||
|         forward_ip:   'input[name="forward_ip"]', |         forward_ip:                'input[name="forward_ip"]', | ||||||
|         buttons:      '.modal-footer button', |         buttons:                   '.modal-footer button', | ||||||
|         cancel:       'button.cancel', |         cancel:                    'button.cancel', | ||||||
|         save:         'button.save', |         save:                      'button.save', | ||||||
|         ssl_enabled:  'input[name="ssl_enabled"]', |         ssl_enabled:               'input[name="ssl_enabled"]', | ||||||
|         ssl_options:  '#ssl-options input', |         ssl_options:               '#ssl-options input', | ||||||
|         ssl_provider: 'input[name="ssl_provider"]', |         ssl_provider:              'input[name="ssl_provider"]', | ||||||
|  |         other_ssl_certificate:     '#other_ssl_certificate', | ||||||
|  |         other_ssl_certificate_key: '#other_ssl_certificate_key', | ||||||
|  |  | ||||||
|         // SSL hiding and showing |         // SSL hiding and showing | ||||||
|         all_ssl:         '.letsencrypt-ssl, .other-ssl', |         all_ssl:         '.letsencrypt-ssl, .other-ssl', | ||||||
| @@ -75,21 +78,71 @@ module.exports = Mn.View.extend({ | |||||||
|                 data.domain_names = data.domain_names.split(','); |                 data.domain_names = data.domain_names.split(','); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // Process |             let require_ssl_files = typeof data.ssl_enabled !== 'undefined' && data.ssl_enabled && typeof data.ssl_provider !== 'undefined' && data.ssl_provider === 'other'; | ||||||
|             this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); |             let ssl_files         = []; | ||||||
|             let method = App.Api.Nginx.ProxyHosts.create; |             let method            = App.Api.Nginx.ProxyHosts.create; | ||||||
|  |             let is_new            = true; | ||||||
|  |  | ||||||
|  |             let must_require_ssl_files = require_ssl_files && !view.model.hasSslFiles('other'); | ||||||
|  |  | ||||||
|             if (this.model.get('id')) { |             if (this.model.get('id')) { | ||||||
|                 // edit |                 // edit | ||||||
|  |                 is_new  = false; | ||||||
|                 method  = App.Api.Nginx.ProxyHosts.update; |                 method  = App.Api.Nginx.ProxyHosts.update; | ||||||
|                 data.id = this.model.get('id'); |                 data.id = this.model.get('id'); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             // check files are attached | ||||||
|  |             if (require_ssl_files) { | ||||||
|  |                 if (!this.ui.other_ssl_certificate[0].files.length || !this.ui.other_ssl_certificate[0].files[0].size) { | ||||||
|  |                     if (must_require_ssl_files) { | ||||||
|  |                         alert('certificate file is not attached'); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     if (this.ui.other_ssl_certificate[0].files[0].size > this.max_file_size) { | ||||||
|  |                         alert('certificate file is too large (> 5kb)'); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     ssl_files.push({name: 'other_certificate', file: this.ui.other_ssl_certificate[0].files[0]}); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (!this.ui.other_ssl_certificate_key[0].files.length || !this.ui.other_ssl_certificate_key[0].files[0].size) { | ||||||
|  |                     if (must_require_ssl_files) { | ||||||
|  |                         alert('certificate key file is not attached'); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     if (this.ui.other_ssl_certificate_key[0].files[0].size > this.max_file_size) { | ||||||
|  |                         alert('certificate key file is too large (> 5kb)'); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     ssl_files.push({name: 'other_certificate_key', file: this.ui.other_ssl_certificate_key[0].files[0]}); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             this.ui.buttons.prop('disabled', true).addClass('btn-disabled'); | ||||||
|             method(data) |             method(data) | ||||||
|                 .then(result => { |                 .then(result => { | ||||||
|                     view.model.set(result); |                     view.model.set(result); | ||||||
|  |  | ||||||
|  |                     // Now upload the certs if we need to | ||||||
|  |                     if (ssl_files.length) { | ||||||
|  |                         let form_data = new FormData(); | ||||||
|  |  | ||||||
|  |                         ssl_files.map(function (file) { | ||||||
|  |                             form_data.append(file.name, file.file); | ||||||
|  |                         }); | ||||||
|  |  | ||||||
|  |                         return App.Api.Nginx.ProxyHosts.setCerts(view.model.get('id'), form_data) | ||||||
|  |                             .then(result => { | ||||||
|  |                                 view.model.set('meta', _.assign({}, view.model.get('meta'), result)); | ||||||
|  |                             }); | ||||||
|  |                     } | ||||||
|  |                 }) | ||||||
|  |                 .then(() => { | ||||||
|                     App.UI.closeModal(function () { |                     App.UI.closeModal(function () { | ||||||
|                         if (method === App.Api.Nginx.ProxyHosts.create) { |                         if (is_new) { | ||||||
|                             App.Controller.showNginxProxy(); |                             App.Controller.showNginxProxy(); | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
|   | |||||||
| @@ -19,11 +19,20 @@ const model = Backbone.Model.extend({ | |||||||
|             ssl_forced:      false, |             ssl_forced:      false, | ||||||
|             caching_enabled: false, |             caching_enabled: false, | ||||||
|             block_exploits:  false, |             block_exploits:  false, | ||||||
|             meta:            [], |             meta:            {}, | ||||||
|             // The following are expansions: |             // The following are expansions: | ||||||
|             owner:           null, |             owner:           null, | ||||||
|             access_list:     null |             access_list:     null | ||||||
|         }; |         }; | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @param   {String}  type     'letsencrypt' or 'other' | ||||||
|  |      * @returns {Boolean} | ||||||
|  |      */ | ||||||
|  |     hasSslFiles: function (type) { | ||||||
|  |         let meta = this.get('meta'); | ||||||
|  |         return typeof meta[type + '_certificate'] !== 'undefined' && meta[type + '_certificate'] && typeof meta[type + '_certificate_key'] !== 'undefined' && meta[type + '_certificate_key']; | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user