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 4283677

Browse filesBrowse files
authored
Merge branch 'develop' into feature/add-zone-edit-certbot-plugin
2 parents c05f969 + 2a07544 commit 4283677
Copy full SHA for 4283677

File tree

Expand file treeCollapse file tree

39 files changed

+921
-211
lines changed
Filter options
Expand file treeCollapse file tree

39 files changed

+921
-211
lines changed

‎backend/internal/access-list.js

Copy file name to clipboardExpand all lines: backend/internal/access-list.js
+8-2Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ const internalAccessList = {
258258
})
259259
.where('access_list.is_deleted', 0)
260260
.andWhere('access_list.id', data.id)
261+
.groupBy('access_list.id')
261262
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
262263
.first();
263264

@@ -507,8 +508,13 @@ const internalAccessList = {
507508
if (typeof item.password !== 'undefined' && item.password.length) {
508509
logger.info('Adding: ' + item.username);
509510

510-
utils.execFile('/usr/bin/htpasswd', ['-b', htpasswd_file, item.username, item.password])
511-
.then((/*result*/) => {
511+
utils.execFile('openssl', ['passwd', '-apr1', item.password])
512+
.then((res) => {
513+
try {
514+
fs.appendFileSync(htpasswd_file, item.username + ':' + res + '\n', {encoding: 'utf8'});
515+
} catch (err) {
516+
reject(err);
517+
}
512518
next();
513519
})
514520
.catch((err) => {

‎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/internal/stream.js

Copy file name to clipboardExpand all lines: backend/internal/stream.js
+98-21Lines changed: 98 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
const _ = require('lodash');
2-
const error = require('../lib/error');
3-
const utils = require('../lib/utils');
4-
const streamModel = require('../models/stream');
5-
const internalNginx = require('./nginx');
6-
const internalAuditLog = require('./audit-log');
7-
const {castJsonIfNeed} = require('../lib/helpers');
1+
const _ = require('lodash');
2+
const error = require('../lib/error');
3+
const utils = require('../lib/utils');
4+
const streamModel = require('../models/stream');
5+
const internalNginx = require('./nginx');
6+
const internalAuditLog = require('./audit-log');
7+
const internalCertificate = require('./certificate');
8+
const internalHost = require('./host');
9+
const {castJsonIfNeed} = require('../lib/helpers');
810

911
function omissions () {
10-
return ['is_deleted'];
12+
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted'];
1113
}
1214

1315
const internalStream = {
@@ -18,6 +20,12 @@ const internalStream = {
1820
* @returns {Promise}
1921
*/
2022
create: (access, data) => {
23+
const create_certificate = data.certificate_id === 'new';
24+
25+
if (create_certificate) {
26+
delete data.certificate_id;
27+
}
28+
2129
return access.can('streams:create', data)
2230
.then((/*access_data*/) => {
2331
// TODO: At this point the existing ports should have been checked
@@ -27,16 +35,44 @@ const internalStream = {
2735
data.meta = {};
2836
}
2937

38+
// streams aren't routed by domain name so don't store domain names in the DB
39+
let data_no_domains = structuredClone(data);
40+
delete data_no_domains.domain_names;
41+
3042
return streamModel
3143
.query()
32-
.insertAndFetch(data)
44+
.insertAndFetch(data_no_domains)
3345
.then(utils.omitRow(omissions()));
3446
})
47+
.then((row) => {
48+
if (create_certificate) {
49+
return internalCertificate.createQuickCertificate(access, data)
50+
.then((cert) => {
51+
// update host with cert id
52+
return internalStream.update(access, {
53+
id: row.id,
54+
certificate_id: cert.id
55+
});
56+
})
57+
.then(() => {
58+
return row;
59+
});
60+
} else {
61+
return row;
62+
}
63+
})
64+
.then((row) => {
65+
// re-fetch with cert
66+
return internalStream.get(access, {
67+
id: row.id,
68+
expand: ['certificate', 'owner']
69+
});
70+
})
3571
.then((row) => {
3672
// Configure nginx
3773
return internalNginx.configure(streamModel, 'stream', row)
3874
.then(() => {
39-
return internalStream.get(access, {id: row.id, expand: ['owner']});
75+
return row;
4076
});
4177
})
4278
.then((row) => {
@@ -60,6 +96,12 @@ const internalStream = {
6096
* @return {Promise}
6197
*/
6298
update: (access, data) => {
99+
const create_certificate = data.certificate_id === 'new';
100+
101+
if (create_certificate) {
102+
delete data.certificate_id;
103+
}
104+
63105
return access.can('streams:update', data.id)
64106
.then((/*access_data*/) => {
65107
// TODO: at this point the existing streams should have been checked
@@ -71,16 +113,32 @@ const internalStream = {
71113
throw new error.InternalValidationError('Stream could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
72114
}
73115

116+
if (create_certificate) {
117+
return internalCertificate.createQuickCertificate(access, {
118+
domain_names: data.domain_names || row.domain_names,
119+
meta: _.assign({}, row.meta, data.meta)
120+
})
121+
.then((cert) => {
122+
// update host with cert id
123+
data.certificate_id = cert.id;
124+
})
125+
.then(() => {
126+
return row;
127+
});
128+
} else {
129+
return row;
130+
}
131+
})
132+
.then((row) => {
133+
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
134+
data = _.assign({}, {
135+
domain_names: row.domain_names
136+
}, data);
137+
74138
return streamModel
75139
.query()
76140
.patchAndFetchById(row.id, data)
77141
.then(utils.omitRow(omissions()))
78-
.then((saved_row) => {
79-
return internalNginx.configure(streamModel, 'stream', saved_row)
80-
.then(() => {
81-
return internalStream.get(access, {id: row.id, expand: ['owner']});
82-
});
83-
})
84142
.then((saved_row) => {
85143
// Add to audit log
86144
return internalAuditLog.add(access, {
@@ -93,6 +151,17 @@ const internalStream = {
93151
return saved_row;
94152
});
95153
});
154+
})
155+
.then(() => {
156+
return internalStream.get(access, {id: data.id, expand: ['owner', 'certificate']})
157+
.then((row) => {
158+
return internalNginx.configure(streamModel, 'stream', row)
159+
.then((new_meta) => {
160+
row.meta = new_meta;
161+
row = internalHost.cleanRowCertificateMeta(row);
162+
return _.omit(row, omissions());
163+
});
164+
});
96165
});
97166
},
98167

@@ -115,7 +184,7 @@ const internalStream = {
115184
.query()
116185
.where('is_deleted', 0)
117186
.andWhere('id', data.id)
118-
.allowGraph('[owner]')
187+
.allowGraph('[owner,certificate]')
119188
.first();
120189

121190
if (access_data.permission_visibility !== 'all') {
@@ -132,6 +201,7 @@ const internalStream = {
132201
if (!row || !row.id) {
133202
throw new error.ItemNotFoundError(data.id);
134203
}
204+
row = internalHost.cleanRowCertificateMeta(row);
135205
// Custom omissions
136206
if (typeof data.omit !== 'undefined' && data.omit !== null) {
137207
row = _.omit(row, data.omit);
@@ -197,14 +267,14 @@ const internalStream = {
197267
.then(() => {
198268
return internalStream.get(access, {
199269
id: data.id,
200-
expand: ['owner']
270+
expand: ['certificate', 'owner']
201271
});
202272
})
203273
.then((row) => {
204274
if (!row || !row.id) {
205275
throw new error.ItemNotFoundError(data.id);
206276
} else if (row.enabled) {
207-
throw new error.ValidationError('Host is already enabled');
277+
throw new error.ValidationError('Stream is already enabled');
208278
}
209279

210280
row.enabled = 1;
@@ -250,7 +320,7 @@ const internalStream = {
250320
if (!row || !row.id) {
251321
throw new error.ItemNotFoundError(data.id);
252322
} else if (!row.enabled) {
253-
throw new error.ValidationError('Host is already disabled');
323+
throw new error.ValidationError('Stream is already disabled');
254324
}
255325

256326
row.enabled = 0;
@@ -298,7 +368,7 @@ const internalStream = {
298368
.query()
299369
.where('is_deleted', 0)
300370
.groupBy('id')
301-
.allowGraph('[owner]')
371+
.allowGraph('[owner,certificate]')
302372
.orderByRaw('CAST(incoming_port AS INTEGER) ASC');
303373

304374
if (access_data.permission_visibility !== 'all') {
@@ -317,6 +387,13 @@ const internalStream = {
317387
}
318388

319389
return query.then(utils.omitRows(omissions()));
390+
})
391+
.then((rows) => {
392+
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
393+
return internalHost.cleanAllRowsCertificateMeta(rows);
394+
}
395+
396+
return rows;
320397
});
321398
},
322399

+38Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const migrate_name = 'stream_ssl';
2+
const logger = require('../logger').migrate;
3+
4+
/**
5+
* Migrate
6+
*
7+
* @see http://knexjs.org/#Schema
8+
*
9+
* @param {Object} knex
10+
* @returns {Promise}
11+
*/
12+
exports.up = function (knex) {
13+
logger.info('[' + migrate_name + '] Migrating Up...');
14+
15+
return knex.schema.table('stream', (table) => {
16+
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
17+
})
18+
.then(function () {
19+
logger.info('[' + migrate_name + '] stream Table altered');
20+
});
21+
};
22+
23+
/**
24+
* Undo Migrate
25+
*
26+
* @param {Object} knex
27+
* @returns {Promise}
28+
*/
29+
exports.down = function (knex) {
30+
logger.info('[' + migrate_name + '] Migrating Down...');
31+
32+
return knex.schema.table('stream', (table) => {
33+
table.dropColumn('certificate_id');
34+
})
35+
.then(function () {
36+
logger.info('[' + migrate_name + '] stream Table altered');
37+
});
38+
};

‎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
}

0 commit comments

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