a special treat
This commit is contained in:
		
							parent
							
								
									7a208b0308
								
							
						
					
					
						commit
						8ccd89ddfd
					
				
							
								
								
									
										222
									
								
								bin/lex.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										222
									
								
								bin/lex.js
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,222 @@ | ||||
| #!/usr/bin/env node
 | ||||
| 'use strict'; | ||||
| 
 | ||||
| var fs = require('fs'); | ||||
| var path = require('path'); | ||||
| var mkdirp = require('fs'); | ||||
| var cli = require('cli'); | ||||
| var mkdirp = require('mkdirp'); | ||||
| var homedir = require('os').homedir(); | ||||
| var configDir = path.join(homedir, 'letsencrypt'); | ||||
| var desktop = path.join(homedir, 'Desktop'); | ||||
| var vhostDir = path.join(fs.existsSync(desktop) ? desktop : configDir, 'www'); | ||||
| var welcomeHtml = fs.readFileSync(path.join(__dirname, '..', 'lib', 'public', 'welcome.html'), 'utf8'); | ||||
| var express = require('express'); | ||||
| 
 | ||||
| cli.parse({ | ||||
|   'agree-tos': [ false, " Agree to the Let's Encrypt Subscriber Agreement", 'boolean', false ] | ||||
| , email: [ false, " Email used for registration and recovery contact. (default: null)", 'email' ] | ||||
| , domains: [ false, " Domain names to apply. To include the www domain with your main domain your can enter both with a comma. Ex --domains example.com,www.example.com (default: [])", 'string' ] | ||||
| , debug: [ false, " show traces and logs", 'boolean', false ] | ||||
| , server: [ false, " ACME Directory Resource URI.", 'string', 'https://acme-v01.api.letsencrypt.org/directory)' ] | ||||
| }); | ||||
| 
 | ||||
| // ignore certonly and extraneous arguments
 | ||||
