login is (almost) fully working now

This commit is contained in:
dorian 2019-08-07 23:03:59 +02:00
parent 903f730502
commit eb8edc8d03
9 changed files with 241 additions and 84239 deletions

View file

@ -125,4 +125,40 @@ triggered by setting POST parameter 'submitSensorData' to a JSON encoded string
- data: Array[Array[sensorId, errorCode]] sensors which were ignored due to some error (401: user doesn't own sensor; 404: senso wasn't found) - data: Array[Array[sensorId, errorCode]] sensors which were ignored due to some error (401: user doesn't own sensor; 404: senso wasn't found)
only set if status is 901 only set if status is 901
## ## edit user data
- requests to change user specific data (like adding/removing sensors/api-keys, etc.)
- this type of request is triggered by setting GET parameter 'command' to a JSON encoded string containing the request
- request structure: (JSON object)
- header: (int) containing the desired command
- body: (mixed)(optional) containing the individual request
- reply structure: (JSON object)
- header: (int) indicating if the request was successfull (mostly like HTTP status codes)
- body: (mixed)(optional) containing further data depending on the request
### login
submit username and password to get a session token which can be used to authenticate any further commands
#### Request
- header: 1000
- body: (object)
- username: (string)
- password: (string)
#### Reply
- header: (int)
- 200: OK
- 400: invalid request
- 401: invalid username or password
- body: (string) (only set when header is 200) Session-token
### get user information
submit a sesion token to check if it s valid and get some information about the user if it is
#### Request
- header: 1001
- body: (string) the session token to be checked
#### Reply
- header: (int)
- 200: OK
- 400: invalid request
- 401: the token is invalid
- body: (object) (only set when header is 200)
- username: (string) username of the user the session belongs to
- realname: (string) full name of the user the session belongs to

View file

