Features: simple admin menu, public tracks
This commit is contained in:
parent
0d396a34ec
commit
41eb7df3fc
3
README
3
README
@ -24,8 +24,9 @@ Features:
|
||||
Todo
|
||||
- install script
|
||||
- custom icons
|
||||
- admin page (users management)
|
||||
- admin menu (users management)
|
||||
- track editing
|
||||
- track display filters (accurracy, provider)
|
||||
|
||||
License
|
||||
- GPL
|
||||
|
92
adduser.php
Normal file
92
adduser.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/* μlogger
|
||||
*
|
||||
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Library General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
require_once("auth.php");
|
||||
|
||||
/**
|
||||
* Exit with xml response
|
||||
* @param boolean $isError Error if true
|
||||
* @param string $errorMessage Optional error message
|
||||
*/
|
||||
function exitWithStatus($isError, $errorMessage = NULL) {
|
||||
header("Content-type: text/xml");
|
||||
$xml = new XMLWriter();
|
||||
$xml->openURI("php://output");
|
||||
$xml->startDocument("1.0");
|
||||
$xml->setIndent(true);
|
||||
$xml->startElement('root');
|
||||
$xml->writeElement("error", (int) $isError);
|
||||
if ($isError) {
|
||||
$xml->writeElement("message", $errorMessage);
|
||||
}
|
||||
$xml->endElement();
|
||||
$xml->endDocument();
|
||||
$xml->flush();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if login is allowed
|
||||
* @param string $login Login
|
||||
*/
|
||||
function checkUser($login) {
|
||||
global $mysqli;
|
||||
$sql = "SELECT id FROM users WHERE login = ?";
|
||||
$query = $mysqli->prepare($sql);
|
||||
$query->bind_param('s', $login);
|
||||
$query->execute();
|
||||
if ($query->errno) {
|
||||
exitWithStatus(true, $query->error);
|
||||
}
|
||||
$query->store_result();
|
||||
if ($query->num_rows) {
|
||||
exitWithStatus(true, "User exists");
|
||||
}
|
||||
$query->free_result();
|
||||
$query->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new user to database
|
||||
* @param string $login Login
|
||||
* @param string $hash Password hash
|
||||
*/
|
||||
function insertUser($login, $hash) {
|
||||
global $mysqli;
|
||||
$sql = "INSERT INTO users (login, password) VALUES (?, ?)";
|
||||
$query = $mysqli->prepare($sql);
|
||||
$query->bind_param('ss', $login, $hash);
|
||||
$query->execute();
|
||||
if ($query->errno) {
|
||||
exitWithStatus(true, $query->error);
|
||||
$isError = false;
|
||||
}
|
||||
$query->close();
|
||||
}
|
||||
|
||||
$login = isset($_REQUEST['login']) ? trim($_REQUEST['login']) : NULL;
|
||||
$hash = isset($_REQUEST['pass']) ? password_hash($_REQUEST['pass'], PASSWORD_DEFAULT) : NULL;
|
||||
if ($admin && !empty($login) && !empty($hash)) {
|
||||
checkUser($login);
|
||||
insertUser($login, $hash);
|
||||
}
|
||||
exitWithStatus(false);
|
||||
|
||||
?>
|
79
admin.js
Normal file
79
admin.js
Normal file
@ -0,0 +1,79 @@
|
||||
/* μlogger
|
||||
*
|
||||
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Library General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
function showModal(contentHTML) {
|
||||
var div = document.createElement("div");
|
||||
div.setAttribute("id", "modal");
|
||||
div.innerHTML = '<div id="modal-header"><button type="button" onclick="removeModal()">×</button></div><div id="modal-body"></div>';
|
||||
document.body.appendChild(div);
|
||||
var modalBody = document.getElementById('modal-body');
|
||||
modalBody.innerHTML = contentHTML;
|
||||
}
|
||||
|
||||
function removeModal() {
|
||||
document.body.removeChild(document.getElementById('modal'));
|
||||
}
|
||||
|
||||
function addUser() {
|
||||
var form = '<form id="userForm" method="post" onsubmit="submitUser(); return false">';
|
||||
form += '<label><b>User name</b></label><input type="text" placeholder="Enter user login" name="login" required>';
|
||||
form += '<label><b>Password</b></label><input type="password" placeholder="Enter Password" name="pass" required>';
|
||||
form += '<label><b>Repeat password</b></label><input type="password" placeholder="Enter Password" name="pass2" required>';
|
||||
form += '<button type="button" onclick="removeModal()">Cancel</button><button type="submit">Submit</button>';
|
||||
form += '</form>';
|
||||
showModal(form);
|
||||
}
|
||||
|
||||
function submitUser() {
|
||||
var form = document.getElementById('userForm');
|
||||
var login = form.elements['login'].value;
|
||||
var pass = form.elements['pass'].value;
|
||||
var pass2 = form.elements['pass2'].value;
|
||||
if (!login || !pass || !pass2) {
|
||||
alert("All fields are required");
|
||||
return;
|
||||
}
|
||||
if (pass != pass2) {
|
||||
alert("Passwords don't match");
|
||||
return;
|
||||
}
|
||||
var xhr = getXHR();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState==4 && xhr.status==200) {
|
||||
var xml = xhr.responseXML;
|
||||
var message = "";
|
||||
if (xml) {
|
||||
var root = xml.getElementsByTagName('root');
|
||||
if (root.length && getNode(root[0], 'error') == 0) {
|
||||
removeModal();
|
||||
alert("User successfully added");
|
||||
return;
|
||||
}
|
||||
errorMsg = getNode(root[0], 'message');
|
||||
if (errorMsg) { message = errorMsg; }
|
||||
}
|
||||
alert("Something went wrong\n" + message);
|
||||
xhr = null;
|
||||
}
|
||||
}
|
||||
xhr.open('POST', 'adduser.php', true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr.send('login=' + login + '&pass=' + pass);
|
||||
return;
|
||||
}
|
9
auth.php
9
auth.php
@ -95,7 +95,7 @@ if ($require_authentication || defined('headless')) {
|
||||
$query = $mysqli->prepare("SELECT id, login, password FROM users WHERE login=? LIMIT 1");
|
||||
$query->bind_param('s', $user);
|
||||
$query->execute();
|
||||
$query->bind_result($rec_ID, $rec_user, $rec_pass);
|
||||
$query->bind_result($rec_id, $rec_user, $rec_pass);
|
||||
$query->fetch();
|
||||
$query->free_result();
|
||||
//correct pass
|
||||
@ -111,14 +111,9 @@ if ($require_authentication || defined('headless')) {
|
||||
if (($user == $admin_user) && !empty($admin_user)) {
|
||||
$_SESSION['admin'] = $admin_user;
|
||||
}
|
||||
$_SESSION['auth'] = $rec_ID;
|
||||
if (defined('headless')) {
|
||||
$url = str_replace("//", "/", $_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME'])."/client/index.php");
|
||||
header("Location: $ssl://$url");
|
||||
} else {
|
||||
$_SESSION['auth'] = $rec_id;
|
||||
$url = str_replace("//", "/", $_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME'])."/index.php");
|
||||
header("Location: $ssl://$url");
|
||||
}
|
||||
exit();
|
||||
} else {
|
||||
// unsuccessful
|
||||
|
@ -57,14 +57,14 @@ $dbname = ""; // database name
|
||||
// (0 = no, 1 = yes)
|
||||
$require_authentication = 1;
|
||||
|
||||
// all users tracks are visible to authenticated user
|
||||
// (0 = no, 1 = yes)
|
||||
$public_tracks = 0;
|
||||
|
||||
// admin user who has access to all users locations
|
||||
// none if empty
|
||||
$admin_user = "";
|
||||
|
||||
// allow automatic registration of new users
|
||||
// (0 = no, 1 = yes)
|
||||
$allow_registration = 0;
|
||||
|
||||
// Default interval in seconds for live auto reload
|
||||
$interval = 10;
|
||||
|
||||
|
21
index.php
21
index.php
@ -19,7 +19,8 @@
|
||||
*/
|
||||
require_once("auth.php");
|
||||
|
||||
if ($auth && !$admin) {
|
||||
if ($auth && !$admin && !$public_tracks) {
|
||||
// only authorized user tracks
|
||||
// get username
|
||||
$query = "SELECT login FROM users WHERE id='$auth' LIMIT 1";
|
||||
$result = $mysqli->query($query);
|
||||
@ -30,7 +31,7 @@ if ($auth && !$admin) {
|
||||
$user_form = '<u>'.$lang_user.'</u><br />'.$user.' (<a href="logout.php">'.$lang_logout.'</a>)';
|
||||
}
|
||||
else {
|
||||
// free access or admin user
|
||||
// public access or admin user
|
||||
// prepare user select form
|
||||
if ($admin) {
|
||||
$user = $admin_user;
|
||||
@ -71,7 +72,7 @@ $track_form = '
|
||||
<form>
|
||||
<select name="track" onchange="selectTrack(this)">';
|
||||
$userid = "";
|
||||
if ($auth && !$admin) {
|
||||
if ($auth && !$admin && !$public_tracks) {
|
||||
// display track of authenticated user
|
||||
$userid = $auth;
|
||||
} elseif ($last_id) {
|
||||
@ -124,6 +125,18 @@ $units_form = '
|
||||
</select>
|
||||
</form>
|
||||
';
|
||||
// admin menu
|
||||
$admin_menu = '';
|
||||
$admin_script = '';
|
||||
if ($admin) {
|
||||
$admin_menu = '
|
||||
<div id="admin_menu">
|
||||
<u>'.$lang_adminmenu.'</u><br />
|
||||
<a href="javascript:void(0);" onclick="addUser()">'.$lang_adduser.'</a><br />
|
||||
</div>
|
||||
';
|
||||
$admin_script = '<script type="text/javascript" src="admin.js"></script>';
|
||||
}
|
||||
|
||||
print
|
||||
'<!DOCTYPE html>
|
||||
@ -176,6 +189,7 @@ else {
|
||||
';
|
||||
}
|
||||
print '
|
||||
'.$admin_script.'
|
||||
<script type="text/javascript" src="//www.google.com/jsapi"></script>
|
||||
<script type="text/javascript">
|
||||
google.load("visualization", "1", {packages:["corechart"]});
|
||||
@ -211,6 +225,7 @@ print '
|
||||
<a href="javascript:void(0);" onclick="load(\'kml\',userid,trackid)">kml</a><br />
|
||||
<a href="javascript:void(0);" onclick="load(\'gpx\',userid,trackid)">gpx</a><br />
|
||||
</div>
|
||||
'.$admin_menu.'
|
||||
</div>
|
||||
<div id="menu-close" onclick="toggleMenu();">»</div>
|
||||
<div id="footer"><a target="_blank" href="https://github.com/bfabiszewski/ulogger-server"><span class="mi">μ</span>logger</a> '.$version.'</div>
|
||||
|
15
lang.php
15
lang.php
@ -53,6 +53,9 @@ switch($lang) {
|
||||
$lang_units = "Units";
|
||||
$lang_metric = "Metric";
|
||||
$lang_imperial = "Imperial/US";
|
||||
$lang_adminmenu = "Administration";
|
||||
$lang_adduser = "Add user";
|
||||
$lang_userexists = "User exists";
|
||||
break;
|
||||
|
||||
case "pl":
|
||||
@ -89,6 +92,9 @@ switch($lang) {
|
||||
$lang_units = "Jednostki";
|
||||
$lang_metric = "Metryczne";
|
||||
$lang_imperial = "Anglosaskie";
|
||||
$lang_adminmenu = "Administracja";
|
||||
$lang_adduser = "Dodaj użytkownika";
|
||||
$lang_userexists = "Użytkownik istnieje";
|
||||
break;
|
||||
|
||||
case "de":
|
||||
@ -125,6 +131,11 @@ switch($lang) {
|
||||
$lang_units = "Maßsystem";
|
||||
$lang_metric = "Metrisches";
|
||||
$lang_imperial = "Angloamerikanisches";
|
||||
$lang_adminmenu = "Verwaltung";
|
||||
|
||||
// todo: translate
|
||||
$lang_adduser = "Add user";
|
||||
$lang_userexists = "User exists";
|
||||
break;
|
||||
|
||||
case "hu":
|
||||
@ -161,6 +172,10 @@ switch($lang) {
|
||||
$lang_units = "Mértékegység";
|
||||
$lang_metric = "Metrikus";
|
||||
$lang_imperial = "Imperal/US";
|
||||
$lang_adminmenu = "Adminisztráció";
|
||||
// todo: translate
|
||||
$lang_adduser = "Add user";
|
||||
$lang_userexists = "User exists";
|
||||
break;
|
||||
}
|
||||
?>
|
||||
|
44
main.css
44
main.css
@ -187,3 +187,47 @@ select {
|
||||
padding-right:0.1em;
|
||||
font-style:italic;
|
||||
}
|
||||
|
||||
#modal {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 10010;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: black; /* fallback */
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
padding-top: 10%;
|
||||
}
|
||||
|
||||
#modal-header {
|
||||
top: 10px;
|
||||
position: relative;
|
||||
text-align: right;
|
||||
margin: 0 auto;
|
||||
width: 40%;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
#modal-body {
|
||||
font-size: 0.9em;
|
||||
font-family: Verdana, sans-serif;
|
||||
color: white;
|
||||
background-color: #666;
|
||||
margin: 0 auto 15% auto;
|
||||
border: 1px solid #888;
|
||||
width: 40%;
|
||||
min-width: 300px;
|
||||
padding: 1%;
|
||||
}
|
||||
|
||||
#modal input[type=text], #modal input[type=password] {
|
||||
width: 100%;
|
||||
padding: 0.4em;
|
||||
margin: 0.8em 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: border-box;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user