| cli.main(function(_, options) { | ||||
|   console.log(''); | ||||
|   var args = {}; | ||||
| 
 | ||||
|   Object.keys(options).forEach(function (key) { | ||||
|     var val = options[key]; | ||||
| 
 | ||||
|     if ('string' === typeof val) { | ||||
|       val = val.replace(/^~/, homedir); | ||||
|     } | ||||
| 
 | ||||
|     key = key.replace(/\-([a-z0-9A-Z])/g, function (c) { return c[1].toUpperCase(); }); | ||||
|     args[key] = val; | ||||
|   }); | ||||
| 
 | ||||
|   if (args.domains) { | ||||
|     args.domains = args.domains.split(','); | ||||
|   } | ||||
| 
 | ||||
|   makeDirectories(); | ||||
| 
 | ||||
|   function makeDirectories() { | ||||
|     mkdirp(configDir, function (err) { | ||||
|       if (err) { | ||||
|         console.error("Could not create config directory '" + configDir + "':", err.code); | ||||
|         console.error(err.stack); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       mkdirp(vhostDir, function (err) { | ||||
|         if (err) { | ||||
|           console.error("Could not create vhost directory '" + vhostDir + "':", err.code); | ||||
|           console.error(err.stack); | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         startServers(); | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function configure(le, args, cb) { | ||||
|     var vhost; | ||||
|     var pubDir; | ||||
|     var index; | ||||
| 
 | ||||
|     if (!(args.email && args.agreeTos && args.server && args.domains)) { | ||||
|       cb({ error : { message: "missing one or more of agreeTos,domains,email,server" } }); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     vhost = args.domains[0]; | ||||
|     pubDir = path.join(vhostDir, vhost); | ||||
|     index = path.join(pubDir, 'index.html'); | ||||
| 
 | ||||
|     makeLandingPage(); | ||||
| 
 | ||||
|     function makeLandingPage() { | ||||
|       mkdirp(pubDir, function (err) { | ||||
|         if (err) { | ||||
|           cb(err); | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         fs.exists(index, function (exists) { | ||||
|           if (exists) { | ||||
|             configureForHttps(); | ||||
|             return; | ||||
|           } | ||||
| 
 | ||||
|           fs.writeFile(path.join(pubDir, 'index.html'), welcomeHtml.replace(/:hostname/g, vhost), 'utf8', function (err) { | ||||
|             if (err) { | ||||
|               cb(err); | ||||
|               return; | ||||
|             } | ||||
| 
 | ||||
|             configureForHttps(); | ||||
|           }); | ||||
|         }); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     function configureForHttps() { | ||||
|       le.setConfig(args, cb); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   function createConfigurator(le) { | ||||
|     var app = express(); | ||||
| 
 | ||||
|     app.use('/', express.static(path.join(__dirname, '..', 'lib', 'configurator'))); | ||||
| 
 | ||||
|     app.use(require('body-parser').json()); | ||||
| 
 | ||||
|     app.get('/api/com.daplie.lex/sites', function (req, res, next) { | ||||
|       le.getConfigs({ configDir: configDir }, function (err, configs) { | ||||
|         if (err) { | ||||
|           next(err); | ||||
|           return; | ||||
|         } | ||||
|         res.send(configs); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     app.post('/api/com.daplie.lex/sites', function (req, res, next) { | ||||
|       var data = req.body; | ||||
| 
 | ||||
|       configure(le, data, function (err, configs) { | ||||
|         if (err) { | ||||
|           console.error(err.stack); | ||||
|           next(err); | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         res.send(configs); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     return app; | ||||
|   } | ||||
| 
 | ||||
|   function startServers() { | ||||
|     // Note: using staging server url, remove .testing() for production
 | ||||
|     var LE = require('letsencrypt'); | ||||
|     var challengeStore = require('../lib/challenge-handlers'); | ||||
|     var le = LE.create({ | ||||
|       configDir: configDir | ||||
|     , manual: true | ||||
| 
 | ||||
|     , privkeyPath: LE.privkeyPath | ||||
|     , fullchainPath: LE.fullchainPath | ||||
|     , certPath: LE.certPath | ||||
|     , chainPath: LE.chainPath | ||||
|     }, { | ||||
|       setChallenge: challengeStore.set | ||||
|     , removeChallenge: challengeStore.remove | ||||
|     }); | ||||
|     var lex = require('../'); | ||||
|     var app = express(); | ||||
|     var vhosts = {}; | ||||
| 
 | ||||
|     vhosts['localhost.daplie.com'] = createConfigurator(le, vhosts); | ||||
| 
 | ||||
|     app.use('/', function (req, res, next) { | ||||
|       var hostname = req.hostname.replace(/^www\./, ''); | ||||
|       var pubDir = path.join(vhostDir, hostname); | ||||
| 
 | ||||
|       if (vhosts[hostname]) { | ||||
|         vhosts[hostname](req, res, next); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       fs.exists(pubDir, function (exists) { | ||||
|         if (exists) { | ||||
|           vhosts[hostname] = express().use('/', express.static(pubDir)); | ||||
|           vhosts[hostname](req, res, next); | ||||
|         } else { | ||||
|           vhosts['localhost.daplie.com'](req, res, next); | ||||
|         } | ||||
|       }); | ||||
|     }); | ||||
|     app.use('/', express.static(path.join(__dirname, '..', 'lib', 'public'))); | ||||
| 
 | ||||
|     lex.create({ | ||||
|       onRequest: app | ||||
|     , configDir: configDir | ||||
|     , letsencrypt: le | ||||
|     , approveRegistration: function (domain, cb) { | ||||
|         le.getConfig({ domains: [domain] }, function (err, config) { | ||||
|           if (!(config && config.checkpoints >= 0)) { | ||||
|             cb(null, null); | ||||
|             return; | ||||
|           } | ||||
| 
 | ||||
|           cb(null, { | ||||
|             email: config.email | ||||
|                 // can't remember which it is, but the pyconf is different that the regular variable
 | ||||
|           , agreeTos: config.tos || config.agree || config.agreeTos | ||||
|           , server: config.server || LE.productionServerUrl | ||||
|           , domains: config.domains || [domain] | ||||
|           }); | ||||
|         }); | ||||
|       } | ||||
|     }).listen([80], [443, 5001], function () { | ||||
|       console.log("ENCRYPT __ALL__ THE DOMAINS!"); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /* | ||||
|       // should get back account, path to certs, pems, etc?
 | ||||
|       console.log('\nCertificates installed at:'); | ||||
|       console.log(Object.keys(results).filter(function (key) { | ||||
|         return /Path/.test(key); | ||||
|       }).map(function (key) { | ||||
|         return results[key]; | ||||
|       }).join('\n')); | ||||
|   */ | ||||
| }); | ||||
							
								
								
									
										41
									
								
								lib/configurator/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								lib/configurator/app.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| $(function () { | ||||
|   'use strict'; | ||||
| 
 | ||||
|   var tpl = $('.js-hostnames').html(); | ||||
|   $('.js-hostnames').html(''); | ||||
| 
 | ||||
|   $('body').on('submit', 'form.js-add-site', function (ev) { | ||||
|     ev.preventDefault(); | ||||
|     // I don't think this actually has any meaning when listening on body
 | ||||
|     ev.stopPropagation(); | ||||
| 
 | ||||
|     var data = { | ||||
|       email: $('.js-email').val() | ||||
|     , agreeTos: !!$('.js-agree-tos').prop('checked') | ||||
|     , server: $('.js-server').val() | ||||
|     , domains: $('.js-domains').val().split(/\s*,\s*/) | ||||
|     }; | ||||
| 
 | ||||
|     $.ajax({ | ||||
|       method: 'POST' | ||||
|     , url: '/api/com.daplie.lex/sites' | ||||
|     , data: JSON.stringify(data) | ||||
|     , headers: { 'Content-Type': 'application/json; charset=utf-8' } | ||||
|     }).then(function (data) { | ||||
|       console.log(data); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   $.ajax({ | ||||
|     method: 'GET' | ||||
|   , url: '/api/com.daplie.lex/sites' | ||||
|   }).then(function (data) { | ||||
|     var $hostnames = $('.js-hostnames'); | ||||
|     $hostnames.html(''); | ||||
|     data.forEach(function (config) { | ||||
|       var $conf = $(tpl); | ||||
|       $conf.text(config.domains); | ||||
|       $hostnames.append($conf); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										37
									
								
								lib/configurator/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								lib/configurator/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <title>Welcome to :hostname!</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | ||||
|     <meta http-equiv="Content-Security-Policy" content="default-src 'self';"> | ||||
|     <link rel="stylesheet" type="text/css" href="./bootstrap.css"> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div class="container"> | ||||
|       <div class="jumbotron"> | ||||
|         <h1>Add a Site</h1> | ||||
|         <form class="js-add-site"> | ||||
|           <label>Domain</label>: <input type="text" class="js-domains" placeholder="ex: example.com,www.example.com"> | ||||
|           <br/> | ||||
|           <label>Email</label>: <input type="email" class="js-email" placeholder="ex: user@example.com"> | ||||
|           <br/> | ||||
|           <label>LE Server</label>: <input type="text" class="js-server" placeholder="ex: https://acme-staging.api.letsencrypt.org/directory" value="https://acme-v01.api.letsencrypt.org/directory"> | ||||
|           <br/> | ||||
|           <label><input type="checkbox" class="js-agree-tos"> Agree to Let's Encrypt Terms of Service?</label> | ||||
|           <br/> | ||||
|           <button class="btn btn-primary" type="submit">Add Site</button> | ||||
|         </form> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <p>Sites: | ||||
|         <div class="js-hostnames-container"> | ||||
|           <ul class="js-hostnames"> | ||||
|             <li class="js-hostname"></li> | ||||
|           </ul> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <script src="./jquery.js"></script> | ||||
|     <script src="./app.js"></script> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										6961
									
								
								lib/public/bootstrap.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6961
									
								
								lib/public/bootstrap.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										9210
									
								
								lib/public/jquery.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9210
									
								
								lib/public/jquery.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								lib/public/welcome.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/public/welcome.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <title>Welcome to :hostname!</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | ||||
|     <meta http-equiv="Content-Security-Policy" content="default-src 'self';"> | ||||
|     <link rel="stylesheet" type="text/css" href="./bootstrap.css"> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div class="container"> | ||||
|       <div class="jumbotron"> | ||||
|         <h1>Hello, world!</h1> | ||||
|         <p>Your website is located in one of two places:</p> | ||||
|         <ul> | ||||
|           <li>on your <code>Desktop</code> inside of the <code>www</code> directory and <code>:hostname</code></li> | ||||
|           <li><code>~/www/:hostname</code> (your home folder, under <code>www/:hostname</code></li> | ||||
|         <ul> | ||||
|         <p>This very file is called <code>index.html</code>. | ||||
|         You can open it up in <code>notepad</code> and change it up a little if you'd like.</p> | ||||
|       </div> | ||||
|     </div> | ||||
|     <script src="./jquery.js"></script> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										22
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								package.json
									
									
									
									
									
								
							| @ -3,6 +3,16 @@ | ||||
|   "version": "1.0.2", | ||||
|   "description": "Free SSL and Automatic HTTPS for node.js with Express, Connect, and other middleware systems", | ||||
|   "main": "index.js", | ||||
|   "bin": { | ||||
|     "letsencrypt-express": "bin/lex.js", | ||||
|     "lex": "bin/lex.js" | ||||
|   }, | ||||
|   "files": [ | ||||
|     "lib/", | ||||
|     "bin/", | ||||
|     "examples/", | ||||
|     "index.js" | ||||
|   ], | ||||
|   "directories": { | ||||
|     "example": "examples" | ||||
|   }, | ||||
| @ -33,9 +43,15 @@ | ||||
|     "url": "https://github.com/Daplie/letsencrypt-express/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/Daplie/letsencrypt-express#readme", | ||||
|   "dependencies": { | ||||
|     "homedir": "^0.6.0", | ||||
|     "letsencrypt": "^1.3.0", | ||||
|   "devDependencies": { | ||||
|     "body-parser": "^1.14.2", | ||||
|     "cli": "^0.11.1", | ||||
|     "express": "^4.13.3", | ||||
|     "localhost.daplie.com-certificates": "^1.1.2", | ||||
|     "mkdirp": "^0.5.1" | ||||
|   } | ||||
|   "dependencies": { | ||||
|     "homedir": "^0.6.0", | ||||
|     "letsencrypt": "^1.3.0" | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user