Skip to content

Commit 080bd0b

Browse files
committed
Added status of certificates to the certificate list and show on which domain names the certificates are in use
1 parent 8351dd4 commit 080bd0b

File tree

10 files changed

+96
-27
lines changed

10 files changed

+96
-27
lines changed

backend/internal/certificate.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ const internalCertificate = {
313313
.where('is_deleted', 0)
314314
.andWhere('id', data.id)
315315
.allowGraph('[owner]')
316+
.allowGraph('[proxy_hosts]')
317+
.allowGraph('[redirection_hosts]')
318+
.allowGraph('[dead_hosts]')
316319
.first();
317320

318321
if (access_data.permission_visibility !== 'all') {
@@ -464,6 +467,9 @@ const internalCertificate = {
464467
.where('is_deleted', 0)
465468
.groupBy('id')
466469
.allowGraph('[owner]')
470+
.allowGraph('[proxy_hosts]')
471+
.allowGraph('[redirection_hosts]')
472+
.allowGraph('[dead_hosts]')
467473
.orderBy('nice_name', 'ASC');
468474

469475
if (access_data.permission_visibility !== 'all') {

backend/models/certificate.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
const db = require('../db');
55
const helpers = require('../lib/helpers');
66
const Model = require('objection').Model;
7-
const User = require('./user');
87
const now = require('./now_helper');
98

109
Model.knex(db);
@@ -68,6 +67,11 @@ class Certificate extends Model {
6867
}
6968

7069
static get relationMappings () {
70+
const ProxyHost = require('./proxy_host');
71+
const DeadHost = require('./dead_host');
72+
const User = require('./user');
73+
const RedirectionHost = require('./redirection_host');
74+
7175
return {
7276
owner: {
7377
relation: Model.HasOneRelation,
@@ -79,6 +83,39 @@ class Certificate extends Model {
7983
modify: function (qb) {
8084
qb.where('user.is_deleted', 0);
8185
}
86+
},
87+
proxy_hosts: {
88+
relation: Model.HasManyRelation,
89+
modelClass: ProxyHost,
90+
join: {
91+
from: 'certificate.id',
92+
to: 'proxy_host.certificate_id'
93+
},
94+
modify: function (qb) {
95+
qb.where('proxy_host.is_deleted', 0);
96+
}
97+
},
98+
dead_hosts: {
99+
relation: Model.HasManyRelation,
100+
modelClass: DeadHost,
101+
join: {
102+
from: 'certificate.id',
103+
to: 'dead_host.certificate_id'
104+
},
105+
modify: function (qb) {
106+
qb.where('dead_host.is_deleted', 0);
107+
}
108+
},
109+
redirection_hosts: {
110+
relation: Model.HasManyRelation,
111+
modelClass: RedirectionHost,
112+
join: {
113+
from: 'certificate.id',
114+
to: 'redirection_host.certificate_id'
115+
},
116+
modify: function (qb) {
117+
qb.where('redirection_host.is_deleted', 0);
118+
}
82119
}
83120
};
84121
}

frontend/js/app/dashboard/main.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ module.exports = Mn.View.extend({
5050
onRender: function () {
5151
let view = this;
5252

53-
if (typeof view.stats.hosts === 'undefined') {
54-
Api.Reports.getHostStats()
53+
Api.Reports.getHostStats()
5554
.then(response => {
5655
if (!view.isDestroyed()) {
5756
view.stats.hosts = response;
@@ -61,7 +60,6 @@ module.exports = Mn.View.extend({
6160
.catch(err => {
6261
console.log(err);
6362
});
64-
}
6563
},
6664

6765
/**

frontend/js/app/nginx/certificates/list/item.ejs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333
<td class="<%- isExpired() ? 'text-danger' : '' %>">
3434
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
3535
</td>
36+
<td>
37+
<% if (active_domain_names().length > 0) { %>
38+
<span class="status-icon bg-success"></span> <%- i18n('certificates', 'in-use') %>
39+
<% } else { %>
40+
<span class="status-icon bg-danger"></span> <%- i18n('certificates', 'inactive') %>
41+
<% } %>
42+
</td>
3643
<% if (canManage) { %>
3744
<td class="text-right">
3845
<div class="item-action dropdown">
@@ -48,7 +55,14 @@
4855
<div class="dropdown-divider"></div>
4956
<% } %>
5057
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
58+
<% if (active_domain_names().length > 0) { %>
59+
<div class="dropdown-divider"></div>
60+
<span class="dropdown-header"><%- i18n('certificates', 'active-domain_names') %></span>
61+
<% active_domain_names().forEach(function(host) { %>
62+
<a href="https://<%- host %>" class="dropdown-item" target="_blank"><%- host %></a>
63+
<% }); %>
64+
<% } %>
5165
</div>
5266
</div>
5367
</td>
54-
<% } %>
68+
<% } %>

frontend/js/app/nginx/certificates/list/item.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,24 @@ module.exports = Mn.View.extend({
4444
},
4545
},
4646

47-
templateContext: {
48-
canManage: App.Cache.User.canManage('certificates'),
49-
isExpired: function () {
50-
return moment(this.expires_on).isBefore(moment());
51-
},
52-
dns_providers: dns_providers
47+
templateContext: function () {
48+
return {
49+
canManage: App.Cache.User.canManage('certificates'),
50+
isExpired: function () {
51+
return moment(this.expires_on).isBefore(moment());
52+
},
53+
dns_providers: dns_providers,
54+
active_domain_names: function () {
55+
const { proxy_hosts = [], redirect_hosts = [], dead_hosts = [] } = this;
56+
return [...proxy_hosts, ...redirect_hosts, ...dead_hosts].reduce((acc, host) => {
57+
acc.push(...(host.domain_names || []));
58+
return acc;
59+
}, []);
60+
}
61+
};
5362
},
5463

64+
5565
initialize: function () {
5666
this.listenTo(this.model, 'change', this.render);
5767
}

frontend/js/app/nginx/certificates/list/main.ejs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<th><%- i18n('str', 'name') %></th>
44
<th><%- i18n('all-hosts', 'cert-provider') %></th>
55
<th><%- i18n('str', 'expires') %></th>
6+
<th><%- i18n('str', 'status') %></th>
67
<% if (canManage) { %>
78
<th>&nbsp;</th>
89
<% } %>

frontend/js/app/nginx/certificates/main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ module.exports = Mn.View.extend({
7474
e.preventDefault();
7575
let query = this.ui.query.val();
7676

77-
this.fetch(['owner'], query)
77+
this.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts'], query)
7878
.then(response => this.showData(response))
7979
.catch(err => {
8080
this.showError(err);
@@ -89,7 +89,7 @@ module.exports = Mn.View.extend({
8989
onRender: function () {
9090
let view = this;
9191

92-
view.fetch(['owner'])
92+
view.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts'])
9393
.then(response => {
9494
if (!view.isDestroyed()) {
9595
if (response && response.length) {

frontend/js/app/user/form.ejs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<div class="modal-content">
2-
<div class="modal-header">
3-
<h5 class="modal-title"><%- i18n('users', 'form-title', {id: id}) %></h5>
4-
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
5-
</div>
6-
<div class="modal-body">
7-
<form>
2+
<form>
3+
<div class="modal-header">
4+
<h5 class="modal-title"><%- i18n('users', 'form-title', {id: id}) %></h5>
5+
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
6+
</div>
7+
<div class="modal-body">
88
<div class="row">
99
<div class="col-sm-6 col-md-6">
1010
<div class="form-group">
@@ -49,10 +49,10 @@
4949
</div>
5050
<% } %>
5151
</div>
52-
</form>
53-
</div>
54-
<div class="modal-footer">
55-
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
56-
<button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
57-
</div>
52+
</div>
53+
<div class="modal-footer">
54+
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
55+
<button type="submit" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
56+
</div>
57+
</form>
5858
</div>

frontend/js/app/user/form.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = Mn.View.extend({
1919

2020
events: {
2121

22-
'click @ui.save': function (e) {
22+
'submit @ui.form': function (e) {
2323
e.preventDefault();
2424
this.ui.error.hide();
2525
let view = this;

frontend/js/i18n/messages.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,10 @@
206206
"reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.",
207207
"download": "Download",
208208
"renew-title": "Renew Let's Encrypt Certificate",
209-
"search": "Search Certificate…"
209+
"search": "Search Certificate…",
210+
"in-use" : "In use",
211+
"inactive": "Inactive",
212+
"active-domain_names": "Active domain names"
210213
},
211214
"access-lists": {
212215
"title": "Access Lists",

0 commit comments

Comments
 (0)