show many more things
This commit is contained in:
		
							parent
							
								
									783dd3c53b
								
							
						
					
					
						commit
						90f5eb11d5
					
				@ -18,24 +18,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <div class="container" ng-controller="LoginController as vm" ng-init="vm.setSimple()">
 | 
					    <div class="container" ng-controller="LoginController as vm" ng-init="vm.setSimple()">
 | 
				
			||||||
      <h1 ng-if="!vm.authnUpdated">Initializing... {{vm.hello}}</h1>
 | 
					      <h1 ng-if="!vm.authnUpdated">Initializing... {{vm.hello}}</h1>
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					      Configure Remote Server
 | 
				
			||||||
 | 
					      <label>Configuration Address:</label>
 | 
				
			||||||
 | 
					      <input type="text" placeholder="i.e. 192.168.1.100">
 | 
				
			||||||
 | 
					      <label>Configuration Name:</label>
 | 
				
			||||||
 | 
					      <input type="text" placeholder="i.e. localhost.daplie.invalid">
 | 
				
			||||||
 | 
					      <label>Root Certificate Validation (optional):</label>
 | 
				
			||||||
 | 
					      <textarea class="textarea" placeholder="paste the contents of a root.pem here"></textarea>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div ng-if="!vm.authnUpdated">
 | 
					      <div ng-if="!vm.authnUpdated">
 | 
				
			||||||
      <button
 | 
					 | 
				
			||||||
        type="button"
 | 
					 | 
				
			||||||
        class="btn btn-link"
 | 
					 | 
				
			||||||
        ng-if="!vm.advanced"
 | 
					 | 
				
			||||||
        ng-click="vm.setAdvanced()"
 | 
					 | 
				
			||||||
        >advanced</button>
 | 
					 | 
				
			||||||
      <button
 | 
					 | 
				
			||||||
        type="button"
 | 
					 | 
				
			||||||
        class="btn btn-link"
 | 
					 | 
				
			||||||
        ng-if="vm.advanced"
 | 
					 | 
				
			||||||
        ng-click="vm.setSimple();"
 | 
					 | 
				
			||||||
        >simple</button>
 | 
					 | 
				
			||||||
      <input
 | 
					 | 
				
			||||||
        type="text"
 | 
					 | 
				
			||||||
        ng-if="vm.advanced"
 | 
					 | 
				
			||||||
        ng-change="vm.checkProviderUri(vm.myProviderUri)"
 | 
					 | 
				
			||||||
        ng-model="vm.myProviderUri">
 | 
					 | 
				
			||||||
      <button
 | 
					      <button
 | 
				
			||||||
        type="button"
 | 
					        type="button"
 | 
				
			||||||
        class="btn btn-default"
 | 
					        class="btn btn-default"
 | 
				
			||||||
