Browse Source

Forward to password change page if default password

fastled
Xose Pérez 8 years ago
parent
commit
0f5a0e8f75
11 changed files with 189 additions and 18 deletions
  1. BIN
      code/data/index.html.gz
  2. BIN
      code/data/password.html.gz
  3. BIN
      code/data/script.js.gz
  4. BIN
      code/data/style.css.gz
  5. +24
    -3
      code/gulpfile.js
  6. +34
    -1
      code/html/custom.js
  7. +29
    -5
      code/html/index.html
  8. +72
    -0
      code/html/password.html
  9. +4
    -1
      code/package.json
  10. +1
    -1
      code/pio_hooks.py
  11. +25
    -7
      code/src/web.ino

BIN
code/data/index.html.gz View File


BIN
code/data/password.html.gz View File


BIN
code/data/script.js.gz View File


BIN
code/data/style.css.gz View File


+ 24
- 3
code/gulpfile.js View File

@ -2,7 +2,7 @@
ESP8266 file system builder ESP8266 file system builder
Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
Copyright (C) 2016 by Xose PĆ©rez <xose dot perez at gmail dot com>
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -24,11 +24,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const gulp = require('gulp'); const gulp = require('gulp');
const plumber = require('gulp-plumber');
const htmlmin = require('gulp-htmlmin'); const htmlmin = require('gulp-htmlmin');
const cleancss = require('gulp-clean-css'); const cleancss = require('gulp-clean-css');
const uglify = require('gulp-uglify'); const uglify = require('gulp-uglify');
const gzip = require('gulp-gzip'); const gzip = require('gulp-gzip');
const del = require('del'); const del = require('del');
const useref = require('gulp-useref');
const gulpif = require('gulp-if');
const inline = require('gulp-inline'); const inline = require('gulp-inline');
/* Clean destination folder */ /* Clean destination folder */
@ -66,6 +69,24 @@ gulp.task('inline', function() {
.pipe(gulp.dest('data')); .pipe(gulp.dest('data'));
}) })
/* Process HTML, CSS, JS */
gulp.task('html', function() {
return gulp.src('html/*.html')
.pipe(useref())
.pipe(plumber())
.pipe(gulpif('*.css', cleancss()))
.pipe(gulpif('*.js', uglify()))
.pipe(gulpif('*.html', htmlmin({
collapseWhitespace: true,
removeComments: true,
minifyCSS: true,
minifyJS: true
})))
.pipe(gzip())
.pipe(gulp.dest('data'));
});
/* Build file system */ /* Build file system */
gulp.task('buildfs', ['clean', 'files', 'inline']);
gulp.task('default', ['buildfs']);
gulp.task('buildfs_split', ['clean', 'files', 'html']);
gulp.task('buildfs_inline', ['clean', 'files', 'inline']);
gulp.task('default', ['buildfs_inline']);

+ 34
- 1
code/html/custom.js View File

