Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0d5d2b1

Browse filesBrowse files
authored
Merge pull request NginxProxyManager#4283 from badkeyy/feature/show-active-host-in-cert-list
SSL Certificates: Show if cert is in use on host
2 parents 3a01b2c + aedaaa1 commit 0d5d2b1
Copy full SHA for 0d5d2b1

File tree

Expand file treeCollapse file tree

8 files changed

+83
-14
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+83
-14
lines changed

‎backend/internal/certificate.js

Copy file name to clipboardExpand all lines: backend/internal/certificate.js
+6Lines 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

Copy file name to clipboardExpand all lines: backend/models/certificate.js
+38-1Lines 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

Copy file name to clipboardExpand all lines: frontend/js/app/dashboard/main.js
+1-3Lines 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

Copy file name to clipboardExpand all lines: frontend/js/app/nginx/certificates/list/item.ejs
+15-1Lines 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

Copy file name to clipboardExpand all lines: frontend/js/app/nginx/certificates/list/item.js
+16-6Lines 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

Copy file name to clipboardExpand all lines: frontend/js/app/nginx/certificates/list/main.ejs
+1Lines 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

Copy file name to clipboardExpand all lines: frontend/js/app/nginx/certificates/main.js
+2-2Lines 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/i18n/messages.json

Copy file name to clipboardExpand all lines: frontend/js/i18n/messages.json
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@
208208
"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.",
209209
"download": "Download",
210210
"renew-title": "Renew Let's Encrypt Certificate",
211-
"search": "Search Certificate…"
211+
"search": "Search Certificate…",
212+
"in-use" : "In use",
213+
"inactive": "Inactive",
214+
"active-domain_names": "Active domain names"
212215
},
213216
"access-lists": {
214217
"title": "Access Lists",

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.