@ -43,48 +37,143 @@
 | 
				
			|||||||
        ng-click="vm.authenticate()"
 | 
					        ng-click="vm.authenticate()"
 | 
				
			||||||
        >Login</button>
 | 
					        >Login</button>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					      <button
 | 
				
			||||||
 | 
					        type="button"
 | 
				
			||||||
 | 
					        class="btn btn-link"
 | 
				
			||||||
 | 
					        ng-if="!vm.advanced"
 | 
				
			||||||
 | 
					        ng-click="vm.setAdvanced()"
 | 
				
			||||||
 | 
					        >advanced</button>
 | 
				
			||||||
 | 
					      <div ng-if="vm.advanced">
 | 
				
			||||||
 | 
					        <button
 | 
				
			||||||
 | 
					          type="button"
 | 
				
			||||||
 | 
					          class="btn btn-link"
 | 
				
			||||||
 | 
					          ng-click="vm.setSimple();"
 | 
				
			||||||
 | 
					          >simple</button>
 | 
				
			||||||
 | 
					        <input
 | 
				
			||||||
 | 
					          type="text"
 | 
				
			||||||
 | 
					          ng-change="vm.checkProviderUri(vm.myProviderUri)"
 | 
				
			||||||
 | 
					          ng-model="vm.myProviderUri">
 | 
				
			||||||
 | 
					        <br/>
 | 
				
			||||||
 | 
					        <small>todo: allow per-device authorization</small>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div ng-if="vm.config">
 | 
					      <div ng-if="vm.config">
 | 
				
			||||||
        <div class="input-group" ng-init="siteconf = vm.config.global">
 | 
					        <div ng-init="siteconf = vm.config.global">
 | 
				
			||||||
 | 
					          <h1>Server Device Name: <span ng-bind="vm.config.device.hostname"></span></h1>
 | 
				
			||||||
 | 
					          <!-- input class="form-control" ng-model="vm.config.device.hostname" / -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <h1>Server Working Directory:</h1>
 | 
					          <h1>Server Working Directory:</h1>
 | 
				
			||||||
          <input class="form-control" ng-model="vm.config.cwd" />
 | 
					          <input class="form-control" ng-model="vm.config.cwd" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <h1>Addresses:</h1>
 | 
				
			||||||
 | 
					          <table class="table">
 | 
				
			||||||
 | 
					            <tr>
 | 
				
			||||||
 | 
					              <th>Interface</th>
 | 
				
			||||||
 | 
					              <th>Address</th>
 | 
				
			||||||
 | 
					              <th>Family</th>
 | 
				
			||||||
 | 
					              <th>Scope</th>
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					            <tr ng-repeat="addr in vm.config.addresses">
 | 
				
			||||||
 | 
					              <td ng-bind="addr.iface"></td>
 | 
				
			||||||
 | 
					              <td ng-bind="addr.address"></td>
 | 
				
			||||||
 | 
					              <td ng-bind="addr.family"></td>
 | 
				
			||||||
 | 
					              <td ng-bind="addr.range"></td>
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					          </table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <h1>Managed Domains:</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div ng-if="!vm.domains.length">
 | 
				
			||||||
 | 
					            You don't have any domains with this account.
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            Try a different account?
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <input type="url" placeholder="https://daplie.domains">
 | 
				
			||||||
 | 
					            <button type="button"
 | 
				
			||||||
 | 
					              class="btn"
 | 
				
			||||||
 | 
					              disabled
 | 
				
			||||||
 | 
					              >Login</button>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <div ng-if="vm.domains.length">
 | 
				
			||||||
 | 
					            <h2>Enable Tunnel</h2>
 | 
				
			||||||
 | 
					            <input type="radio" ng-model="vm.config.tunnel.enabled" ng-value="true">
 | 
				
			||||||
 | 
					            <input type="radio" ng-model="vm.config.tunnel.enabled" ng-value="false">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <table class="table">
 | 
				
			||||||
 | 
					              <tr>
 | 
				
			||||||
 | 
					                <th>Domain</th>
 | 
				
			||||||
 | 
					                <th>Sub</th>
 | 
				
			||||||
 | 
					                <th>Devices</th>
 | 
				
			||||||
 | 
					              </tr>
 | 
				
			||||||
 | 
					              <tr ng-repeat="d in vm.dns">
 | 
				
			||||||
 | 
					                <td ng-bind="d.domain"></td>
 | 
				
			||||||
 | 
					                <td ng-bind="d.name"></td>
 | 
				
			||||||
 | 
					                <td>
 | 
				
			||||||
 | 
					                  <span ng-if="!d.domain">
 | 
				
			||||||
 | 
					                    <div ng-repeat="dev in d.devices">
 | 
				
			||||||
 | 
					                      <span ng-bind="dev"
 | 
				
			||||||
 | 
					                        ></span> <button
 | 
				
			||||||
 | 
					                        type="button"
 | 
				
			||||||
 | 
					                        class="btn btn-danger"
 | 
				
			||||||
 | 
					                        ng-click="vm.removeDevice(d, dev)"
 | 
				
			||||||
 | 
					                        >x</button>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                  </span>
 | 
				
			||||||
 | 
					                </td>
 | 
				
			||||||
 | 
					              </tr>
 | 
				
			||||||
 | 
					            </table>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <h1>Global Settings:</h1>
 | 
					          <h1>Global Settings:</h1>
 | 
				
			||||||
          <br/>
 | 
					          <br/>
 | 
				
			||||||
          <div ng-repeat="path in siteconf.paths">Pathname:
 | 
					          <form class="form-inline">
 | 
				
			||||||
            <input class="form-control" ng-model="path.$id" />
 | 
					          <div ng-repeat="path in siteconf.paths">
 | 
				
			||||||
            <div ng-repeat="module in path.modules">Modulename: {{module.$id}}
 | 
					            <h2 ng-bind="path.$id"></h2>
 | 
				
			||||||
              <div ng-repeat="(key, value) in module">{{key}}:
 | 
					            <div ng-repeat="module in path.modules">
 | 
				
			||||||
                <input class="form-control" ng-model="value" />
 | 
					              <h3>{{module.$id}}</h3>
 | 
				
			||||||
 | 
					              <div ng-repeat="(key, value) in module">
 | 
				
			||||||
 | 
					                <label>{{key}}</label>: <input class="form-control" ng-model="module[key]" />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					          </form>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <h1>Per-Domain Settings:</h1>
 | 
					        <h1>Per-Domain Settings:</h1>
 | 
				
			||||||
        <div class="input-group" ng-repeat="siteconf in vm.config.sites">
 | 
					        <div ng-repeat="siteconf in vm.config.sites">
 | 
				
			||||||
          <label>Hostname:</label> <input class="form-control" ng-model="siteconf.$id" />
 | 
					          <h2 ng-bind="siteconf.$id"></h2>
 | 
				
			||||||
          <br/>
 | 
					          <div ng-repeat="path in siteconf.paths">
 | 
				
			||||||
          <div ng-repeat="path in siteconf.paths">Pathname:
 | 
					            <h2 ng-bind="path.$id"></h2>
 | 
				
			||||||
            <input class="form-control" ng-model="path.$id" />
 | 
					            <div ng-repeat="module in path.modules">
 | 
				
			||||||
            <div ng-repeat="module in path.modules">Modulename: {{module.$id}}
 | 
					              <h3>{{module.$id}}</h3>
 | 
				
			||||||
              <div ng-repeat="(key, value) in module">{{key}}:
 | 
					              <div ng-repeat="(key, value) in module">
 | 
				
			||||||
                <input class="form-control" ng-model="value" />
 | 
					                <label>{{key}}</label>: <input class="form-control" ng-model="module[key]" />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="input-group" ng-init="defaultsconf = vm.config.defaults">
 | 
					        <div ng-init="defaultsconf = vm.config.defaults">
 | 
				
			||||||
          <h1>Fallback Settings:</h1>
 | 
					          <h1>Fallback Settings:</h1>
 | 
				
			||||||
          <br/>
 | 
					          <br/>
 | 
				
			||||||
          <div ng-repeat="path in defaultsconf.paths">Pathname:
 | 
					          <div ng-repeat="path in siteconf.paths">
 | 
				
			||||||
            <input class="form-control" ng-model="path.$id" />
 | 
					            <h2 ng-bind="path.$id"></h2>
 | 
				
			||||||
            <div ng-repeat="module in path.modules">Modulename: {{module.$id}}
 | 
					            <div ng-repeat="module in path.modules">
 | 
				
			||||||
              <div ng-repeat="(key, value) in module">{{key}}:
 | 
					              <h3>{{module.$id}}</h3>
 | 
				
			||||||
                <input class="form-control" ng-model="value" />
 | 
					              <div ng-repeat="(key, value) in module">
 | 
				
			||||||
 | 
					                <label>{{key}}</label>: <input class="form-control" ng-model="module[key]" />
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
 | 
					            <br/>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -104,6 +193,7 @@
 | 
				
			|||||||
    <script src="/assets/org.oauth3/oauth3.core.js"></script>
 | 
					    <script src="/assets/org.oauth3/oauth3.core.js"></script>
 | 
				
			||||||
    <script src="/assets/org.oauth3/oauth3.ng.js"></script>
 | 
					    <script src="/assets/org.oauth3/oauth3.ng.js"></script>
 | 
				
			||||||
    <script src="/assets/org.oauth3/oauth3.domains.js"></script>
 | 
					    <script src="/assets/org.oauth3/oauth3.domains.js"></script>
 | 
				
			||||||
 | 
					    <script src="/assets/org.oauth3/oauth3.dns.js"></script>
 | 
				
			||||||
    <script src="/js/app.js"></script>
 | 
					    <script src="/js/app.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
 | 
				
			|||||||
