mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-06-14 16:34:27 +00:00
Compare commits
5 Commits
677371c777
...
a812e0280c
Author | SHA1 | Date | |
---|---|---|---|
|
a812e0280c | ||
|
0d5d2b1b7c | ||
|
e6f61e297f | ||
|
aedaaa18e0 | ||
|
080bd0b749 |
@ -313,6 +313,9 @@ const internalCertificate = {
|
||||
.where('is_deleted', 0)
|
||||
.andWhere('id', data.id)
|
||||
.allowGraph('[owner]')
|
||||
.allowGraph('[proxy_hosts]')
|
||||
.allowGraph('[redirection_hosts]')
|
||||
.allowGraph('[dead_hosts]')
|
||||
.first();
|
||||
|
||||
if (access_data.permission_visibility !== 'all') {
|
||||
@ -464,6 +467,9 @@ const internalCertificate = {
|
||||
.where('is_deleted', 0)
|
||||
.groupBy('id')
|
||||
.allowGraph('[owner]')
|
||||
.allowGraph('[proxy_hosts]')
|
||||
.allowGraph('[redirection_hosts]')
|
||||
.allowGraph('[dead_hosts]')
|
||||
.orderBy('nice_name', 'ASC');
|
||||
|
||||
if (access_data.permission_visibility !== 'all') {
|
||||
|
@ -4,7 +4,6 @@
|
||||
const db = require('../db');
|
||||
const helpers = require('../lib/helpers');
|
||||
const Model = require('objection').Model;
|
||||
const User = require('./user');
|
||||
const now = require('./now_helper');
|
||||
|
||||
Model.knex(db);
|
||||
@ -68,6 +67,11 @@ class Certificate extends Model {
|
||||
}
|
||||
|
||||
static get relationMappings () {
|
||||
const ProxyHost = require('./proxy_host');
|
||||
const DeadHost = require('./dead_host');
|
||||
const User = require('./user');
|
||||
const RedirectionHost = require('./redirection_host');
|
||||
|
||||
return {
|
||||
owner: {
|
||||
relation: Model.HasOneRelation,
|
||||
@ -79,6 +83,39 @@ class Certificate extends Model {
|
||||
modify: function (qb) {
|
||||
qb.where('user.is_deleted', 0);
|
||||
}
|
||||
},
|
||||
proxy_hosts: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: ProxyHost,
|
||||
join: {
|
||||
from: 'certificate.id',
|
||||
to: 'proxy_host.certificate_id'
|
||||
},
|
||||
modify: function (qb) {
|
||||
qb.where('proxy_host.is_deleted', 0);
|
||||
}
|
||||
},
|
||||
dead_hosts: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: DeadHost,
|
||||
join: {
|
||||
from: 'certificate.id',
|
||||
to: 'dead_host.certificate_id'
|
||||
},
|
||||
modify: function (qb) {
|
||||
qb.where('dead_host.is_deleted', 0);
|
||||
}
|
||||
},
|
||||
redirection_hosts: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: RedirectionHost,
|
||||
join: {
|
||||
from: 'certificate.id',
|
||||
to: 'redirection_host.certificate_id'
|
||||
},
|
||||
modify: function (qb) {
|
||||
qb.where('redirection_host.is_deleted', 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ module.exports = Mn.View.extend({
|
||||
onRender: function () {
|
||||
let view = this;
|
||||
|
||||
if (typeof view.stats.hosts === 'undefined') {
|
||||
Api.Reports.getHostStats()
|
||||
.then(response => {
|
||||
if (!view.isDestroyed()) {
|
||||
@ -61,7 +60,6 @@ module.exports = Mn.View.extend({
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -6,6 +6,10 @@ if (subtitle) { %>
|
||||
<p class="h4 text-muted font-weight-normal mb-7"><%- subtitle %></p>
|
||||
<% }
|
||||
|
||||
if (link) { %>
|
||||
<a class="btn btn-<%- btn_color %>" href="#"><%- link %></a>
|
||||
if (links && links.length) { %>
|
||||
<% links.forEach(function(link, index) { %>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<a class="btn btn-<%- btn_color %>" href="#" data-index="<%- index %>"><%- link %></a>
|
||||
</div>
|
||||
<% }); %>
|
||||
<% } %>
|
||||
|
@ -6,7 +6,9 @@ module.exports = Mn.View.extend({
|
||||
template: template,
|
||||
|
||||
options: {
|
||||
btn_color: 'teal'
|
||||
btn_color: 'teal',
|
||||
links: [], // Added to accept multiple links
|
||||
actions: [] // Added to accept multiple actions
|
||||
},
|
||||
|
||||
ui: {
|
||||
@ -16,7 +18,8 @@ module.exports = Mn.View.extend({
|
||||
events: {
|
||||
'click @ui.action': function (e) {
|
||||
e.preventDefault();
|
||||
this.getOption('action')();
|
||||
const index = $(e.currentTarget).data('index');
|
||||
this.getOption('actions')[index]();
|
||||
}
|
||||
},
|
||||
|
||||
@ -24,8 +27,9 @@ module.exports = Mn.View.extend({
|
||||
return {
|
||||
title: this.getOption('title'),
|
||||
subtitle: this.getOption('subtitle'),
|
||||
link: this.getOption('link'),
|
||||
action: typeof this.getOption('action') === 'function',
|
||||
links: this.getOption('links'), // Changed to array
|
||||
actions: this.getOption('actions'), // Changed to array
|
||||
hasActions: this.getOption('actions').length > 0,
|
||||
btn_color: this.getOption('btn_color')
|
||||
};
|
||||
}
|
||||
|
@ -45,12 +45,14 @@ module.exports = Mn.View.extend({
|
||||
this.showChildView('list_region', new EmptyView({
|
||||
title: App.i18n('access-lists', 'empty'),
|
||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||
link: manage ? App.i18n('access-lists', 'add') : null,
|
||||
links: manage ? [App.i18n('access-lists', 'add')] : [],
|
||||
btn_color: 'teal',
|
||||
permission: 'access_lists',
|
||||
action: function () {
|
||||
actions: [
|
||||
function () {
|
||||
App.Controller.showNginxAccessListForm();
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -33,6 +33,13 @@
|
||||
<td class="<%- isExpired() ? 'text-danger' : '' %>">
|
||||
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
|
||||
</td>
|
||||
<td>
|
||||
<% if (active_domain_names().length > 0) { %>
|
||||
<span class="status-icon bg-success"></span> <%- i18n('certificates', 'in-use') %>
|
||||
<% } else { %>
|
||||
<span class="status-icon bg-danger"></span> <%- i18n('certificates', 'inactive') %>
|
||||
<% } %>
|
||||
</td>
|
||||
<% if (canManage) { %>
|
||||
<td class="text-right">
|
||||
<div class="item-action dropdown">
|
||||
@ -48,6 +55,13 @@
|
||||
<div class="dropdown-divider"></div>
|
||||
<% } %>
|
||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||
<% if (active_domain_names().length > 0) { %>
|
||||
<div class="dropdown-divider"></div>
|
||||
<span class="dropdown-header"><%- i18n('certificates', 'active-domain_names') %></span>
|
||||
<% active_domain_names().forEach(function(host) { %>
|
||||
<a href="https://<%- host %>" class="dropdown-item" target="_blank"><%- host %></a>
|
||||
<% }); %>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -44,14 +44,24 @@ module.exports = Mn.View.extend({
|
||||
},
|
||||
},
|
||||
|
||||
templateContext: {
|
||||
templateContext: function () {
|
||||
return {
|
||||
canManage: App.Cache.User.canManage('certificates'),
|
||||
isExpired: function () {
|
||||
return moment(this.expires_on).isBefore(moment());
|
||||
},
|
||||
dns_providers: dns_providers
|
||||
dns_providers: dns_providers,
|
||||
active_domain_names: function () {
|
||||
const { proxy_hosts = [], redirect_hosts = [], dead_hosts = [] } = this;
|
||||
return [...proxy_hosts, ...redirect_hosts, ...dead_hosts].reduce((acc, host) => {
|
||||
acc.push(...(host.domain_names || []));
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
<th><%- i18n('str', 'name') %></th>
|
||||
<th><%- i18n('all-hosts', 'cert-provider') %></th>
|
||||
<th><%- i18n('str', 'expires') %></th>
|
||||
<th><%- i18n('str', 'status') %></th>
|
||||
<% if (canManage) { %>
|
||||
<th> </th>
|
||||
<% } %>
|
||||
|
@ -45,12 +45,16 @@ module.exports = Mn.View.extend({
|
||||
this.showChildView('list_region', new EmptyView({
|
||||
title: App.i18n('certificates', 'empty'),
|
||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||
link: manage ? App.i18n('certificates', 'add') : null,
|
||||
btn_color: 'pink',
|
||||
permission: 'certificates',
|
||||
action: function () {
|
||||
links: manage ? [App.i18n('certificates', 'add-letsencrypt'), App.i18n('certificates', 'add-custom')] : [],
|
||||
actions: [
|
||||
function () {
|
||||
App.Controller.showNginxCertificateForm();
|
||||
}
|
||||
},
|
||||
function () {
|
||||
App.Controller.showNginxCertificateForm(new CertificateModel.Model({provider: 'custom'}));
|
||||
}],
|
||||
btn_color: 'pink',
|
||||
permission: 'certificates'
|
||||
}));
|
||||
},
|
||||
|
||||
@ -74,7 +78,7 @@ module.exports = Mn.View.extend({
|
||||
e.preventDefault();
|
||||
let query = this.ui.query.val();
|
||||
|
||||
this.fetch(['owner'], query)
|
||||
this.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts'], query)
|
||||
.then(response => this.showData(response))
|
||||
.catch(err => {
|
||||
this.showError(err);
|
||||
@ -89,7 +93,7 @@ module.exports = Mn.View.extend({
|
||||
onRender: function () {
|
||||
let view = this;
|
||||
|
||||
view.fetch(['owner'])
|
||||
view.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts'])
|
||||
.then(response => {
|
||||
if (!view.isDestroyed()) {
|
||||
if (response && response.length) {
|
||||
|
@ -45,12 +45,14 @@ module.exports = Mn.View.extend({
|
||||
this.showChildView('list_region', new EmptyView({
|
||||
title: App.i18n('dead-hosts', 'empty'),
|
||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||
link: manage ? App.i18n('dead-hosts', 'add') : null,
|
||||
links: manage ? [App.i18n('dead-hosts', 'add')] : [],
|
||||
btn_color: 'danger',
|
||||
permission: 'dead_hosts',
|
||||
action: function () {
|
||||
actions: [
|
||||
function () {
|
||||
App.Controller.showNginxDeadForm();
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -41,16 +41,17 @@ module.exports = Mn.View.extend({
|
||||
|
||||
showEmpty: function() {
|
||||
let manage = App.Cache.User.canManage('proxy_hosts');
|
||||
|
||||
this.showChildView('list_region', new EmptyView({
|
||||
title: App.i18n('proxy-hosts', 'empty'),
|
||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||
link: manage ? App.i18n('proxy-hosts', 'add') : null,
|
||||
btn_color: 'success',
|
||||
permission: 'proxy_hosts',
|
||||
action: function () {
|
||||
links: manage ? [App.i18n('proxy-hosts', 'add')] : [],
|
||||
actions: [
|
||||
function () {
|
||||
App.Controller.showNginxProxyForm();
|
||||
}
|
||||
],
|
||||
btn_color: 'success',
|
||||
permission: 'proxy_hosts',
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -44,12 +44,14 @@ module.exports = Mn.View.extend({
|
||||
this.showChildView('list_region', new EmptyView({
|
||||
title: App.i18n('redirection-hosts', 'empty'),
|
||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||
link: manage ? App.i18n('redirection-hosts', 'add') : null,
|
||||
links: manage ? [App.i18n('redirection-hosts', 'add')] : [],
|
||||
btn_color: 'yellow',
|
||||
permission: 'redirection_hosts',
|
||||
action: function () {
|
||||
actions: [
|
||||
function () {
|
||||
App.Controller.showNginxRedirectionForm();
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -45,12 +45,14 @@ module.exports = Mn.View.extend({
|
||||
this.showChildView('list_region', new EmptyView({
|
||||
title: App.i18n('streams', 'empty'),
|
||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||
link: manage ? App.i18n('streams', 'add') : null,
|
||||
links: manage ? [App.i18n('streams', 'add')] : [],
|
||||
btn_color: 'blue',
|
||||
permission: 'streams',
|
||||
action: function () {
|
||||
actions: [
|
||||
function () {
|
||||
App.Controller.showNginxStreamForm();
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -187,6 +187,8 @@
|
||||
"title": "SSL Certificates",
|
||||
"empty": "There are no SSL Certificates",
|
||||
"add": "Add SSL Certificate",
|
||||
"add-letsencrypt": "Add SSL Certificate with Let's Encrypt",
|
||||
"add-custom": "Add Custom SSL Certificate",
|
||||
"form-title": "Add {provider, select, letsencrypt{Let's Encrypt} other{Custom}} Certificate",
|
||||
"delete": "Delete SSL Certificate",
|
||||
"delete-confirm": "Are you sure you want to delete this SSL Certificate? Any hosts using it will need to be updated later.",
|
||||
@ -208,7 +210,10 @@
|
||||
"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.",
|
||||
"download": "Download",
|
||||
"renew-title": "Renew Let's Encrypt Certificate",
|
||||
"search": "Search Certificate…"
|
||||
"search": "Search Certificate…",
|
||||
"in-use" : "In use",
|
||||
"inactive": "Inactive",
|
||||
"active-domain_names": "Active domain names"
|
||||
},
|
||||
"access-lists": {
|
||||
"title": "Access Lists",
|
||||
|
Loading…
x
Reference in New Issue
Block a user