diff --git a/dist/pvv.sql b/dist/pvv.sql index 3fc32f0..38cb495 100644 --- a/dist/pvv.sql +++ b/dist/pvv.sql @@ -38,15 +38,12 @@ CREATE TABLE "motd" ( INSERT INTO motd (title, content) VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet"); -CREATE TABLE "doors" ( -"name" TEXT PRIMARY KEY, -"open" BOOLEAN, -"description" TEXT +CREATE TABLE "door" ( +"time" INTEGER PRIMARY KEY, +"open" BOOLEAN ); -INSERT INTO doors(name, open, description) VALUES -("koserommet", FALSE, "Døra inn til koserommet på stripa"), -("terminalrommet", FALSE, "Døra inn til terminalrommet på stripa"); - +INSERT INTO door (time, open) +VALUES (0, FALSE); INSERT INTO users (uname, groups) diff --git a/dist/pvv_mysql.sql b/dist/pvv_mysql.sql index 797f4f0..1e327c3 100644 --- a/dist/pvv_mysql.sql +++ b/dist/pvv_mysql.sql @@ -40,11 +40,8 @@ INSERT INTO motd (title, content) VALUES ("MOTD ./dev.sh", "du kan endre motd i admin panelet"); */ -CREATE TABLE doors ( -`name` VARCHAR(20) PRIMARY KEY, -`open` BOOLEAN, -`description` TEXT +CREATE TABLE door ( +`time` INTEGER PRIMARY KEY, +`open` BOOLEAN ); -INSERT INTO doors(name, open, description) VALUES -("koserommet", FALSE, "Døra inn til koserommet på stripa"), -("terminalrommet", FALSE, "Døra inn til terminalrommet på stripa"); +INSERT INTO door(time, open) VALUES (0, FALSE); \ No newline at end of file diff --git a/dist/sql_config_example.php b/dist/sql_config_example.php index 99c13c9..af802f3 100644 --- a/dist/sql_config_example.php +++ b/dist/sql_config_example.php @@ -3,3 +3,4 @@ $dbDsn = 'sqlite:'.__DIR__.DIRECTORY_SEPARATOR.'pvv.sqlite'; $dbUser = null; $dbPass = null; +$doorSensorSecret = "OGJiZTdjZDctMmFkNy00ZjZjLTk3OGItOTA3NzU3ZDM2Yjlm"; \ No newline at end of file diff --git a/src/pvv/side/door.php b/src/pvv/side/door.php new file mode 100644 index 0000000..2a868ee --- /dev/null +++ b/src/pvv/side/door.php @@ -0,0 +1,74 @@ +pdo = $pdo; + } + + public function getAll() { + $query = 'SELECT time, open FROM door ORDER BY time DESC'; + $statement = $this->pdo->prepare($query); + $statement->execute(); + + $doorEvents = []; + foreach($statement->fetchAll() as $row){ + $doorEvents[] = [ + 'time' => (int)$row['time'], + 'open' => (bool)$row['open'] + ]; + } + + return $doorEvents; + } + + public function getEntriesAfter($startTime) { + $query = 'SELECT time, open FROM door WHERE time > :startTime ORDER BY time DESC'; + $statement = $this->pdo->prepare($query); + $statement->bindParam(':startTime', $startTime, PDO::PARAM_STR); + $statement->execute(); + + $doorEvents = []; + foreach($statement->fetchAll() as $row){ + $doorEvents[] = [ + 'time' => (int)$row['time'], + 'open' => (bool)$row['open'] + ]; + } + + return $doorEvents; + } + + public function getCurrent() { + $query = 'SELECT time, open FROM door ORDER BY time DESC LIMIT 1'; + $statement = $this->pdo->prepare($query); + $statement->execute(); + $row = $statement->fetch(); + return [ + 'time' => (int)$row['time'], + 'open' => (bool)$row['open'] + ]; + } + + private function removeOld() { + $firstValidTime = time() - 60*60*24*7; //One week before now + $query = 'DELETE FROM door WHERE time < :firstValid'; + $statement = $this->pdo->prepare($query); + $statement->bindParam(':firstValid', $firstValidTime, PDO::PARAM_STR); + $statement->execute(); + } + + public function createEvent($time, $open) { + $query = 'INSERT INTO door(time, open) VALUES (:time, :open)'; + $statement = $this->pdo->prepare($query); + $statement->bindParam(':time', $time, PDO::PARAM_STR); + $statement->bindParam(':open', $open, PDO::PARAM_STR); + $statement->execute(); + + $this->removeOld(); + } +} diff --git a/src/pvv/side/doors.php b/src/pvv/side/doors.php deleted file mode 100644 index ab511ce..0000000 --- a/src/pvv/side/doors.php +++ /dev/null @@ -1,79 +0,0 @@ -pdo = $pdo; - } - - public function getAll() { - $query = 'SELECT name, open, description FROM doors ORDER BY open DESC, name ASC'; - $statement = $this->pdo->prepare($query); - $statement->execute(); - - $doors = []; - foreach($statement->fetchAll() as $row){ - $doors[] = [ - 'name' => $row['name'], - 'open' => (int)$row['open'], - 'description' => $row['description'], - ]; - } - - return $doors; - } - - public function getByName($name){ - $query = 'SELECT name, open, description FROM doors WHERE name=:name'; - $statement = $this->pdo->prepare($query); - $statement->bindParam(':name', $name, PDO::PARAM_STR); - $statement->execute(); - - $row = $statement->fetch(); - if (!$row) { - return false; - } - - return [ - 'name' => $row['name'], - 'open' => (int)$row['open'], - 'description' => $row['description'], - ]; - } - - public function setDoorState($name, $open) { - $query = 'UPDATE doors SET open=:open WHERE name=:name'; - $statement = $this->pdo->prepare($query); - $statement->bindParam(':name', $name, PDO::PARAM_STR); - $statement->bindParam(':open', $open, PDO::PARAM_INT); - $statement->execute(); - } - - - public function createDoor($name, $description) { - $query = 'INSERT INTO doors(name, open, description) VALUES (:name, TRUE, :desc)'; - $statement = $this->pdo->prepare($query); - $statement->bindParam(':name', $name, PDO::PARAM_STR); - $statement->bindParam(':desc', $description, PDO::PARAM_STR); - $statement->execute(); - } - - public function updateDoorDescription($name, $description) { - $query = 'UPDATE doors SET descriptin=:desc WHERE name=:name'; - $statement = $this->pdo->prepare($query); - $statement->bindParam(':name', $name, PDO::PARAM_STR); - $statement->bindParam(':desc', $description, PDO::PARAM_STR); - $statement->execute(); - } - - public function deleteDoor($name) { - $query = 'DELETE FROM doors WHERE name = :name;'; - $statement = $this->pdo->prepare($query); - $statement->bindParam(':name', $name, PDO::PARAM_STR); - $statement->execute(); - } -} diff --git a/www/css/style.css b/www/css/style.css index c1d0f00..33f2541 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -153,6 +153,16 @@ nav #usermenu li:first-child:hover { background: transparent; } +#doorIndicator { + border-radius: 5px; + padding: 8px 8px; + margin: 4px 4px; +} +#doorIndicator > p > abbr[title] { text-decoration: none; border-bottom: none; cursor: inherit; } +.doorIndicator_OPEN { border: 2px solid green; } +.doorIndicator_CLOSED { border: 2px dotted red; } +.doorStateMobileOnly { display: none; } + @media(max-width: 800px){ nav #menu, nav #menu li.active, nav #menu_toggle, nav #login { position: absolute; @@ -226,6 +236,9 @@ nav #usermenu li:first-child:hover { margin-left: 1em !important; margin-right: 1em !important; } + .doorStateMobileOnly { + display: inline; + } } body { @@ -346,3 +359,4 @@ article p { textarea.boxinput { resize: vertical; } + diff --git a/www/door/index.php b/www/door/index.php index 4dfb883..76c81b9 100644 --- a/www/door/index.php +++ b/www/door/index.php @@ -1,49 +1,73 @@ getByName($_GET["name"]); - if (!$out) { - echo '{"error": true, "reason": "not found"}'; - http_response_code(404); - exit(); +$door = new \pvv\side\Door($pdo); + +if($_SERVER['REQUEST_METHOD'] === 'POST') { + if (isset($_SERVER["HTTP_AUTHORIZATION"])) { + list($type, $data) = explode(" ", $_SERVER["HTTP_AUTHORIZATION"], 2); + if (strcasecmp($type, "Bearer") == 0) { + if (hash_equals($data, $doorSensorSecret)) { + handleSetState(); + } else { + echo '{"status": "error", "message": "Invalid authentication key"}'; + die(); + } + } else { + echo '{"status": "error", "message": "Invalid authentication method"}'; + die(); } + } else { + echo '{"status": "error", "message": "Missing authentication"}'; + die(); } - else { - $out = $doors->getAll(); - } -} -elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { - if (isset($_POST["name"]) and isset($_POST["open"]) ) { - $out = $doors->setDoorState($_POST["name"], (strtolower($_POST["open"])==="true")?1:0); - - $out = $doors->getByName($_POST["name"]); - if (!$out) { - echo '{"error": true, "reason": "not found"}'; - http_response_code(404); - exit(); +} elseif ($_SERVER['REQUEST_METHOD'] === 'GET') { + + if (isset($_GET["period"])) { + $period = (string)htmlspecialchars($_GET["period"]); + if ($period == "day") { + $startTime = time() - (60*60*24); + } else if ($period == "week") { + $startTime = time() - (60*60*24*7); + } else { + echo '{"status": "error", "message": "Invalid period"}'; + die(); } - } - else { - echo '{"error": true, "reason": "missing either \"name\" or \"open\" argument"}'; - http_response_code(404); - exit(); + + $lines = $door->getEntriesAfter($startTime); + echo json_encode([ + 'status' => "OK", + 'entries' => $lines + ]); + } else { + //Only last entry + $line = (object)$door->getCurrent(); + echo json_encode([ + 'status' => "OK", + 'time' => $line->time, + 'open' => $line->open + ]); } } -function utf8ize($d) { - if (is_array($d)) { - foreach ($d as $k => $v) { - $d[$k] = utf8ize($v); - } - } else if (is_string ($d)) { - return utf8_encode($d); - } - return $d; -} -echo json_encode(utf8ize($out)); +function handleSetState() { + global $door; + + $jsonobj = file_get_contents('php://input'); + $event = json_decode($jsonobj); + + if ((!isset($event->time)) || (!is_numeric($event->time))) { + echo '{"status": "error", "message": "Invalid timestamp"}'; + die(); + } + if ((!isset($event->isDoorOpen)) || (!is_bool($event->isDoorOpen))) { + echo '{"status": "error", "message": "Invalid door state"}'; + die(); + } + + $door->createEvent((int)($event->time), (bool)($event->isDoorOpen)); + echo '{"status": "OK"}'; +} \ No newline at end of file diff --git a/www/index.php b/www/index.php index a73c7a8..4822a2b 100644 --- a/www/index.php +++ b/www/index.php @@ -7,6 +7,12 @@ $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $motdfetcher = new \pvv\side\MOTD($pdo); $motd = $motdfetcher->getMOTD(); + +$door = new \pvv\side\Door($pdo); +$doorEntry = (object)($door->getCurrent()); +$isDoorOpen = $doorEntry->open; +if (date("Y-m-d") == date("Y-m-d", $doorEntry->time)) { $doorTime = date("H:i", $doorEntry->time); +} else { $doorTime = date("H:i d/m", $doorEntry->time);} ?> @@ -63,6 +69,10 @@ $motd = $motdfetcher->getMOTD();
  • Om PVV
  • Bli medlem!
  • Veibeskrivelse +
    "> +

    Døren er åpen.

    +

    (Oppdatert )

    +