Skip to content

Commit 06c5f99

Browse files
authored
Merge pull request #1390 from jc21/develop
v2.9.9
2 parents fee87a4 + babc5b7 commit 06c5f99

File tree

15 files changed

+410
-40
lines changed

15 files changed

+410
-40
lines changed

.version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.9.8
1+
2.9.9

README.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<p align="center">
22
<img src="https://nginxproxymanager.com/github.png">
33
<br><br>
4-
<img src="https://img.shields.io/badge/version-2.9.8-green.svg?style=for-the-badge">
4+
<img src="https://img.shields.io/badge/version-2.9.9-green.svg?style=for-the-badge">
55
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
66
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
77
</a>
@@ -483,6 +483,24 @@ Special thanks to the following contributors:
483483
<br /><sub><b>Florian Meinicke</b></sub>
484484
</a>
485485
</td>
486+
<td align="center">
487+
<a href="https://github.com/ssrahul96">
488+
<img src="https://avatars.githubusercontent.com/u/15570570?v=4" width="80" alt=""/>
489+
<br /><sub><b>Rahul Somasundaram</b></sub>
490+
</a>
491+
</td>
492+
<td align="center">
493+
<a href="https://github.com/BjoernAkAManf">
494+
<img src="https://avatars.githubusercontent.com/u/833043?v=4" width="80" alt=""/>
495+
<br /><sub><b>Björn Heinrichs</b></sub>
496+
</a>
497+
</td>
498+
<td align="center">
499+
<a href="https://github.com/realJoshByrnes">
500+
<img src="https://avatars.githubusercontent.com/u/204185?v=4" width="80" alt=""/>
501+
<br /><sub><b>Josh Byrnes</b></sub>
502+
</a>
503+
</td>
486504
</tr>
487505
</table>
488506
<!-- markdownlint-enable -->

backend/app.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ app.use(function (err, req, res, next) {
7575

7676
// Not every error is worth logging - but this is good for now until it gets annoying.
7777
if (typeof err.stack !== 'undefined' && err.stack) {
78-
if (process.env.NODE_ENV === 'development') {
78+
if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
7979
log.debug(err.stack);
8080
} else if (typeof err.public == 'undefined' || !err.public) {
8181
log.warn(err.message);

backend/internal/certificate.js

+67
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const internalHost = require('./host');
1313
const letsencryptStaging = process.env.NODE_ENV !== 'production';
1414
const letsencryptConfig = '/etc/letsencrypt.ini';
1515
const certbotCommand = 'certbot';
16+
const archiver = require('archiver');
17+
const path = require('path');
1618

1719
function omissions() {
1820
return ['is_deleted'];
@@ -335,6 +337,71 @@ const internalCertificate = {
335337
});
336338
},
337339

340+
/**
341+
* @param {Access} access
342+
* @param {Object} data
343+
* @param {Number} data.id
344+
* @returns {Promise}
345+
*/
346+
download: (access, data) => {
347+
return new Promise((resolve, reject) => {
348+
access.can('certificates:get', data)
349+
.then(() => {
350+
return internalCertificate.get(access, data);
351+
})
352+
.then((certificate) => {
353+
if (certificate.provider === 'letsencrypt') {
354+
const zipDirectory = '/etc/letsencrypt/live/npm-' + data.id;
355+
356+
if (!fs.existsSync(zipDirectory)) {
357+
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
358+
}
359+
360+
let certFiles = fs.readdirSync(zipDirectory)
361+
.filter((fn) => fn.endsWith('.pem'))
362+
.map((fn) => fs.realpathSync(path.join(zipDirectory, fn)));
363+
const downloadName = 'npm-' + data.id + '-' + `${Date.now()}.zip`;
364+
const opName = '/tmp/' + downloadName;
365+
internalCertificate.zipFiles(certFiles, opName)
366+
.then(() => {
367+
logger.debug('zip completed : ', opName);
368+
const resp = {
369+
fileName: opName
370+
};
371+
resolve(resp);
372+
}).catch((err) => reject(err));
373+
} else {
374+
throw new error.ValidationError('Only Let\'sEncrypt certificates can be downloaded');
375+
}
376+
}).catch((err) => reject(err));
377+
});
378+
},
379+
380+
/**
381+
* @param {String} source
382+
* @param {String} out
383+
* @returns {Promise}
384+
*/
385+
zipFiles(source, out) {
386+
const archive = archiver('zip', { zlib: { level: 9 } });
387+
const stream = fs.createWriteStream(out);
388+
389+
return new Promise((resolve, reject) => {
390+
source
391+
.map((fl) => {
392+
let fileName = path.basename(fl);
393+
logger.debug(fl, 'added to certificate zip');
394+
archive.file(fl, { name: fileName });
395+
});
396+
archive
397+
.on('error', (err) => reject(err))
398+
.pipe(stream);
399+
400+
stream.on('close', () => resolve());
401+
archive.finalize();
402+
});
403+
},
404+
338405
/**
339406
* @param {Access} access
340407
* @param {Object} data

backend/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"main": "js/index.js",
66
"dependencies": {
77
"ajv": "^6.12.0",
8+
"archiver": "^5.3.0",
89
"batchflow": "^0.4.0",
910
"bcrypt": "^5.0.0",
1011
"body-parser": "^1.19.0",

backend/routes/api/nginx/certificates.js

+29
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,35 @@ router
209209
.catch(next);
210210
});
211211

212+
213+
/**
214+
* Download LE Certs
215+
*
216+
* /api/nginx/certificates/123/download
217+
*/
218+
router
219+
.route('/:certificate_id/download')
220+
.options((req, res) => {
221+
res.sendStatus(204);
222+
})
223+
.all(jwtdecode())
224+
225+
/**
226+
* GET /api/nginx/certificates/123/download
227+
*
228+
* Renew certificate
229+
*/
230+
.get((req, res, next) => {
231+
internalCertificate.download(res.locals.access, {
232+
id: parseInt(req.params.certificate_id, 10)
233+
})
234+
.then((result) => {
235+
res.status(200)
236+
.download(result.fileName);
237+
})
238+
.catch(next);
239+
});
240+
212241
/**
213242
* Validate Certs before saving
214243
*

backend/schema/endpoints/streams.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"maximum": 65535
2222
},
2323
"forwarding_host": {
24-
"oneOf": [
24+
"anyOf": [
2525
{
2626
"$ref": "../definitions.json#/definitions/domain_name"
2727
},

backend/templates/_listen.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{% if certificate -%}
88
listen 443 ssl{% if http2_support %} http2{% endif %};
99
{% if ipv6 -%}
10-
listen [::]:443;
10+
listen [::]:443 ssl{% if http2_support %} http2{% endif %};
1111
{% else -%}
1212
#listen [::]:443;
1313
{% endif %}

0 commit comments

Comments
 (0)