updated API to reflect moved domains
This commit is contained in:
parent
61af4707ee
commit
79ef9694b7
|
@ -380,21 +380,21 @@ module.exports.create = function (deps, conf) {
|
|||
|
||||
var config = { restful: {} };
|
||||
config.restful.readConfig = function (req, res, next) {
|
||||
var part = conf;
|
||||
var part = new (require('./config').ConfigChanger)(conf);
|
||||
if (req.params.group) {
|
||||
part = part[req.params.group];
|
||||
}
|
||||
if (part && req.params.name) {
|
||||
part = part[req.params.name];
|
||||
if (part && req.params.domId) {
|
||||
part = part.domains.find(req.params.domId);
|
||||
}
|
||||
if (part && req.params.id) {
|
||||
part = part.find(function (mod) { return mod.id === req.params.id; });
|
||||
if (part && req.params.mod) {
|
||||
part = part[req.params.mod];
|
||||
}
|
||||
if (part && req.params.name2) {
|
||||
part = part[req.params.name2];
|
||||
if (part && req.params.modGrp) {
|
||||
part = part[req.params.modGrp];
|
||||
}
|
||||
if (part && req.params.id2) {
|
||||
part = part.find(function (mod) { return mod.id === req.params.id2; });
|
||||
if (part && req.params.modId) {
|
||||
part = part.find(req.params.modId);
|
||||
}
|
||||
|
||||
if (part) {
|
||||
|
@ -439,27 +439,35 @@ module.exports.create = function (deps, conf) {
|
|||
var err;
|
||||
deps.PromiseA.resolve().then(function () {
|
||||
var changer = new (require('./config').ConfigChanger)(conf);
|
||||
if (!changer[group] || !changer[group].modules) {
|
||||
err = new Error("'"+group+"' is not a valid settings group or has not modules");
|
||||
err.statusCode = 404;
|
||||
throw err;
|
||||
}
|
||||
|
||||
var modList;
|
||||
if (req.params.id) {
|
||||
if (changer[group].domains) {
|
||||
modList = (changer[group].domains.find(req.params.id) || {}).modules;
|
||||
if (req.params.domId) {
|
||||
var dom = changer.domains.find(req.params.domId);
|
||||
if (!dom) {
|
||||
err = new Error("no domain with ID '"+req.params.domId+"'");
|
||||
} else if (!dom.modules[group]) {
|
||||
err = new Error("domains don't contain '"+group+"' modules");
|
||||
} else {
|
||||
modList = dom.modules[group];
|
||||
}
|
||||
} else {
|
||||
modList = changer[group].modules;
|
||||
if (!changer[group] || !changer[group].modules) {
|
||||
err = new Error("'"+group+"' is not a valid settings group or doesn't support modules");
|
||||
} else {
|
||||
modList = changer[group].modules;
|
||||
}
|
||||
}
|
||||
if (!modList) {
|
||||
err = new Error("'"+group+"' has no domains list or '"+req.params.id+"' does not exist");
|
||||
|
||||
if (err) {
|
||||
err.statusCode = 404;
|
||||
throw err;
|
||||
}
|
||||
|
||||
modList.add(req.body);
|
||||
var update = req.body;
|
||||
if (!Array.isArray(update)) {
|
||||
update = [ update ];
|
||||
}
|
||||
update.forEach(modList.add, modList);
|
||||
|
||||
var errors = changer.validate();
|
||||
if (errors.length) {
|
||||
throw Object.assign(new Error(), errors[0], {statusCode: 400});
|
||||
|
@ -467,13 +475,13 @@ module.exports.create = function (deps, conf) {
|
|||
|
||||
return deps.storage.config.save(changer);
|
||||
}).then(function (config) {
|
||||
var base;
|
||||
if (!req.params.id) {
|
||||
base = config[group];
|
||||
var result;
|
||||
if (!req.params.domId) {
|
||||
result = config[group].modules;
|
||||
} else {
|
||||
base = config[group].domains.find(function (dom) { return dom.id === req.params.id; });
|
||||
result = config.domains.find(function (dom) { return dom.id === req.params.domId; }).modules[group];
|
||||
}
|
||||
res.send(deps.recase.snakeCopy(base.modules));
|
||||
res.send(deps.recase.snakeCopy(result));
|
||||
}, function (err) {
|
||||
res.statusCode = err.statusCode || 500;
|
||||
err.message = err.message || err.toString();
|
||||
|
@ -481,17 +489,15 @@ module.exports.create = function (deps, conf) {
|
|||
});
|
||||
};
|
||||
config.restful.createDomain = function (req, res) {
|
||||
var group = req.params.group;
|
||||
var err;
|
||||
deps.PromiseA.resolve().then(function () {
|
||||
var changer = new (require('./config').ConfigChanger)(conf);
|
||||
if (!changer[group] || !changer[group].domains) {
|
||||
err = new Error("'"+group+"' is not a valid settings group or has no domains list");
|
||||
err.statusCode = 404;
|
||||
throw err;
|
||||
}
|
||||
|
||||
changer[group].domains.add(req.body);
|
||||
var update = req.body;
|
||||
if (!Array.isArray(update)) {
|
||||
update = [ update ];
|
||||
}
|
||||
update.forEach(changer.domains.add, changer.domains);
|
||||
|
||||
var errors = changer.validate();
|
||||
if (errors.length) {
|
||||
throw Object.assign(new Error(), errors[0], {statusCode: 400});
|
||||
|
@ -499,7 +505,7 @@ module.exports.create = function (deps, conf) {
|
|||
|
||||
return deps.storage.config.save(changer);
|
||||
}).then(function (config) {
|
||||
res.send(deps.recase.snakeCopy(config[group].domains));
|
||||
res.send(deps.recase.snakeCopy(config.domains));
|
||||
}, function (err) {
|
||||
res.statusCode = err.statusCode || 500;
|
||||
err.message = err.message || err.toString();
|
||||
|
@ -518,14 +524,15 @@ module.exports.create = function (deps, conf) {
|
|||
app.use( '/config', makeCorsHandler());
|
||||
app.get( '/config', config.restful.readConfig);
|
||||
app.get( '/config/:group', config.restful.readConfig);
|
||||
app.get( '/config/:group/:name(modules|domains)/:id?', config.restful.readConfig);
|
||||
app.get( '/config/:group/:name(domains)/:id/:name2(modules)/:id2?', config.restful.readConfig);
|
||||
app.get( '/config/:group/:mod(modules)/:modId?', config.restful.readConfig);
|
||||
app.get( '/config/domains/:domId/:mod(modules)?', config.restful.readConfig);
|
||||
app.get( '/config/domains/:domId/:mod(modules)/:modGrp/:modId?', config.restful.readConfig);
|
||||
|
||||
app.post( '/config', config.restful.saveBaseConfig);
|
||||
app.post( '/config/:group', config.restful.saveBaseConfig);
|
||||
app.post( '/config/:group/modules', config.restful.createModule);
|
||||
app.post( '/config/:group/domains', config.restful.createDomain);
|
||||
app.post( '/config/:group/domains/:id/modules', config.restful.createModule);
|
||||
app.post( '/config/:group(?!domains)', config.restful.saveBaseConfig);
|
||||
app.post( '/config/:group(?!domains)/modules', config.restful.createModule);
|
||||
app.post( '/config/domains', config.restful.createDomain);
|
||||
app.post( '/config/domains/:domId/modules/:group',config.restful.createModule);
|
||||
|
||||
return app;
|
||||
};
|
||||
|
|
|
@ -63,54 +63,64 @@ Object.keys(moduleSchemas).forEach(function (name) {
|
|||
validator.addSchema(schema, schema.id);
|
||||
});
|
||||
|
||||
function addDomainsSchema(base, modList) {
|
||||
var modSchemas = modList.map(function (name) {
|
||||
return { '$ref': '/modules/'+name };
|
||||
});
|
||||
|
||||
base.required = [ 'modules', 'domains' ].concat(base.required || []);
|
||||
base.properties.modules = {
|
||||
type: 'array'
|
||||
, items: {
|
||||
type: 'object'
|
||||
, required: [ 'domains' ]
|
||||
, properties: {
|
||||
domains: { type: 'array', items: { type: 'string' }, minLength: 1}
|
||||
}
|
||||
, oneOf: modSchemas
|
||||
}
|
||||
};
|
||||
base.properties.domains = {
|
||||
type: 'array'
|
||||
, items: {
|
||||
type: 'object'
|
||||
, required: [ 'id', 'names', ]
|
||||
, properties: {
|
||||
id: { type: 'string' }
|
||||
, names: { type: 'array', items: { type: 'string' }, minLength: 1}
|
||||
, modules: { type: 'array', items: { oneOf: modSchemas }}
|
||||
}
|
||||
}
|
||||
};
|
||||
function toSchemaRef(name) {
|
||||
return { '$ref': '/modules/'+name };
|
||||
}
|
||||
var moduleRefs = {
|
||||
http: [ 'proxy', 'static', 'redirect' ].map(toSchemaRef)
|
||||
, tls: [ 'proxy', 'acme' ].map(toSchemaRef)
|
||||
, tcp: [ 'forward' ].map(toSchemaRef)
|
||||
, udp: [ 'proxy' ].map(toSchemaRef)
|
||||
};
|
||||
|
||||
function addDomainRequirement(itemSchema) {
|
||||
itemSchema.required = (itemSchema.required || []).concat('domains');
|
||||
itemSchema.properties = itemSchema.properties || {};
|
||||
itemSchema.domains = { type: 'array', items: { type: 'string' }, minLength: 1};
|
||||
return itemSchema;
|
||||
}
|
||||
|
||||
var domainSchema = {
|
||||
type: 'array'
|
||||
, items: {
|
||||
type: 'object'
|
||||
, properties: {
|
||||
id: { type: 'string' }
|
||||
, names: { type: 'array', items: { type: 'string' }, minLength: 1}
|
||||
, modules: {
|
||||
type: 'object'
|
||||
, properties: {
|
||||
tls: { type: 'array', items: { oneOf: moduleRefs.tls }}
|
||||
, http: { type: 'array', items: { oneOf: moduleRefs.http }}
|
||||
}
|
||||
, additionalProperties: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var httpSchema = {
|
||||
type: 'object'
|
||||
, properties: {
|
||||
modules: { type: 'array', items: addDomainRequirement({ oneOf: moduleRefs.http }) }
|
||||
|
||||
// These properties should be snake_case to match the API and config format
|
||||
primary_domain: { type: 'string' }
|
||||
, primary_domain: { type: 'string' }
|
||||
, allow_insecure: { type: 'boolean' }
|
||||
, trust_proxy: { type: 'boolean' }
|
||||
|
||||
, bind: { not: {} } // this is a forbidden deprecated setting.
|
||||
// these are forbidden deprecated settings.
|
||||
, bind: { not: {} }
|
||||
, domains: { not: {} }
|
||||
}
|
||||
};
|
||||
addDomainsSchema(httpSchema, ['proxy', 'static', 'redirect']);
|
||||
|
||||
var tlsSchema = {
|
||||
type: 'object'
|
||||
, properties: {
|
||||
acme: {
|
||||
modules: { type: 'array', items: addDomainRequirement({ oneOf: moduleRefs.tls }) }
|
||||
|
||||
, acme: {
|
||||
type: 'object'
|
||||
// These properties should be snake_case to match the API and config format
|
||||
, required: [ 'email', 'approved_domains' ]
|
||||
|
@ -120,19 +130,20 @@ var tlsSchema = {
|
|||
, challenge_type: { type: 'string' }
|
||||
, approved_domains: { type: 'array', items: { type: 'string' }, minLength: 1}
|
||||
|
||||
, bind: { not: {} } // this is a forbidden deprecated setting.
|
||||
// these are forbidden deprecated settings.
|
||||
, bind: { not: {} }
|
||||
, domains: { not: {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
addDomainsSchema(tlsSchema, ['proxy', 'acme']);
|
||||
|
||||
var tcpSchema = {
|
||||
type: 'object'
|
||||
, required: [ 'bind' ]
|
||||
, properties: {
|
||||
bind: { type: 'array', items: portSchema, minLength: 1 }
|
||||
, modules: { type: 'array', items: { '$ref': '/modules/forward' }}
|
||||
, modules: { type: 'array', items: { oneOf: moduleRefs.tcp }}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,7 +151,7 @@ var udpSchema = {
|
|||
type: 'object'
|
||||
, properties: {
|
||||
bind: { type: 'array', items: portSchema }
|
||||
, modules: { type: 'array', items: { '$ref': '/modules/proxy' }}
|
||||
, modules: { type: 'array', items: { oneOf: moduleRefs.udp }}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -176,9 +187,10 @@ var deviceSchema = {
|
|||
|
||||
var mainSchema = {
|
||||
type: 'object'
|
||||
, required: [ 'http', 'tls', 'tcp', 'udp', 'mdns', 'ddns' ]
|
||||
, required: [ 'domains', 'http', 'tls', 'tcp', 'udp', 'mdns', 'ddns' ]
|
||||
, properties: {
|
||||
http: httpSchema
|
||||
domains:domainSchema
|
||||
, http: httpSchema
|
||||
, tls: tlsSchema
|
||||
, tcp: tcpSchema
|
||||
, udp: udpSchema
|
||||
|
@ -228,7 +240,10 @@ class DomainList extends Array {
|
|||
Object.assign(this, JSON.parse(JSON.stringify(rawList)));
|
||||
}
|
||||
this.forEach(function (dom) {
|
||||
dom.modules = new ModuleList(dom.modules);
|
||||
dom.modules = {
|
||||
http: new ModuleList((dom.modules || {}).http),
|
||||
tls: new ModuleList((dom.modules || {}).tls),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -245,15 +260,19 @@ class DomainList extends Array {
|
|||
throw new Error("all domain names must be strings");
|
||||
}
|
||||
|
||||
var modList = new ModuleList();
|
||||
if (Array.isArray(dom.modules)) {
|
||||
dom.modules.forEach(function (mod) {
|
||||
modList.add(mod);
|
||||
});
|
||||
var modLists = {
|
||||
http: new ModuleList(),
|
||||
tls: new ModuleList()
|
||||
};
|
||||
if (dom.modules && Array.isArray(dom.modules.http)) {
|
||||
dom.modules.http.forEach(modLists.http.add, modLists.http);
|
||||
}
|
||||
if (dom.modules && Array.isArray(dom.modules.tls)) {
|
||||
dom.modules.tls.forEach(modLists.tls.add, modLists.tls);
|
||||
}
|
||||
|
||||
dom.id = require('crypto').randomBytes(4).toString('hex');
|
||||
dom.modules = modList;
|
||||
dom.modules = modLists;
|
||||
this.push(dom);
|
||||
}
|
||||
}
|
||||
|
@ -263,10 +282,9 @@ class ConfigChanger {
|
|||
Object.assign(this, JSON.parse(JSON.stringify(start)));
|
||||
delete this.device;
|
||||
|
||||
this.domains = new DomainList(this.domains);
|
||||
this.http.modules = new ModuleList(this.http.modules);
|
||||
this.http.domains = new DomainList(this.http.domains);
|
||||
this.tls.modules = new ModuleList(this.tls.modules);
|
||||
this.tls.domains = new DomainList(this.tls.domains);
|
||||
this.tcp.modules = new ModuleList(this.tcp.modules);
|
||||
this.udp.modules = new ModuleList(this.udp.modules);
|
||||
}
|
||||
|
@ -274,32 +292,15 @@ class ConfigChanger {
|
|||
update(update) {
|
||||
var self = this;
|
||||
|
||||
if (update.http && update.http.modules) {
|
||||
update.http.modules.forEach(self.http.modules.add.bind(self.http.modules));
|
||||
delete update.http.modules;
|
||||
}
|
||||
if (update.http && update.http.domains) {
|
||||
update.http.domains.forEach(self.http.domains.add.bind(self.http.domains));
|
||||
delete update.http.domains;
|
||||
}
|
||||
|
||||
if (update.tls && update.tls.modules) {
|
||||
update.tls.modules.forEach(self.tls.modules.add.bind(self.tls.modules));
|
||||
delete update.tls.modules;
|
||||
}
|
||||
if (update.tls && update.tls.domains) {
|
||||
update.tls.domains.forEach(self.tls.domains.add.bind(self.tls.domains));
|
||||
delete update.tls.domains;
|
||||
}
|
||||
|
||||
if (update.tcp && update.tcp.modules) {
|
||||
update.tcp.modules.forEach(self.tcp.modules.add.bind(self.tcp.modules));
|
||||
delete update.tcp.modules;
|
||||
}
|
||||
if (update.udp && update.udp.modules) {
|
||||
update.udp.modules.forEach(self.udp.modules.add.bind(self.udp.modules));
|
||||
delete update.udp.modules;
|
||||
if (update.domains) {
|
||||
update.domains.forEach(self.domains.add, self.domains);
|
||||
}
|
||||
[ 'http', 'tls', 'tcp', 'udp' ].forEach(function (name) {
|
||||
if (update[name] && update[name].modules) {
|
||||
update[name].modules.forEach(self[name].modules.add, self[name].modules);
|
||||
delete update[name].modules;
|
||||
}
|
||||
});
|
||||
|
||||
function mergeSettings(orig, changes) {
|
||||
Object.keys(changes).forEach(function (key) {
|
||||
|
|
Loading…
Reference in New Issue