@ -92,7 +92,7 @@ class BlueWeather
* *
* @param string $session session token * @param string $session session token
* *
* @return int (-1: does not exist; x>0: userId) * @return int (-1: does not exist; >0: userId)
*/ */
public function checkSession($session) public function checkSession($session)
{ {
@ -110,6 +110,29 @@ class BlueWeather
return($data['userId']); return($data['userId']);
} }
/**
* Function to user information
*
* @param int $userId id of the user
*
* @return mixed (array with some user information, or -1 if user not found)
*/
public function getUserInfo($userId)
{
$sql = "SELECT username,realname FROM `users`
WHERE`id`=\"".$this->_con->real_escape_string($userId)."\"";
$result = $this->_con->query($sql);
if (!$result->num_rows > 0) {
return -1;
}
// only one row will be returned
$data = $result->fetch_assoc();
return($data);
}
// -------------------- // --------------------
// - getter functions - // - getter functions -

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,8 @@ header('Access-Control-Allow-Origin: *');
$blueweather = new BlueWeather($config); $blueweather = new BlueWeather($config);
//$_GET['command'] = '{"header":1001,"body":"undefined"}';
if (isset($_GET['locId'])) { if (isset($_GET['locId'])) {
// get data of given location // get data of given location
$data = $blueweather->getLocationData( $data = $blueweather->getLocationData(
@ -35,6 +37,47 @@ if (isset($_GET['locId'])) {
$sensorData = json_decode($_POST['submitSensorData'], true); $sensorData = json_decode($_POST['submitSensorData'], true);
$ret = $blueweather->processSensorData($sensorData); $ret = $blueweather->processSensorData($sensorData);
$data = $ret; $data = $ret;
} elseif (isset($_GET['command'])) {
// some user-data api request
$request = json_decode($_GET['command'], true);
if (!$request || !isset($request['header'])) {
$data = array("header"=>400);
} else {
switch ($request['header']) {
case 1000:
// user login
if (!isset($request['body']['username']) || !isset($request['body']['password'])) {
$data = array("header"=>400);
} else {
$token = $blueweather->loginUser(
$request['body']['username'],
$request['body']['password']
);
if ($token !== '') {
$data = array("header"=>200, "body"=>$token);
} else {
$data = array("header"=>401);
}
}
break;
case 1001:
// check session
if (!isset($request['body'])) {
$data = array("header"=>400);
} else {
$ret = $blueweather->getUserInfo(
$blueweather->checkSession($request['body'])
);
if ($ret === -1) {
$data = array("header"=>401);
} else {
$data = array("header"=>200, "data"=>$ret);
}
}
}
}
} else { } else {
$data = $blueweather->getAllLocations(); $data = $blueweather->getAllLocations();
} }

View file

@ -15,6 +15,12 @@
width:100%; width:100%;
} }
.feather {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
/* /*
* Login modal * Login modal
*/ */

View file

@ -2,12 +2,6 @@ body {
font-size: .875rem; font-size: .875rem;
} }
.feather {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
/* /*
* Sidebar * Sidebar
*/ */

View file

@ -1,9 +1,12 @@
class BlueWeather { class BlueWeather {
constructor() { constructor(profileObjectParent) {
// cunstruct xmlhttp // cunstruct xmlhttp
this.xhttp = new XMLHttpRequest(); this.xhttp = new XMLHttpRequest();
this.host = "https://weather.itsblue.de"//window.location.href.substring(0, window.location.href.lastIndexOf("/")); //this.host = "https://weather.itsblue.de"
this.host = window.location.href.substring(0, window.location.href.lastIndexOf("/"));
this.profileObjectParent = profileObjectParent
this.log("init done", 2) this.log("init done", 2)
@ -24,34 +27,44 @@ class BlueWeather {
// ---------------------- // ----------------------
restoreSession() { restoreSession() {
if(this.getCookie("session") !== "" && this.getCookie("session") !== undefined) { var thisObject = this
console.log("old session found: " + this.getCookie("session"), 3) if (this.getCookie("session") !== "" && this.getCookie("session") !== undefined && this.getCookie("session") !== "undefined") {
// old session found // old session found
this.session.loggedIn = true console.log("old session found: " + this.getCookie("session"), 3)
this.session.token = this.getCookie("session") // check if the session is still valid
this.checkSession(this.getCookie("session"), function (sessionIsValid) {
if (sessionIsValid) {
thisObject.session.loggedIn = true
thisObject.session.token = thisObject.getCookie("session")
}
thisObject.loadProfileObject(thisObject.profileObjectParent)
})
}
else {
this.loadProfileObject(this.profileObjectParent)
} }
} }
login(async, username, password, processingFunction) { login(async, username, password, processingFunction) {
this.xhttp.abort() var xhttp = new XMLHttpRequest();
var thisObject = this var thisObject = this
if(async) { if (async) {
this.xhttp.onreadystatechange = function() { xhttp.onreadystatechange = function () {
if (this.readyState === 4) { if (this.readyState === 4) {
// Typical action to be performed when the document is ready: if (this.status === 200) {
if(this.status === 200) {
thisObject.log("login response was: " + this.responseText, 3) thisObject.log("login response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText) var ret = JSON.parse(this.responseText)
if(ret && ret['status'] === 200) { if (ret && ret['header'] === 200) {
//this.session.token = ret["token"] thisObject.session.token = ret["body"]
//this.session.loggedIn = true document.cookie = "session=" + ret["body"] + ";"
thisObject.session.loggedIn = true
processingFunction(true) processingFunction(true)
return return
} }
else { else {
//this.session.token = "" thisObject.endSession()
//this.session.loggedIn = false
} }
} }
processingFunction(false) processingFunction(false)
@ -59,15 +72,49 @@ class BlueWeather {
} }
} }
var url = this.host + "/api/json.php" var request = JSON.stringify({ header: 1000, body: { username: username, password: password } })
this.log("starting location request; URL is: " + url, 3) var url = this.host + "/api/json.php?command=" + request
this.xhttp.open("GET", url, async) this.log("starting login request; URL is: " + url, 3)
this.xhttp.send() xhttp.open("GET", url, async)
xhttp.send()
}
checkSession(token, processingFunction) {
var xhttp = new XMLHttpRequest();
var thisObject = this
xhttp.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
thisObject.log("login response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText)
if (ret && ret['header'] === 200) {
thisObject.session.user.username = ret["data"]["username"]
thisObject.session.user.realName = ret["data"]["realname"]
processingFunction(true)
return
}
else {
thisObject.endSession()
}
}
processingFunction(false)
}
}
var request = JSON.stringify({ header: 1001, body: token })
var url = this.host + "/api/json.php?command=" + request
this.log("starting session check request; URL is: " + url, 3)
xhttp.open("GET", url, true)
xhttp.send()
} }
endSession() { endSession() {
document.cookie = "session=;" document.cookie = "session=;"
window.location.href = "./index.html" if (this.session.loggedIn) {
// if the user was logged in before
location.reload()
}
} }
// -------------------- // --------------------
@ -77,25 +124,25 @@ class BlueWeather {
getLocations(async, processingFunction, errorFunction) { getLocations(async, processingFunction, errorFunction) {
this.xhttp.abort() this.xhttp.abort()
var thisObject = this var thisObject = this
if(async) { if (async) {
this.xhttp.onreadystatechange = function () { this.xhttp.onreadystatechange = function () {
if (this.readyState === 4) { if (this.readyState === 4) {
// Typical action to be performed when the document is ready: // Typical action to be performed when the document is ready:
if(this.status === 200) { if (this.status === 200) {
thisObject.log("getting sensors response was: " + this.responseText, 3) thisObject.log("getting sensors response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText) var ret = JSON.parse(this.responseText)
if(ret){ if (ret) {
processingFunction(ret); processingFunction(ret);
return return
} }
} }
if(errorFunction !== null) { if (errorFunction !== null) {
errorFunction(this.status, this.text) errorFunction(this.status, this.text)
} }
} }
}; };
} }
var url = this.host + "/api/json.php" var url = this.host + "/api/json.php"
@ -104,31 +151,31 @@ class BlueWeather {
this.xhttp.send() this.xhttp.send()
} }
getLocationData(locId, range = {from:"", to:""}, maxVals = 0, async, processingFunction, errorFunction) { getLocationData(locId, range = { from: "", to: "" }, maxVals = 0, async, processingFunction, errorFunction) {
this.xhttp.abort() this.xhttp.abort()
var thisObject = this var thisObject = this
if(async) { if (async) {
this.xhttp.onreadystatechange = function () { this.xhttp.onreadystatechange = function () {
if (this.readyState === 4) { if (this.readyState === 4) {
// Typical action to be performed when the document is ready: // Typical action to be performed when the document is ready:
if(this.status === 200) { if (this.status === 200) {
thisObject.log("getting sensors response was: " + this.responseText, 3) thisObject.log("getting sensors response was: " + this.responseText, 3)
var ret = JSON.parse(this.responseText) var ret = JSON.parse(this.responseText)
if(ret){ if (ret) {
processingFunction(ret); processingFunction(ret);
return return
} }
} }
if(errorFunction !== null) { if (errorFunction !== null) {
errorFunction(this.status, this.text) errorFunction(this.status, this.text)
} }
} }
}; };
} }
var url = this.host + "/api/json.php?locId="+locId+"&range[from]="+range.from + "&range[to]="+range.to + "&maxVals[mode]=" + maxVals.mode + "&maxVals[count]=" + maxVals.count var url = this.host + "/api/json.php?locId=" + locId + "&range[from]=" + range.from + "&range[to]=" + range.to + "&maxVals[mode]=" + maxVals.mode + "&maxVals[count]=" + maxVals.count
this.log("starting location request; URL is: " + url, 3) this.log("starting location request; URL is: " + url, 3)
this.xhttp.open("GET", url, async) this.xhttp.open("GET", url, async)
this.xhttp.send() this.xhttp.send()
@ -139,17 +186,21 @@ class BlueWeather {
// ---------------------- // ----------------------
loadProfileObject(parent) { loadProfileObject(parent) {
if(!parent) { parent = this.profileObjectParent
if (!parent) {
this.log("error: no profile object parent", 3)
return false return false
} }
parent = document.getElementById(parent)
var thisObject = this var thisObject = this
var profileObject = document.createElement("li") var profileObject = document.createElement("li")
parent.appendChild(profileObject) parent.appendChild(profileObject)
profileObject.classList.add("nav-item") profileObject.classList.add("nav-item")
if(!this.session.loggedIn) { if (!this.session.loggedIn) {
this.log("not logged in", 3) this.log("not logged in", 3)
profileObject.classList.add("text-nowrap") profileObject.classList.add("text-nowrap")
@ -224,7 +275,7 @@ class BlueWeather {
var alert = document.createElement("div") var alert = document.createElement("div")
fieldset.append(alert) fieldset.append(alert)
alert.id = "loginFormLoginFailedAlert" alert.id = "loginFormLoginFailedAlert"
alert.appear = function() { alert.appear = function () {
alert.innerHTML = '<div class="alert alert-danger alert-dismissible fade show" role="alert">Invalid username or password<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button></div>' alert.innerHTML = '<div class="alert alert-danger alert-dismissible fade show" role="alert">Invalid username or password<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button></div>'
} }
// ----- username input // ----- username input
@ -248,23 +299,26 @@ class BlueWeather {
signInButton.type = "submit" signInButton.type = "submit"
signInButton.classList.add("btn", "btn-lg", "btn-primary", "btn-block") signInButton.classList.add("btn", "btn-lg", "btn-primary", "btn-block")
signInButton.innerHTML = "Sign in" signInButton.innerHTML = "Sign in"
signInButton.setLoading = function() { signInButton.setLoading = function () {
signInButton.disabled = true signInButton.disabled = true
signInButton.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Signing in...' signInButton.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Signing in...'
} }
signInButton.setNormal = function() { signInButton.setNormal = function () {
signInButton.disabled = false signInButton.disabled = false
signInButton.innerHTML = 'Sign in' signInButton.innerHTML = 'Sign in'
} }
signInButton.onclick = function() { signInButton.onclick = function () {
signInButton.setLoading() signInButton.setLoading()
var username = document.getElementById("loginFormUsernameInput").value var username = document.getElementById("loginFormUsernameInput").value
var password = document.getElementById("loginFormPasswordInput").value var password = document.getElementById("loginFormPasswordInput").value
thisObject.login(true, username, password, function(loginSuccess){ thisObject.login(true, username, password, function (loginSuccess) {
if(!loginSuccess){ if (!loginSuccess) {
alert.appear() alert.appear()
signInButton.setNormal()
}
else {
location.reload()
} }
signInButton.setNormal()
}) })
} }
// ---------- // ----------
@ -272,7 +326,7 @@ class BlueWeather {
parent.appendChild(loginModal) parent.appendChild(loginModal)
} }
else { else {
this.log("logged in", 3) this.log("logged in", 3)
profileObject.classList.add("dropdown") profileObject.classList.add("dropdown")
@ -291,7 +345,7 @@ class BlueWeather {
// create profile image inside button // create profile image inside button
var profileImage = document.createElement("img") var profileImage = document.createElement("img")
profileButton.appendChild(profileImage) profileButton.appendChild(profileImage)
profileImage.height="30" profileImage.height = "30"
profileImage.src = "img/user.png" profileImage.src = "img/user.png"
profileImage.classList.add("img-profile", "rounded-circle") profileImage.classList.add("img-profile", "rounded-circle")
@ -302,12 +356,13 @@ class BlueWeather {
profileDropdown.setAttribute("aria-labelledby", "userDropdown") profileDropdown.setAttribute("aria-labelledby", "userDropdown")
// fill the dropdown menu // fill the dropdown menu
function createDropdownMenuElement(icon, text) { function createDropdownMenuElement(icon, text, onclick=null) {
// create element // create element
var elem = document.createElement("a") var elem = document.createElement("a")
elem.classList.add("dropdown-item") elem.classList.add("dropdown-item")
elem.href = "#" elem.href = "#"
elem.onclick = onclick
// create icon // create icon
var iconSpan = document.createElement("span") var iconSpan = document.createElement("span")
elem.appendChild(iconSpan) elem.appendChild(iconSpan)
@ -325,7 +380,7 @@ class BlueWeather {
sep.classList.add("dropdown-divider") sep.classList.add("dropdown-divider")
return sep return sep
} }
var header = document.createElement("div") var header = document.createElement("div")
header.classList.add("dropdown-item") header.classList.add("dropdown-item")
header.innerHTML = "<h6><b>" + this.session.user.realName + "</b></h6>@" + this.session.user.username header.innerHTML = "<h6><b>" + this.session.user.realName + "</b></h6>@" + this.session.user.username
@ -333,7 +388,10 @@ class BlueWeather {
profileDropdown.appendChild(createDropdownSeparator()) profileDropdown.appendChild(createDropdownSeparator())
profileDropdown.appendChild(createDropdownMenuElement("settings", " Settings")) profileDropdown.appendChild(createDropdownMenuElement("settings", " Settings"))
profileDropdown.appendChild(createDropdownSeparator()) profileDropdown.appendChild(createDropdownSeparator())
profileDropdown.appendChild(createDropdownMenuElement("log-out", " Log out")) profileDropdown.appendChild(createDropdownMenuElement("log-out", " Log out", function() {
document.cookie = "session=;"
location.reload()
}))
} }
@ -363,7 +421,7 @@ class BlueWeather {
return result; return result;
} }
log(text, level){ log(text, level) {
// levels: // levels:
// 0: error // 0: error
// 1: warning // 1: warning
@ -372,22 +430,22 @@ class BlueWeather {
var preString = "[BlueWeather]" var preString = "[BlueWeather]"
switch(level){ switch (level) {
case 0: case 0:
preString += "[error] " preString += "[error] "
console.error(preString+text) console.error(preString + text)
break break
case 1: case 1:
preString += "[warining] " preString += "[warining] "
console.warn(preString+text) console.warn(preString + text)
break break
case 2: case 2:
preString += "[info] " preString += "[info] "
console.log(preString+text) console.log(preString + text)
break break
case 3: case 3:
preString += "[debug] " preString += "[debug] "
console.debug(preString+text) console.debug(preString + text)
} }
} }
} }

View file

@ -8,7 +8,7 @@ class BlueWeatherDashboard {
constructor() { constructor() {
// cunstruct xmlhttp // cunstruct xmlhttp
this.initDone = false this.initDone = false
this.blueweather = new BlueWeather() this.blueweather = new BlueWeather("profileContainer")
this.params = { this.params = {
loc: 1, loc: 1,
@ -615,5 +615,4 @@ window.onresize = function (event) {
flexFont(); flexFont();
}; };
feather.replace() feather.replace()
dashboard = new BlueWeatherDashboard() dashboard = new BlueWeatherDashboard(document.getElementById("profileContainer"))
dashboard.blueweather.loadProfileObject(document.getElementById("profileContainer"))

View file

@ -1,32 +1,32 @@
class BlueWeatherIndex { class BlueWeatherIndex {
constructor() { constructor() {
this.initDone = false this.initDone = false
this.blueweather = new BlueWeather() this.blueweather = new BlueWeather("profileContainer")
this.initDone = true this.initDone = true
this.loadLocations() this.loadLocations()
} }
loadLocations () { loadLocations() {
// page: -1 for dashboard or sensor id // page: -1 for dashboard or sensor id
var mainContent = document.getElementById('locationsList') var mainContent = document.getElementById('locationsList')
var loader = document.getElementById('loader') var loader = document.getElementById('loader')
mainContent.style = "opacity: 0;" mainContent.style = "opacity: 0;"
loader.style = "padding-left: 50%; padding-top:15px; opacity: 1; width:0;" loader.style = "padding-left: 50%; padding-top:15px; opacity: 1; width:0;"
this.blueweather.getLocations(true, function(locations) { this.blueweather.getLocations(true, function (locations) {
var locationsList = document.getElementById("locationsList") var locationsList = document.getElementById("locationsList")
locationsList.innerHTML = "" locationsList.innerHTML = ""
for(var location in locations) { for (var location in locations) {
var thisLocation = locations[location] var thisLocation = locations[location]
var locDiv = document.createElement("div") var locDiv = document.createElement("div")
locationsList.appendChild(locDiv) locationsList.appendChild(locDiv)
locDiv.classList.add("media", "text-muted", "pt-3") locDiv.classList.add("media", "text-muted", "pt-3")
locDiv.innerHTML = '<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" src="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32"><rect width="100%" height="100%" fill="#007bff" /><text x="50%" y="50%" fill="#007bff" dy=".3em">32x32</text></svg>' locDiv.innerHTML = '<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" src="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32"><rect width="100%" height="100%" fill="#007bff" /><text x="50%" y="50%" fill="#007bff" dy=".3em">32x32</text></svg>'
var locBody = document.createElement("p") var locBody = document.createElement("p")
locDiv.appendChild(locBody) locDiv.appendChild(locBody)
locBody.classList.add("media-body", "pb-3", "mb-0", "small", "lh-125", "border-bottom", "border-gray") locBody.classList.add("media-body", "pb-3", "mb-0", "small", "lh-125", "border-bottom", "border-gray")
@ -37,7 +37,7 @@ class BlueWeatherIndex {
var locHeadingText = document.createElement("a") var locHeadingText = document.createElement("a")
locHeading.appendChild(locHeadingText) locHeading.appendChild(locHeadingText)
locHeadingText.href = "dashboard.html?params=" + JSON.stringify({loc: parseInt(thisLocation.id)}) locHeadingText.href = "dashboard.html?params=" + JSON.stringify({ loc: parseInt(thisLocation.id) })
locHeadingText.innerHTML = thisLocation.locationname locHeadingText.innerHTML = thisLocation.locationname
var locLocationLink = document.createElement("a") var locLocationLink = document.createElement("a")
@ -55,5 +55,4 @@ class BlueWeatherIndex {
} }
} }
feather.replace() feather.replace()
index = new BlueWeatherIndex() index = new BlueWeatherIndex()
index.blueweather.loadProfileObject(document.getElementById("profileContainer"))