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 {
 | 
			
		||||
        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) {
 | 
			
		||||
function toSchemaRef(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
 | 
			
		||||
}
 | 
			
		||||
var moduleRefs = {
 | 
			
		||||
  http: [ 'proxy', 'static', 'redirect' ].map(toSchemaRef)
 | 
			
		||||
, tls:  [ 'proxy', 'acme' ].map(toSchemaRef)
 | 
			
		||||
, tcp:  [ 'forward' ].map(toSchemaRef)
 | 
			
		||||
, udp:  [ 'proxy' ].map(toSchemaRef)
 | 
			
		||||
};
 | 
			
		||||
  base.properties.domains = {
 | 
			
		||||
 | 
			
		||||
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'
 | 
			
		||||
    , required: [ 'id', 'names', ]
 | 
			
		||||
  , properties: {
 | 
			
		||||
      id:      { type: 'string' }
 | 
			
		||||
    , names:   { type: 'array', items: { type: 'string' }, minLength: 1}
 | 
			
		||||
      , modules: { type: 'array', items: { oneOf: modSchemas }}
 | 
			
		||||
    , 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.domains) {
 | 
			
		||||
      update.domains.forEach(self.domains.add, self.domains);
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
    [ '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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user