@ -1,4 +1,5 @@
var websock; var websock;
var password = false;
function doUpdate() { function doUpdate() {
var data = $("#formSave").serializeArray(); var data = $("#formSave").serializeArray();
@ -87,8 +88,11 @@ function processData(data) {
// title // title
if ("app" in data) { if ("app" in data) {
$(".pure-menu-heading").html(data.app);
var title = data.app; var title = data.app;
if ("version" in data) {
title = title + " " + data.version;
}
$(".pure-menu-heading").html(title);
if ("hostname" in data) { if ("hostname" in data) {
title = data.hostname + " - " + title; title = data.hostname + " - " + title;
} }
@ -97,6 +101,35 @@ function processData(data) {
Object.keys(data).forEach(function(key) { Object.keys(data).forEach(function(key) {
// Actions
if (key == "action") {
if (data.action == "reload") {
if (password) {
// Forget current authentication
$.ajax({
'method': 'GET',
'url': '/',
'async': false,
'username': "logmeout",
'password': "123456",
'headers': { "Authorization": "Basic xxx" }
}).done(function(data) {
// If we don't get an error, we actually got an error as we expect an 401!
}).fail(function(){
// We expect to get an 401 Unauthorized error! In this case we are successfully
// logged out and we redirect the user.
window.location = "/";
});
}
}
return;
}
// Wifi // Wifi
if (key == "wifi") { if (key == "wifi") {
var groups = $("#panel-wifi .pure-g"); var groups = $("#panel-wifi .pure-g");


+ 29
- 5
code/html/index.html View File

@ -40,6 +40,10 @@
<a href="#" class="pure-menu-link" data="panel-general">GENERAL</a> <a href="#" class="pure-menu-link" data="panel-general">GENERAL</a>
</li> </li>
<li class="pure-menu-item">
<a href="#" class="pure-menu-link" data="panel-security">SECURITY</a>
</li>
<li class="pure-menu-item"> <li class="pure-menu-item">
<a href="#" class="pure-menu-link" data="panel-wifi">WIFI</a> <a href="#" class="pure-menu-link" data="panel-wifi">WIFI</a>
</li> </li>
@ -196,16 +200,36 @@
<div class="pure-u-1 pure-u-md-3-4 hint">Define how the different relays should be synchronized.</div> <div class="pure-u-1 pure-u-md-3-4 hint">Define how the different relays should be synchronized.</div>
</div> </div>
<div class="pure-g module module-fauxmo">
<div class="pure-u-1 pure-u-sm-1-4"><label for="fauxmoEnabled">Enable WeMo emulation</label></div>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" name="fauxmoEnabled" /></div>
</div>
</fieldset>
</div>
</div>
<div class="panel" id="panel-security">
<div class="header">
<h1>SECURITY</h1>
<h2>Device security settings</h2>
</div>
<div class="page">
<fieldset>
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="adminPass">Admin password</label>
<input name="adminPass" class="pure-u-1 pure-u-md-3-4" type="text" tabindex="3" />
<label class="pure-u-1 pure-u-md-1-4" for="adminPass1">Admin password</label>
<input name="adminPass1" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="3" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div> <div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).</div> <div class="pure-u-1 pure-u-md-3-4 hint">The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).</div>
</div> </div>
<div class="pure-g module module-fauxmo">
<div class="pure-u-1 pure-u-sm-1-4"><label for="fauxmoEnabled">Enable WeMo emulation</label></div>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" name="fauxmoEnabled" /></div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="adminPass2">Admin password (repeat)</label>
<input name="adminPass2" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="3" />
</div> </div>
<div class="pure-g"> <div class="pure-g">


+ 72
- 0
code/html/password.html View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<title>ESPurna 0.0.0</title>
<meta charset="utf-8" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- build:css style.css -->
<link rel="stylesheet" href="pure-min.css" />
<link rel="stylesheet" href="side-menu.css" />
<link rel="stylesheet" href="grids-responsive-min.css" />
<link rel="stylesheet" href="checkboxes.css" />
<link rel="stylesheet" href="custom.css" />
<!-- endbuild -->
</head>
<body>
<div id="layout">
<div class="content">
<form id="formSave" class="pure-form" action="/" method="post">
<div class="panel" style="display: block;">
<div class="header">
<h1>SECURITY</h1>
<h2>Before using this device you have to change the default password for the user 'admin'. This password will be used for the <strong>AP mode hotspot</strong>, the <strong>web interface</strong> (where you are now) and the <strong>over-the-air updates</strong>.</h2>
</div>
<div class="page">
<fieldset>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="adminPass1">Admin password</label>
<input name="adminPass1" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="1" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="adminPass2">Admin password (repeat)</label>
<input name="adminPass2" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="2" />
</div>
<button class="pure-button button-update">Update</button>
</fieldset>
</div>
</div>
</form>
</div> <!-- content -->
</div> <!-- layout -->
</body>
<!-- build:js script.js -->
<script src="jquery-1.12.3.min.js"></script>
<script src="checkboxes.js"></script>
<script src="custom.js"></script>
<!-- endbuild -->
<script>
password = true;
</script>
</html>

+ 4
- 1
code/package.json View File

@ -11,8 +11,11 @@
"gulp-clean-css": "^2.0.10", "gulp-clean-css": "^2.0.10",
"gulp-gzip": "^1.4.0", "gulp-gzip": "^1.4.0",
"gulp-htmlmin": "^2.0.0", "gulp-htmlmin": "^2.0.0",
"gulp-if": "^2.0.1",
"gulp-inline": "^0.1.1", "gulp-inline": "^0.1.1",
"gulp-uglify": "^1.5.3"
"gulp-plumber": "^1.1.0",
"gulp-uglify": "^1.5.3",
"gulp-useref": "^3.1.2"
}, },
"dependencies": {} "dependencies": {}
} }

+ 1
- 1
code/pio_hooks.py View File

@ -13,7 +13,7 @@ def is_valid_ip(ip):
return False return False
def before_build_spiffs(source, target, env): def before_build_spiffs(source, target, env):
env.Execute("gulp buildfs")
env.Execute("gulp buildfs_split")
def before_upload(source, target, env): def before_upload(source, target, env):
upload_port = env.get('UPLOAD_PORT', False) upload_port = env.get('UPLOAD_PORT', False)


+ 25
- 7
code/src/web.ino View File

@ -94,6 +94,7 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
bool fauxmoEnabled = false; bool fauxmoEnabled = false;
#endif #endif
unsigned int network = 0; unsigned int network = 0;
String adminPass;
for (unsigned int i=0; i<config.size(); i++) { for (unsigned int i=0; i<config.size(); i++) {
@ -109,9 +110,19 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
#endif #endif
// Do not change the password if empty
if (key == "adminPass") {
// Check password
if (key == "adminPass1") {
adminPass = value;
continue;
}
if (key == "adminPass2") {
if (!value.equals(adminPass)) {
ws.text(client_id, "{\"message\": \"Passwords do not match!\"}");
return;
}
if (value.length() == 0) continue; if (value.length() == 0) continue;
ws.text(client_id, "{\"action\": \"reload\"}");
key = String("adminPass");
} }
// Checkboxes // Checkboxes
@ -192,16 +203,17 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
void _wsStart(uint32_t client_id) { void _wsStart(uint32_t client_id) {
char app[64];
sprintf(app, "%s %s", APP_NAME, APP_VERSION);
char chipid[6]; char chipid[6];
sprintf(chipid, "%06X", ESP.getChipId()); sprintf(chipid, "%06X", ESP.getChipId());
DynamicJsonBuffer jsonBuffer; DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject(); JsonObject& root = jsonBuffer.createObject();
root["app"] = app;
root["app"] = APP_NAME;
root["version"] = APP_VERSION;
root["buildDate"] = __DATE__;
root["buildTime"] = __TIME__;
root["manufacturer"] = String(MANUFACTURER); root["manufacturer"] = String(MANUFACTURER);
root["chipid"] = chipid; root["chipid"] = chipid;
root["mac"] = WiFi.macAddress(); root["mac"] = WiFi.macAddress();
@ -365,7 +377,13 @@ void _onHome(AsyncWebServerRequest *request) {
if (!_authenticate(request)) return request->requestAuthentication(); if (!_authenticate(request)) return request->requestAuthentication();
request->send(SPIFFS, "/index.html");
String password = getSetting("adminPass", ADMIN_PASS);
if (password.equals(ADMIN_PASS)) {
request->send(SPIFFS, "/password.html");
} else {
request->send(SPIFFS, "/index.html");
}
} }
bool _apiAuth(AsyncWebServerRequest *request) { bool _apiAuth(AsyncWebServerRequest *request) {


Loading…
Cancel
Save