').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(t).addClass(this.options.style);this.$element.wrap(l),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:e,$toggleOff:s,$toggleGroup:i}),this.$toggle.append(i);var n=this.options.width||Math.max(e.outerWidth(),s.outerWidth())+o.outerWidth()/2,h=this.options.height||Math.max(e.outerHeight(),s.outerHeight());e.addClass("toggle-on"),s.addClass("toggle-off"),this.$toggle.css({width:n,height:h}),this.options.height&&(e.css("line-height",e.height()+"px"),s.css("line-height",s.height()+"px")),this.update(!0),this.trigger(!0)},l.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},l.prototype.on=function(t){if(this.$element.prop("disabled"))return!1;this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),t||this.trigger()},l.prototype.off=function(t){if(this.$element.prop("disabled"))return!1;this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),t||this.trigger()},l.prototype.enable=function(){this.$toggle.removeClass("disabled"),this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},l.prototype.disable=function(){this.$toggle.addClass("disabled"),this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},l.prototype.update=function(t){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(t):this.off(t)},l.prototype.trigger=function(t){this.$element.off("change.bs.toggle"),t||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},l.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var t=a.fn.bootstrapToggle;a.fn.bootstrapToggle=function(o){var i=Array.prototype.slice.call(arguments,1)[0];return this.each(function(){var t=a(this),e=t.data("bs.toggle"),s="object"==typeof o&&o;e||t.data("bs.toggle",e=new l(this,s)),"string"==typeof o&&e[o]&&"boolean"==typeof i?e[o](i):"string"==typeof o&&e[o]&&e[o]()})},a.fn.bootstrapToggle.Constructor=l,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=t,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(t){a(this).find("input[type=checkbox]").bootstrapToggle("toggle"),t.preventDefault()})}(jQuery);
+//# sourceMappingURL=bootstrap4-toggle.min.js.map
\ No newline at end of file
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..45f7147
--- /dev/null
+++ b/server.js
@@ -0,0 +1,110 @@
+var express = require('express');
+var passport = require('passport');
+var Strategy = require('passport-local').Strategy;
+var db = require('./db');
+
+
+// Configure the local strategy for use by Passport.
+//
+// The local strategy require a `verify` function which receives the credentials
+// (`username` and `password`) submitted by the user. The function must verify
+// that the password is correct and then invoke `cb` with a user object, which
+// will be set at `req.user` in route handlers after authentication.
+passport.use(new Strategy({
+ passReqToCallback: true},
+ function(username, password, cb) {
+ console.log('requesting authentication for user '+ username);
+ db.users.findByUsername(username, function(err, user) {
+ if (err) { return cb(err); }
+ if (!user) { return cb(null, false); }
+ if (user.password != password) { return cb(null, false); }
+ return cb(null, user);
+ });
+ }));
+
+
+// Configure Passport authenticated session persistence.
+//
+// In order to restore authentication state across HTTP requests, Passport needs
+// to serialize users into and deserialize users out of the session. The
+// typical implementation of this is as simple as supplying the user ID when
+// serializing, and querying the user record by ID from the database when
+// deserializing.
+passport.serializeUser(function(user, cb) {
+ cb(null, user.id);
+});
+
+passport.deserializeUser(function(id, cb) {
+ db.users.findById(id, function (err, user) {
+ if (err) { return cb(err); }
+ cb(null, user);
+ });
+});
+
+
+
+
+// Create a new Express application.
+var app = express();
+
+// Configure view engine to render EJS templates.
+//app.set('views', __dirname + '/views');
+//app.set('view engine', 'ejs');
+app.set('view engine', 'vash');
+app.use(express.static('public'))
+
+// Use application-level middleware for common functionality, including
+// logging, parsing, and session handling.
+app.use(require('morgan')('combined'));
+app.use(require('body-parser').urlencoded({ extended: true }));
+app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
+
+// Initialize Passport and restore authentication state, if any, from the
+// session.
+app.use(passport.initialize());
+app.use(passport.session());
+
+// Define routes.
+app.get('/',
+ function(req, res) {
+ res.render('layout', { user: req.user });
+ });
+
+app.get('/login',
+ function(req, res){
+ res.render('login');
+ });
+
+app.post('/login',
+ passport.authenticate('local', { failureRedirect: '/n/login' }),
+ function(req, res) {
+ res.redirect('/n/');
+ });
+
+app.get('/logout',
+ function(req, res){
+ req.logout();
+ res.redirect('/n/');
+ });
+
+app.get('/accontrol',
+ // passport.authenticate('local', {
+ // failureRedirect: '/n/login' ,
+ // successRedirect: '/n/accontrol'}),
+ require('connect-ensure-login').ensureLoggedIn('/n/login'),
+ function(req, res){
+ res.render('accontrol', { user: req.user });
+ });
+
+//app.listen(81);
+
+var fs = require("fs");
+var https = require('https');
+var privateKey = fs.readFileSync('/etc/letsencrypt/live/iot.d-popov.com/privkey.pem', 'utf8');
+var certificate = fs.readFileSync('/etc/letsencrypt/live/iot.d-popov.com/cert.pem', 'utf8');
+var credentials = {key: privateKey, cert: certificate};
+
+var httpsServer = https.createServer(credentials, app);
+httpsServer.listen(8443, () => {
+ console.log('HTTP server listening on port 8443');
+});
diff --git a/views/accontrol.ejs b/views/accontrol.ejs
new file mode 100644
index 0000000..b15a002
--- /dev/null
+++ b/views/accontrol.ejs
@@ -0,0 +1,20 @@
+
AC Control for <%= model.user.username %>
+
+INFO:
+<%= model.info %>
\ No newline at end of file
diff --git a/views/chart.ejs b/views/chart.ejs
new file mode 100644
index 0000000..fdc88ec
--- /dev/null
+++ b/views/chart.ejs
@@ -0,0 +1,128 @@
+
+
+
+
+<%- contentFor('head') %>
+
+
diff --git a/views/layout.ejs b/views/layout.ejs
new file mode 100644
index 0000000..1fc8244
--- /dev/null
+++ b/views/layout.ejs
@@ -0,0 +1,28 @@
+
+
+
+
+
+
ESP8266 Weather Server
+
+
+
+ <%- defineContent("head") %>
+
+
+ <%- include('nav'); -%>
+
+ <%- body %>
+
+
+
+
+
+
+ <%- defineContent("scripts") %>
+
+
\ No newline at end of file
diff --git a/views/login.ejs b/views/login.ejs
new file mode 100644
index 0000000..54f53fe
--- /dev/null
+++ b/views/login.ejs
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/views/nav.ejs b/views/nav.ejs
new file mode 100644
index 0000000..bb406e1
--- /dev/null
+++ b/views/nav.ejs
@@ -0,0 +1,4 @@
+
+
control
+
log out
+
chart
\ No newline at end of file