Sfoglia il codice sorgente

Post certificate move fixes

Jamie Curnow 7 anni fa
parent
commit
6920a61871

+ 20 - 0
src/backend/internal/certificate.js

@@ -27,6 +27,10 @@ const internalCertificate = {
             .then(() => {
                 data.owner_user_id = access.token.get('attrs').id;
 
+                if (data.provider === 'letsencrypt') {
+                    data.nice_name = data.domain_names.sort().join(', ');
+                }
+
                 return certificateModel
                     .query()
                     .omit(omissions())
@@ -246,6 +250,22 @@ const internalCertificate = {
             });
     },
 
+    /**
+     * @param   {Access}   access
+     * @param   {Object}   data
+     * @param   {Array}    data.domain_names
+     * @param   {String}   data.meta.letsencrypt_email
+     * @param   {Boolean}  data.meta.letsencrypt_agree
+     * @returns {Promise}
+     */
+    createQuickCertificate: (access, data) => {
+        return internalCertificate.create(access, {
+            provider:     'letsencrypt',
+            domain_names: data.domain_names,
+            meta:         data.meta
+        });
+    },
+
     /**
      * Validates that the certs provided are good.
      * No access required here, nothing is changed or stored.

+ 77 - 21
src/backend/internal/proxy-host.js

@@ -1,11 +1,12 @@
 'use strict';
 
-const _                = require('lodash');
-const error            = require('../lib/error');
-const proxyHostModel   = require('../models/proxy_host');
-const internalHost     = require('./host');
-const internalNginx    = require('./nginx');
-const internalAuditLog = require('./audit-log');
+const _                   = require('lodash');
+const error               = require('../lib/error');
+const proxyHostModel      = require('../models/proxy_host');
+const internalHost        = require('./host');
+const internalNginx       = require('./nginx');
+const internalAuditLog    = require('./audit-log');
+const internalCertificate = require('./certificate');
 
 function omissions () {
     return ['is_deleted'];
@@ -19,6 +20,12 @@ const internalProxyHost = {
      * @returns {Promise}
      */
     create: (access, data) => {
+        let create_certificate = data.certificate_id === 'new';
+
+        if (create_certificate) {
+            delete data.certificate_id;
+        }
+
         return access.can('proxy_hosts:create', data)
             .then(access_data => {
                 // Get a list of the domain names and check each of them against existing records
@@ -46,14 +53,39 @@ const internalProxyHost = {
                     .omit(omissions())
                     .insertAndFetch(data);
             })
+            .then(row => {
+                if (create_certificate) {
+                    return internalCertificate.createQuickCertificate(access, data)
+                        .then(cert => {
+                            // update host with cert id
+                            return internalProxyHost.update(access, {
+                                id:             row.id,
+                                certificate_id: cert.id
+                            });
+                        })
+                        .then(() => {
+                            return row;
+                        });
+                } else {
+                    return row;
+                }
+            })
+            .then(row => {
+                // re-fetch with cert
+                return internalProxyHost.get(access, {
+                    id:     row.id,
+                    expand: ['certificate', 'owner']
+                });
+            })
             .then(row => {
                 // Configure nginx
                 return internalNginx.configure(proxyHostModel, 'proxy_host', row)
                     .then(() => {
-                        return internalProxyHost.get(access, {id: row.id, expand: ['owner']});
+                        return row;
                     });
             })
             .then(row => {
+                // Audit log
                 data.meta = _.assign({}, data.meta || {}, row.meta);
 
                 // Add to audit log
@@ -78,6 +110,12 @@ const internalProxyHost = {
      * @return {Promise}
      */
     update: (access, data) => {
+        let create_certificate = data.certificate_id === 'new';
+
+        if (create_certificate) {
+            delete data.certificate_id;
+        }
+
         return access.can('proxy_hosts:update', data.id)
             .then(access_data => {
                 // Get a list of the domain names and check each of them against existing records
@@ -107,13 +145,28 @@ const internalProxyHost = {
                     throw new error.InternalValidationError('Proxy Host could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
                 }
 
+                if (create_certificate) {
+                    return internalCertificate.createQuickCertificate(access, {
+                        domain_names: data.domain_names || row.domain_names,
+                        meta:         _.assign({}, row.meta, data.meta)
+                    })
+                        .then(cert => {
+                            // update host with cert id
+                            data.certificate_id = cert.id;
+                        })
+                        .then(() => {
+                            return row;
+                        });
+                } else {
+                    return row;
+                }
+            })
+            .then(row => {
                 return proxyHostModel
                     .query()
-                    .omit(omissions())
-                    .patchAndFetchById(row.id, data)
+                    .where({id: data.id})
+                    .patch(data)
                     .then(saved_row => {
-                        saved_row.meta = internalHost.cleanMeta(saved_row.meta);
-
                         // Add to audit log
                         return internalAuditLog.add(access, {
                             action:      'updated',
@@ -125,6 +178,19 @@ const internalProxyHost = {
                                 return _.omit(saved_row, omissions());
                             });
                     });
+            })
+            .then(() => {
+                return internalProxyHost.get(access, {
+                    id:     data.id,
+                    expand: ['owner', 'certificate']
+                })
+                    .then(row => {
+                        // Configure nginx
+                        return internalNginx.configure(proxyHostModel, 'proxy_host', row)
+                            .then(() => {
+                                return _.omit(row, omissions());
+                            });
+                    })
             });
     },
 
@@ -167,7 +233,6 @@ const internalProxyHost = {
             })
             .then(row => {
                 if (row) {
-                    row.meta = internalHost.cleanMeta(row.meta);
                     return _.omit(row, omissions());
                 } else {
                     throw new error.ItemNotFoundError(data.id);
@@ -207,8 +272,6 @@ const internalProxyHost = {
                     })
                     .then(() => {
                         // Add to audit log
-                        row.meta = internalHost.cleanMeta(row.meta);
-
                         return internalAuditLog.add(access, {
                             action:      'deleted',
                             object_type: 'proxy-host',
@@ -257,13 +320,6 @@ const internalProxyHost = {
                 }
 
                 return query;
-            })
-            .then(rows => {
-                rows.map(row => {
-                    row.meta = internalHost.cleanMeta(row.meta);
-                });
-
-                return rows;
             });
     },
 

+ 14 - 0
src/backend/schema/definitions.json

@@ -116,6 +116,20 @@
       "type": "integer",
       "minimum": 1
     },
+    "certificate_id": {
+      "description": "Certificate ID",
+      "example": 1234,
+      "anyOf": [
+        {
+          "type": "integer",
+          "minimum": 0
+        },
+        {
+          "type": "string",
+          "pattern": "^new$"
+        }
+      ]
+    },
     "access_list_id": {
       "description": "Access List ID",
       "example": 1234,

+ 9 - 31
src/backend/schema/endpoints/proxy-hosts.json

@@ -27,15 +27,12 @@
       "minimum": 1,
       "maximum": 65535
     },
-    "ssl_enabled": {
-      "$ref": "../definitions.json#/definitions/ssl_enabled"
+    "certificate_id": {
+      "$ref": "../definitions.json#/definitions/certificate_id"
     },
     "ssl_forced": {
       "$ref": "../definitions.json#/definitions/ssl_forced"
     },
-    "ssl_provider": {
-      "$ref": "../definitions.json#/definitions/ssl_provider"
-    },
     "block_exploits": {
       "$ref": "../definitions.json#/definitions/block_exploits"
     },
@@ -46,17 +43,7 @@
       "$ref": "../definitions.json#/definitions/access_list_id"
     },
     "meta": {
-      "type": "object",
-      "additionalProperties": false,
-      "properties": {
-        "letsencrypt_email": {
-          "type": "string",
-          "format": "email"
-        },
-        "letsencrypt_agree": {
-          "type": "boolean"
-        }
-      }
+      "type": "object"
     }
   },
   "properties": {
@@ -78,15 +65,12 @@
     "forward_port": {
       "$ref": "#/definitions/forward_port"
     },
-    "ssl_enabled": {
-      "$ref": "#/definitions/ssl_enabled"
+    "certificate_id": {
+      "$ref": "#/definitions/certificate_id"
     },
     "ssl_forced": {
       "$ref": "#/definitions/ssl_forced"
     },
-    "ssl_provider": {
-      "$ref": "#/definitions/ssl_provider"
-    },
     "block_exploits": {
       "$ref": "#/definitions/block_exploits"
     },
@@ -146,15 +130,12 @@
           "forward_port": {
             "$ref": "#/definitions/forward_port"
           },
-          "ssl_enabled": {
-            "$ref": "#/definitions/ssl_enabled"
+          "certificate_id": {
+            "$ref": "#/definitions/certificate_id"
           },
           "ssl_forced": {
             "$ref": "#/definitions/ssl_forced"
           },
-          "ssl_provider": {
-            "$ref": "#/definitions/ssl_provider"
-          },
           "block_exploits": {
             "$ref": "#/definitions/block_exploits"
           },
@@ -198,15 +179,12 @@
           "forward_port": {
             "$ref": "#/definitions/forward_port"
           },
-          "ssl_enabled": {
-            "$ref": "#/definitions/ssl_enabled"
+          "certificate_id": {
+            "$ref": "#/definitions/certificate_id"
           },
           "ssl_forced": {
             "$ref": "#/definitions/ssl_forced"
           },
-          "ssl_provider": {
-            "$ref": "#/definitions/ssl_provider"
-          },
           "block_exploits": {
             "$ref": "#/definitions/block_exploits"
           },

+ 1 - 1
src/frontend/js/app/nginx/proxy/delete.ejs

@@ -8,7 +8,7 @@
             <div class="row">
                 <div class="col-sm-12 col-md-12">
                     <%= i18n('proxy-hosts', 'delete-confirm', {domains: domain_names.join(', ')}) %>
-                    <% if (ssl_enabled) { %>
+                    <% if (certificate_id) { %>
                         <br><br>
                         <%- i18n('ssl', 'delete-ssl') %>
                     <% } %>

+ 2 - 2
src/frontend/js/app/nginx/proxy/form.ejs

@@ -87,13 +87,13 @@
                         <div class="col-sm-12 col-md-12 letsencrypt">
                             <div class="form-group">
                                 <label class="form-label"><%- i18n('ssl', 'letsencrypt-email') %> <span class="form-required">*</span></label>
-                                <input name="meta[letsencrypt_email]" type="email" class="form-control" placeholder="" value="<%- getLetsencryptEmail() %>" required>
+                                <input name="meta[letsencrypt_email]" type="email" class="form-control" placeholder="" value="<%- getLetsencryptEmail() %>" required disabled>
                             </div>
                         </div>
                         <div class="col-sm-12 col-md-12 letsencrypt">
                             <div class="form-group">
                                 <label class="custom-switch">
-                                    <input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required>
+                                    <input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required disabled>
                                     <span class="custom-switch-indicator"></span>
                                     <span class="custom-switch-description"><%= i18n('ssl', 'letsencrypt-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
                                 </label>

+ 6 - 2
src/frontend/js/app/nginx/proxy/form.js

@@ -24,7 +24,7 @@ module.exports = Mn.View.extend({
         cancel:             'button.cancel',
         save:               'button.save',
         certificate_select: 'select[name="certificate_id"]',
-        ssl_options:        '#ssl-options input',
+        ssl_forced:         'input[name="ssl_forced"]',
         letsencrypt:        '.letsencrypt'
     },
 
@@ -38,7 +38,7 @@ module.exports = Mn.View.extend({
             }
 
             let enabled = id === 'new' || parseInt(id, 10) > 0;
-            this.ui.ssl_options.prop('disabled', !enabled).parents('.form-group').css('opacity', enabled ? 1 : 0.5);
+            this.ui.ssl_forced.prop('disabled', !enabled).parents('.form-group').css('opacity', enabled ? 1 : 0.5);
         },
 
         'click @ui.save': function (e) {
@@ -57,6 +57,10 @@ module.exports = Mn.View.extend({
             data.block_exploits  = !!data.block_exploits;
             data.caching_enabled = !!data.caching_enabled;
 
+            if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
+                data.ssl_forced = true;
+            }
+
             if (typeof data.domain_names === 'string' && data.domain_names) {
                 data.domain_names = data.domain_names.split(',');
             }

+ 1 - 1
src/frontend/js/app/nginx/proxy/list/item.ejs

@@ -20,7 +20,7 @@
     <div class="text-monospace"><%- forward_ip %>:<%- forward_port %></div>
 </td>
 <td>
-    <div><%- certificate ? i18n('ssl', certificate.provider) : i18n('ssl', 'none') %></div>
+    <div><%- certificate && certificate_id ? i18n('ssl', certificate.provider) : i18n('ssl', 'none') %></div>
 </td>
 <td>
     <div><%- access_list_id ? access_list.name : i18n('str', 'public') %></div>