Post certificate move fixes

This commit is contained in:
Jamie Curnow 2018-08-13 22:51:36 +10:00
parent 0bb65e4c3c
commit 6920a61871
8 changed files with 130 additions and 58 deletions

View File

@ -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.

View File

@ -6,6 +6,7 @@ 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
@ -47,13 +54,38 @@ const internalProxyHost = {
.insertAndFetch(data);
})
.then(row => {
// Configure nginx
return internalNginx.configure(proxyHostModel, 'proxy_host', 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 internalProxyHost.get(access, {id: row.id, expand: ['owner']});
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 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;
});
},

View File

@ -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,

View File

@ -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"
},

View File

@ -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') %>
<% } %>

View File

@ -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>

View File

@ -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(',');
}

View File

@ -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>