@ -38,6 +38,91 @@ angular.module('com.daplie.cloud', [ 'org.oauth3' ])
 | 
				
			|||||||
      }, 250);
 | 
					      }, 250);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vm.sortDnsRecords = function (a, b) {
 | 
				
			||||||
 | 
					      if (a.sld !== b.sld) {
 | 
				
			||||||
 | 
					        return a.sld > b.sld ? 1 : -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (a.tld !== b.tld) {
 | 
				
			||||||
 | 
					        return a.tld > b.tld ? 1 : -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // TODO normalize
 | 
				
			||||||
 | 
					      a.sub = a.sub || '';
 | 
				
			||||||
 | 
					      b.sub = b.sub || '';
 | 
				
			||||||
 | 
					      if (a.sub !== b.sub) {
 | 
				
			||||||
 | 
					        if (!a.sub) {
 | 
				
			||||||
 | 
					          return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!b.sub) {
 | 
				
			||||||
 | 
					          return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return a.sub > b.sub ? 1 : -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (a.domain !== b.domain) {
 | 
				
			||||||
 | 
					        if (!a.domain) {
 | 
				
			||||||
 | 
					          return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!b.domain) {
 | 
				
			||||||
 | 
					          return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vm.viewDomains = function (config, domains, dns) {
 | 
				
			||||||
 | 
					      vm.dns = dns.slice(0);
 | 
				
			||||||
 | 
					      vm.domains = domains.slice(0);
 | 
				
			||||||
 | 
					      vm.dns = vm.dns.filter(function (record) {
 | 
				
			||||||
 | 
					        if (-1 === [ 'A', 'AAAA', 'ANAME' ].indexOf(record.type)) {
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (record.device !== config.device.hostname) {
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      vm.dns.forEach(function (r) {
 | 
				
			||||||
 | 
					        vm.domains.forEach(function (d) {
 | 
				
			||||||
 | 
					          if (r.zone === d.domain) {
 | 
				
			||||||
 | 
					            r.sub = r.name.substr(0, r.name.length - (d.domain.length + 1));
 | 
				
			||||||
 | 
					            r.tld = d.tld;
 | 
				
			||||||
 | 
					            r.sld = d.sld;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      vm.dns = vm.dns.concat(vm.domains);
 | 
				
			||||||
 | 
					      vm.dns.sort(vm.sortDnsRecords);
 | 
				
			||||||
 | 
					      vm.dns.forEach(function (r) {
 | 
				
			||||||
 | 
					        if (r.domain) {
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        r.devices = r.devices || [ r.device ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dns.forEach(function (r2) {
 | 
				
			||||||
 | 
					          if (r.name !== r2.name) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (-1 !== r.devices.indexOf(r2.device)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          r.devices.push(r2.device);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      console.log('vm.dns');
 | 
				
			||||||
 | 
					      console.log(vm.dns);
 | 
				
			||||||
 | 
					      /*
 | 
				
			||||||
 | 
					      vm.domains.forEach(function (d) {
 | 
				
			||||||
 | 
					        d.devices = [];
 | 
				
			||||||
 | 
					        dns.forEach(function (r) {
 | 
				
			||||||
 | 
					          // 0 === r.name.split('').reverse().join('').indexOf(d.domain.split('').reverse().join(''))
 | 
				
			||||||
 | 
					          if (r.zone === d.domain) {
 | 
				
			||||||
 | 
					            d.devices.push({
 | 
				
			||||||
 | 
					              name: r.device
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      */
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vm.authenticate = function () {
 | 
					    vm.authenticate = function () {
 | 
				
			||||||
      // TODO authorization redirect /api/org.oauth3.consumer/authorization_redirect/:provider_uri
 | 
					      // TODO authorization redirect /api/org.oauth3.consumer/authorization_redirect/:provider_uri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,44 +131,50 @@ angular.module('com.daplie.cloud', [ 'org.oauth3' ])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return oauth3.api('domains.list').then(function (domains) {
 | 
					        return oauth3.api('domains.list').then(function (domains) {
 | 
				
			||||||
          console.info("domains owned", domains);
 | 
					          console.info("domains owned", domains);
 | 
				
			||||||
          vm.domains = domains;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
          return OAUTH3.request({
 | 
					          return oauth3.api('dns.list').then(function (dns) {
 | 
				
			||||||
            method: 'POST'
 | 
					            console.info("dns records", dns);
 | 
				
			||||||
          , url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/init'
 | 
					
 | 
				
			||||||
          , session: session
 | 
					 | 
				
			||||||
          , data: {
 | 
					 | 
				
			||||||
              access_token: session.access_token
 | 
					 | 
				
			||||||
            , refresh_token: session.refresh_token
 | 
					 | 
				
			||||||
            , expires_in: session.expires_in
 | 
					 | 
				
			||||||
            , scope: session.scope
 | 
					 | 
				
			||||||
            , provider_uri: OAUTH3.uri.normalize(session.provider_uri)
 | 
					 | 
				
			||||||
            , client_uri: vm.clientUri
 | 
					 | 
				
			||||||
            , domains: domains.map(function (d) {
 | 
					 | 
				
			||||||
                return {
 | 
					 | 
				
			||||||
                  id: d.id
 | 
					 | 
				
			||||||
                , sub: d.sub
 | 
					 | 
				
			||||||
                , sld: d.sld
 | 
					 | 
				
			||||||
                , tld: d.tld
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
            , jwk: null // TODO publish public key
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }).then(function (resp) {
 | 
					 | 
				
			||||||
            // TODO resp should contain a token
 | 
					 | 
				
			||||||
            console.info('Initialized Goldilocks', resp);
 | 
					 | 
				
			||||||
            return OAUTH3.request({
 | 
					            return OAUTH3.request({
 | 
				
			||||||
              method: 'GET'
 | 
					              method: 'POST'
 | 
				
			||||||
            , url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/config'
 | 
					            , url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/init'
 | 
				
			||||||
            , session: session
 | 
					            , session: session
 | 
				
			||||||
            }).then(function (configResp) {
 | 
					            , data: {
 | 
				
			||||||
              console.log('config', configResp.data);
 | 
					                access_token: session.access_token
 | 
				
			||||||
              vm.config = configResp.data;
 | 
					              , refresh_token: session.refresh_token
 | 
				
			||||||
              return resp;
 | 
					              , expires_in: session.expires_in
 | 
				
			||||||
 | 
					              , scope: session.scope
 | 
				
			||||||
 | 
					              , provider_uri: OAUTH3.uri.normalize(session.provider_uri)
 | 
				
			||||||
 | 
					              , client_uri: vm.clientUri
 | 
				
			||||||
 | 
					              , domains: domains.map(function (d) {
 | 
				
			||||||
 | 
					                  return {
 | 
				
			||||||
 | 
					                    id: d.id
 | 
				
			||||||
 | 
					                  , sub: d.sub
 | 
				
			||||||
 | 
					                  , sld: d.sld
 | 
				
			||||||
 | 
					                  , tld: d.tld
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					              , jwk: null // TODO publish public key
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }).then(function (resp) {
 | 
				
			||||||
 | 
					              // TODO resp should contain a token
 | 
				
			||||||
 | 
					              console.info('Initialized Goldilocks', resp);
 | 
				
			||||||
 | 
					              return OAUTH3.request({
 | 
				
			||||||
 | 
					                method: 'GET'
 | 
				
			||||||
 | 
					              , url: 'https://' + vm.clientUri + '/api/com.daplie.caddy/config'
 | 
				
			||||||
 | 
					              , session: session
 | 
				
			||||||
 | 
					              }).then(function (configResp) {
 | 
				
			||||||
 | 
					                console.log('config', configResp.data);
 | 
				
			||||||
 | 
					                vm.config = configResp.data;
 | 
				
			||||||
 | 
					                //vm.config.ifaces
 | 
				
			||||||
 | 
					                //vm.config.addresses = [];
 | 
				
			||||||
 | 
					                vm.viewDomains(vm.config, domains, dns);
 | 
				
			||||||
 | 
					                return resp;
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					            }, function (err) {
 | 
				
			||||||
 | 
					              console.error(err);
 | 
				
			||||||
 | 
					              window.alert("Initialization failed:" + err.message);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
          }, function (err) {
 | 
					 | 
				
			||||||
            console.error(err);
 | 
					 | 
				
			||||||
            window.alert("Initialization failed:" + err.message);
 | 
					 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }, function (err) {
 | 
					      }, function (err) {
 | 
				
			||||||
 | 
				
			|||||||
@ -92,152 +92,191 @@ function createServer(port, _delete_me_, content, opts) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return new PromiseA(function (realResolve) {
 | 
					  return new PromiseA(function (realResolve) {
 | 
				
			||||||
    var app = require('../lib/app.js');
 | 
					    var app = require('../lib/app.js');
 | 
				
			||||||
 | 
					    var ipaddr = require('ipaddr.js');
 | 
				
			||||||
 | 
					    var addresses = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var directive = {
 | 
					    Object.keys(opts.ifaces).forEach(function (ifacename) {
 | 
				
			||||||
      global: opts.global
 | 
					      var iface = opts.ifaces[ifacename];
 | 
				
			||||||
    , sites: opts.sites
 | 
					      iface.ipv4.forEach(function (ip) {
 | 
				
			||||||
    , defaults: opts.defaults
 | 
					        addresses.push(ip);
 | 
				
			||||||
    , cwd: process.cwd()
 | 
					      });
 | 
				
			||||||
    };
 | 
					      iface.ipv6.forEach(function (ip) {
 | 
				
			||||||
    var server;
 | 
					        addresses.push(ip);
 | 
				
			||||||
    var insecureServer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function resolve() {
 | 
					 | 
				
			||||||
      realResolve({
 | 
					 | 
				
			||||||
        plainServer: insecureServer
 | 
					 | 
				
			||||||
      , server: server
 | 
					 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // returns an instance of node-letsencrypt with additional helper methods
 | 
					 | 
				
			||||||
    var webrootPath = require('os').tmpdir();
 | 
					 | 
				
			||||||
    var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath });
 | 
					 | 
				
			||||||
    //var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath });
 | 
					 | 
				
			||||||
    var leChallengeDdns = require('le-challenge-ddns').create({ ttl: 1 });
 | 
					 | 
				
			||||||
    var lex = require('greenlock-express').create({
 | 
					 | 
				
			||||||
      // set to https://acme-v01.api.letsencrypt.org/directory in production
 | 
					 | 
				
			||||||
      server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // If you wish to replace the default plugins, you may do so here
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    , challenges: {
 | 
					 | 
				
			||||||
        'http-01': leChallengeFs
 | 
					 | 
				
			||||||
      , 'tls-sni-01': leChallengeFs // leChallengeSni
 | 
					 | 
				
			||||||
      , 'dns-01': leChallengeDdns
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    , challengeType: (opts.tunnel ? 'http-01' : 'dns-01')
 | 
					 | 
				
			||||||
    , store: require('le-store-certbot').create({
 | 
					 | 
				
			||||||
        webrootPath: webrootPath
 | 
					 | 
				
			||||||
      , configDir: path.join((opts.homedir || '~'), 'letsencrypt', 'etc')
 | 
					 | 
				
			||||||
      , homedir: opts.homedir
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    , webrootPath: webrootPath
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // You probably wouldn't need to replace the default sni handler
 | 
					 | 
				
			||||||
    // See https://git.daplie.com/Daplie/le-sni-auto if you think you do
 | 
					 | 
				
			||||||
    //, sni: require('le-sni-auto').create({})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    , approveDomains: approveDomains
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var secureContexts = {
 | 
					    addresses.sort(function (a, b) {
 | 
				
			||||||
      'localhost.daplie.me': null
 | 
					      if (a.family !== b.family) {
 | 
				
			||||||
    };
 | 
					        return 'IPv4' === a.family ? 1 : -1;
 | 
				
			||||||
    opts.httpsOptions.SNICallback = function (sni, cb ) {
 | 
					 | 
				
			||||||
      var tlsOptions;
 | 
					 | 
				
			||||||
      console.log('[https] sni', sni);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Static Certs
 | 
					 | 
				
			||||||
      if (/.*localhost.*\.daplie\.me/.test(sni.toLowerCase())) {
 | 
					 | 
				
			||||||
        // TODO implement
 | 
					 | 
				
			||||||
        if (!secureContexts[sni]) {
 | 
					 | 
				
			||||||
          tlsOptions = require('localhost.daplie.me-certificates').mergeTlsOptions(sni, {});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (tlsOptions) {
 | 
					 | 
				
			||||||
          secureContexts[sni] = tls.createSecureContext(tlsOptions);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        cb(null, secureContexts[sni]);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Dynamic Certs
 | 
					      return a.address > b.address ? 1 : -1;
 | 
				
			||||||
      lex.httpsOptions.SNICallback(sni, cb);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    server = https.createServer(opts.httpsOptions);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    server.on('error', function (err) {
 | 
					 | 
				
			||||||
      if (opts.errorPort || opts.manualPort) {
 | 
					 | 
				
			||||||
        showError(err, port);
 | 
					 | 
				
			||||||
        process.exit(1);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      opts.errorPort = err.toString();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return createServer(portFallback, null, content, opts).then(resolve);
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    server.listen(port, function () {
 | 
					    addresses.forEach(function (addr) {
 | 
				
			||||||
      opts.port = port;
 | 
					      addr.range = ipaddr.parse(addr.address).range();
 | 
				
			||||||
      opts.redirectOptions.port = port;
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (opts.livereload) {
 | 
					    var Oauth3 = require('oauth3-cli');
 | 
				
			||||||
        opts.lrPort = opts.lrPort || lrPort;
 | 
					    var oauth3 = Oauth3.create({ device: { hostname: opts.device } });
 | 
				
			||||||
        var livereload = require('livereload');
 | 
					    return Oauth3.Devices.one(oauth3).then(function (device) {
 | 
				
			||||||
        var server2 = livereload.createServer({
 | 
					      return Oauth3.Devices.all(oauth3).then(function (devices) {
 | 
				
			||||||
          https: opts.httpsOptions
 | 
					        return { devices: devices, device: device.device || device };
 | 
				
			||||||
        , port: opts.lrPort
 | 
					      });
 | 
				
			||||||
        , exclusions: [ 'node_modules' ]
 | 
					    }).then(function (devices) {
 | 
				
			||||||
 | 
					      devices.device.secret = undefined;
 | 
				
			||||||
 | 
					      console.log('devices');
 | 
				
			||||||
 | 
					      console.log(devices);
 | 
				
			||||||
 | 
					      var directive = {
 | 
				
			||||||
 | 
					        global: opts.global
 | 
				
			||||||
 | 
					      , sites: opts.sites
 | 
				
			||||||
 | 
					      , defaults: opts.defaults
 | 
				
			||||||
 | 
					      , cwd: process.cwd()
 | 
				
			||||||
 | 
					      , ifaces: opts.ifaces
 | 
				
			||||||
 | 
					      , addresses: addresses
 | 
				
			||||||
 | 
					      , devices: devices.devices
 | 
				
			||||||
 | 
					      , device: devices.device
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      var server;
 | 
				
			||||||
 | 
					      var insecureServer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      function resolve() {
 | 
				
			||||||
 | 
					        realResolve({
 | 
				
			||||||
 | 
					          plainServer: insecureServer
 | 
				
			||||||
 | 
					        , server: server
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        console.info("[livereload] watching " + opts.pubdir);
 | 
					 | 
				
			||||||
        console.warn("WARNING: If CPU usage spikes to 100% it's because too many files are being watched");
 | 
					 | 
				
			||||||
        // TODO create map of directories to watch from opts.sites and iterate over it
 | 
					 | 
				
			||||||
        server2.watch(opts.pubdir);
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // if we haven't disabled insecure port
 | 
					      // returns an instance of node-letsencrypt with additional helper methods
 | 
				
			||||||
      if ('false' !== opts.insecurePort) {
 | 
					      var webrootPath = require('os').tmpdir();
 | 
				
			||||||
        // and both ports are the default
 | 
					      var leChallengeFs = require('le-challenge-fs').create({ webrootPath: webrootPath });
 | 
				
			||||||
        if ((httpsPort === opts.port && httpPort === opts.insecurePort)
 | 
					      //var leChallengeSni = require('le-challenge-sni').create({ webrootPath: webrootPath });
 | 
				
			||||||
          // or other case
 | 
					      var leChallengeDdns = require('le-challenge-ddns').create({ ttl: 1 });
 | 
				
			||||||
          || (httpPort !== opts.insecurePort && opts.port !== opts.insecurePort)
 | 
					      var lex = require('greenlock-express').create({
 | 
				
			||||||
        ) {
 | 
					        // set to https://acme-v01.api.letsencrypt.org/directory in production
 | 
				
			||||||
          return createInsecureServer(opts.insecurePort, null, opts).then(function (_server) {
 | 
					        server: opts.debug ? 'staging' : 'https://acme-v01.api.letsencrypt.org/directory'
 | 
				
			||||||
            insecureServer = _server;
 | 
					
 | 
				
			||||||
            resolve();
 | 
					      // If you wish to replace the default plugins, you may do so here
 | 
				
			||||||
          });
 | 
					      //
 | 
				
			||||||
 | 
					      , challenges: {
 | 
				
			||||||
 | 
					          'http-01': leChallengeFs
 | 
				
			||||||
 | 
					        , 'tls-sni-01': leChallengeFs // leChallengeSni
 | 
				
			||||||
 | 
					        , 'dns-01': leChallengeDdns
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      , challengeType: (opts.tunnel ? 'http-01' : 'dns-01')
 | 
				
			||||||
 | 
					      , store: require('le-store-certbot').create({
 | 
				
			||||||
 | 
					          webrootPath: webrootPath
 | 
				
			||||||
 | 
					        , configDir: path.join((opts.homedir || '~'), 'letsencrypt', 'etc')
 | 
				
			||||||
 | 
					        , homedir: opts.homedir
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      , webrootPath: webrootPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      opts.insecurePort = opts.port;
 | 
					      // You probably wouldn't need to replace the default sni handler
 | 
				
			||||||
      resolve();
 | 
					      // See https://git.daplie.com/Daplie/le-sni-auto if you think you do
 | 
				
			||||||
      return;
 | 
					      //, sni: require('le-sni-auto').create({})
 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ('function' === typeof app) {
 | 
					      , approveDomains: approveDomains
 | 
				
			||||||
      app = app(directive);
 | 
					      });
 | 
				
			||||||
    } else if ('function' === typeof app.create) {
 | 
					 | 
				
			||||||
      app = app.create(directive);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    server.on('request', function (req, res) {
 | 
					      var secureContexts = {
 | 
				
			||||||
      console.log('[' + req.method + '] ' + req.url);
 | 
					        'localhost.daplie.me': null
 | 
				
			||||||
      if (!req.socket.encrypted && !/\/\.well-known\/acme-challenge\//.test(req.url)) {
 | 
					      };
 | 
				
			||||||
        opts.redirectApp(req, res);
 | 
					      opts.httpsOptions.SNICallback = function (sni, cb ) {
 | 
				
			||||||
 | 
					        var tlsOptions;
 | 
				
			||||||
 | 
					        console.log('[https] sni', sni);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Static Certs
 | 
				
			||||||
 | 
					        if (/.*localhost.*\.daplie\.me/.test(sni.toLowerCase())) {
 | 
				
			||||||
 | 
					          // TODO implement
 | 
				
			||||||
 | 
					          if (!secureContexts[sni]) {
 | 
				
			||||||
 | 
					            tlsOptions = require('localhost.daplie.me-certificates').mergeTlsOptions(sni, {});
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (tlsOptions) {
 | 
				
			||||||
 | 
					            secureContexts[sni] = tls.createSecureContext(tlsOptions);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          cb(null, secureContexts[sni]);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Dynamic Certs
 | 
				
			||||||
 | 
					        lex.httpsOptions.SNICallback(sni, cb);
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      server = https.createServer(opts.httpsOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      server.on('error', function (err) {
 | 
				
			||||||
 | 
					        if (opts.errorPort || opts.manualPort) {
 | 
				
			||||||
 | 
					          showError(err, port);
 | 
				
			||||||
 | 
					          process.exit(1);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        opts.errorPort = err.toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return createServer(portFallback, null, content, opts).then(resolve);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      server.listen(port, function () {
 | 
				
			||||||
 | 
					        opts.port = port;
 | 
				
			||||||
 | 
					        opts.redirectOptions.port = port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (opts.livereload) {
 | 
				
			||||||
 | 
					          opts.lrPort = opts.lrPort || lrPort;
 | 
				
			||||||
 | 
					          var livereload = require('livereload');
 | 
				
			||||||
 | 
					          var server2 = livereload.createServer({
 | 
				
			||||||
 | 
					            https: opts.httpsOptions
 | 
				
			||||||
 | 
					          , port: opts.lrPort
 | 
				
			||||||
 | 
					          , exclusions: [ 'node_modules' ]
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          console.info("[livereload] watching " + opts.pubdir);
 | 
				
			||||||
 | 
					          console.warn("WARNING: If CPU usage spikes to 100% it's because too many files are being watched");
 | 
				
			||||||
 | 
					          // TODO create map of directories to watch from opts.sites and iterate over it
 | 
				
			||||||
 | 
					          server2.watch(opts.pubdir);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if we haven't disabled insecure port
 | 
				
			||||||
 | 
					        if ('false' !== opts.insecurePort) {
 | 
				
			||||||
 | 
					          // and both ports are the default
 | 
				
			||||||
 | 
					          if ((httpsPort === opts.port && httpPort === opts.insecurePort)
 | 
				
			||||||
 | 
					            // or other case
 | 
				
			||||||
 | 
					            || (httpPort !== opts.insecurePort && opts.port !== opts.insecurePort)
 | 
				
			||||||
 | 
					          ) {
 | 
				
			||||||
 | 
					            return createInsecureServer(opts.insecurePort, null, opts).then(function (_server) {
 | 
				
			||||||
 | 
					              insecureServer = _server;
 | 
				
			||||||
 | 
					              resolve();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        opts.insecurePort = opts.port;
 | 
				
			||||||
 | 
					        resolve();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if ('function' === typeof app) {
 | 
					      if ('function' === typeof app) {
 | 
				
			||||||
        app(req, res);
 | 
					        app = app(directive);
 | 
				
			||||||
        return;
 | 
					      } else if ('function' === typeof app.create) {
 | 
				
			||||||
 | 
					        app = app.create(directive);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      res.end('not ready');
 | 
					      server.on('request', function (req, res) {
 | 
				
			||||||
    });
 | 
					        console.log('[' + req.method + '] ' + req.url);
 | 
				
			||||||
 | 
					        if (!req.socket.encrypted && !/\/\.well-known\/acme-challenge\//.test(req.url)) {
 | 
				
			||||||
 | 
					          opts.redirectApp(req, res);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return PromiseA.resolve(app).then(function (_app) {
 | 
					        if ('function' === typeof app) {
 | 
				
			||||||
      app = _app;
 | 
					          app(req, res);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res.end('not ready');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return PromiseA.resolve(app).then(function (_app) {
 | 
				
			||||||
 | 
					        app = _app;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,7 @@
 | 
				
			|||||||
    "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
 | 
					    "greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
 | 
				
			||||||
    "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master",
 | 
					    "greenlock-express": "git+https://git.daplie.com/Daplie/greenlock-express.git#master",
 | 
				
			||||||
    "httpolyglot": "^0.1.1",
 | 
					    "httpolyglot": "^0.1.1",
 | 
				
			||||||
 | 
					    "ipaddr.js": "git+https://github.com/whitequark/ipaddr.js.git#v1.3.0",
 | 
				
			||||||
    "ipify": "^1.1.0",
 | 
					    "ipify": "^1.1.0",
 | 
				
			||||||
    "js-yaml": "^3.8.1",
 | 
					    "js-yaml": "^3.8.1",
 | 
				
			||||||
    "le-challenge-ddns": "git+https://git.daplie.com/Daplie/le-challenge-ddns.git#master",
 | 
					    "le-challenge-ddns": "git+https://git.daplie.com/Daplie/le-challenge-ddns.git#master",
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1 @@
 | 
				
			|||||||
Subproject commit 356a2d3131bcc6d0f6199a1d2039dcdcee0e3481
 | 
					Subproject commit d64699977e883871246d3fc062a384e88a554e2a
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user