Skip to content

Commit 368a419

Browse files
committed
Merge Dashboard auth with shutdown authentication
- allowing user to shutdown password-less within 5 minutes since last authentication 🛂 - design and dynamic content things 👍 - ask for confirmation on cancel of shutdown events - check shutdown regularly with update of dashboard - rewrote checkShutdown routine - mdtoastJS: library 😆 applying duration to toasts with interaction not only for those without action button
1 parent 6b5f13e commit 368a419

File tree

3 files changed

+99
-29
lines changed

3 files changed

+99
-29
lines changed

backend/serv.php

+16-4
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,21 @@
1010
session_destroy();
1111
exit();
1212
}
13+
if(isset($_POST["check"])){
14+
$dif=time() - $_SESSION["rpidbauth"];
15+
if($dif > 60 * 4){
16+
echo "invalid";
17+
}else{
18+
echo "valid";
19+
}
20+
exit();
21+
}
1322
if(isset($_POST["login"])){
1423
if(isset($_POST["pw"])){
1524
$pw=md5($_POST["pw"]);
1625
if($pw==$correctPassword){
1726
echo "correctCredentials";
18-
$_SESSION["rpidbauth"]="1";
27+
$_SESSION["rpidbauth"]=time();
1928
}else{
2029
echo "wrongCredentials";
2130
}
@@ -24,19 +33,22 @@
2433
}
2534
if(isset($_GET["checkShutdown"])){
2635
system("date --date @$(head -1 /run/systemd/shutdown/scheduled |cut -c6-15)");
27-
exit;
36+
exit();
2837
}else if(isset($_GET["cancelShutdown"])){
2938
system('sudo /sbin/shutdown -c');
30-
exit;
39+
exit();
3140
}
3241
$pass = $_REQUEST["p"];
3342
$time = $_REQUEST["time"];
3443
if (strpos($time, ':') == false) {
3544
$time="+".$time;
3645
}
37-
if($pass != "root"){
46+
if( ($pass != $correctPassword) && (time()-$_SESSION["rpidbauth"] > 5 * 60) ){
3847
echo "wrongCredentials";
3948
}else{
49+
if($pass==$correctPassword){
50+
$_SESSION["rpidbauth"]=time();
51+
}
4052
if($_REQUEST["a"]=="1"){
4153
echo "true_";
4254
system('sudo /sbin/shutdown -h '.$time);

index.php

+82-24
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ function preload(){
318318
<div class="modal-body">
319319
<!---->
320320
<div id="currentState"></div>
321-
<form action="javascript:void(0);">
321+
<form id="pwrform" action="javascript:void(0);">
322322
<div class="form-check form-check-inline">
323323
<input class="form-check-input" type="radio" name="pwrOptions" id="inlineRadio1" value="1">
324324
<label class="form-check-label" for="inlineRadio1">Shutdown</label>
@@ -353,7 +353,7 @@ function preload(){
353353
</div>
354354
</div>
355355
<hr>
356-
<div class="form-group">
356+
<div id="pwrauth" class="form-group">
357357
<label for="inputPassword2" class="sr-only">Password</label>
358358
<div class="input-group">
359359
<div class="input-group-prepend">
@@ -362,11 +362,10 @@ function preload(){
362362
<input type="password" class="form-control" id="inputPassword2" placeholder="Password">
363363
</div>
364364
</div>
365-
<div id="rmd"></div>
366365
</form>
367366
</div>
368367
<div class="modal-footer">
369-
<button class="btn btn-primary" onclick="authorize(document.getElementById('inputPassword2').value);">Confirm identity</button>
368+
<button id="confbtn" class="btn btn-primary" onclick="authorize();">Confirm identity</button>
370369
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
371370
</div>
372371
</div>
@@ -503,8 +502,15 @@ function preload(){
503502

504503
<script>
505504
tselect=1;
506-
function authorize(pass) {
507-
console.log(pass);
505+
function authorize() {
506+
if(document.getElementById('inputPassword2')==null){
507+
pass="alreadyauthorized";
508+
}else{
509+
pass=document.getElementById('inputPassword2').value;
510+
}
511+
$("#confbtn").html("Checking...");
512+
$("#pwrform input, select").prop("disabled","true");
513+
$("#confbtn").prop("disabled","true");
508514
var e = document.getElementById("time"+tselect);
509515
if( (tselect==1) || (tselect==2) ){
510516

@@ -526,53 +532,80 @@ function authorize(pass) {
526532

527533
var act=document.querySelector('input[name="pwrOptions"]:checked').value;
528534
if (pass.length == 0) {
529-
document.getElementById("rmd").innerHTML = "<font class='text-danger'>Please enter a valid password!</font>";
535+
document.getElementById("currentState").innerHTML = "<font class='text-danger'>Please enter a valid password!</font>";
530536
return;
531537
} else {
532538
var xmlhttp = new XMLHttpRequest();
533539
xmlhttp.onreadystatechange = function() {
534540
if (this.readyState == 4 && this.status == 200) {
535541
console.log(this.responseText);
536542
if(this.responseText.indexOf("true") > -1){
537-
document.getElementById("rmd").innerHTML = "<font class='text-success'>Authorization completed!</font>";
543+
document.getElementById("currentState").innerHTML = "<div class='alert alert-success' role='alert'><i data-feather='check-circle'></i>&nbsp;Authorization completed!</font>";
544+
$("#confbtn").html("<i data-feather='check-circle'></i>&nbsp;Saved");
545+
feather.replace();
538546
var res=this.responseText.split("_");
539547
outputShutdown(res[1],act);
540-
$("#exampleModalCenter").modal("hide");
548+
setTimeout(function(){
549+
$("#exampleModalCenter").modal("hide");
550+
document.getElementById("pwrform").reset();
551+
$("#pwrform input, select").prop("disabled","");
552+
$("#confbtn").prop("disabled","");
553+
document.getElementById("currentState").innerHTML = "";
554+
$("#confbtn").html("Confirm identity");
555+
},3000);
541556
}else if(this.responseText=="wrongCredentials"){
542-
document.getElementById("rmd").innerHTML = "<font class='text-danger'>Authorization failed!</font>";
557+
document.getElementById("currentState").innerHTML = "<div class='alert alert-success' role='alert'><i data-feather='x-circle'></i>&nbsp;Authorization failed!</div>";
543558
}else{
544-
document.getElementById("rmd").innerHTML = "<font class='text-danger'>Error!</font>";
559+
document.getElementById("currentState").innerHTML = "<div class='alert alert-success' role='alert'><i data-feather='x-circle'></i>&nbsp;Error!</div>";
545560
}
546561
}
547562
};
548563
xmlhttp.open("GET", "backend/serv.php?p=" + pass+"&a="+act+"&time="+time, true);
549564
xmlhttp.send();
550565
}
551566
}
552-
function checkShutdown() {
567+
function checkShutdown(callback) {
568+
document.getElementById("currentState").innerHTML='<div class="alert alert-info" role="alert"><i data-feather="chevrons-right"></i>&nbsp;Checking for power events...</div>';
553569
var xmlhttp = new XMLHttpRequest();
554570
xmlhttp.onreadystatechange = function() {
555571
if (this.readyState == 4 && this.status == 200) {
556572
if(this.responseText==""){
557573
document.getElementById("sys2").innerHTML="";
558574
shutdownCurrent=false;
559-
return;
575+
}else{
576+
shutdownCurrent=true;
577+
outputShutdown(this.responseText,"unknown");
578+
}
579+
if(callback !== undefined){
580+
callback();
581+
}else{
582+
if(shutdownCurrent){
583+
document.getElementById("currentState").innerHTML='<div class="alert alert-danger" role="alert"><i data-feather="alert-circle"></i>&nbsp;Existing shutdown will be overwritten.&nbsp;<button class="btn btn-sm btn-outline-danger" onclick="cancelShutdown();$(\'#exampleModalCenter\').modal(\'hide\');">Remove</button></div>';
584+
}else{
585+
document.getElementById("currentState").innerHTML='<div class="alert alert-success" role="alert"><i data-feather="check-circle"></i>&nbsp;Currently there is no other power event planned.</div>';
586+
}
587+
feather.replace();
560588
}
561-
shutdownCurrent=true;
562-
outputShutdown(this.responseText,"unknown");
563589
}
564590
};
565591
xmlhttp.open("GET", "backend/serv.php?checkShutdown", true);
566592
xmlhttp.send();
567593
}
568594

569-
function cancelShutdown() {
595+
function cancelShutdown(force) {
596+
if(force == undefined){
597+
mdtoast('<i data-feather="help-circle"></i>&nbsp;Confirm to cancel', { type: 'warning', interaction: true, actionText: "Confirm", action: function(){ cancelShutdown(true); }, duration: 3000});
598+
feather.replace();
599+
return;
600+
}
570601
var xmlhttp = new XMLHttpRequest();
571602
xmlhttp.onreadystatechange = function() {
572603
if (this.readyState == 4 && this.status == 200) {
573604
console.log(this.responseText);
574605
if(this.responseText==""){
575606
console.log("Cancel response is empty");
607+
mdtoast('<i data-feather="check-circle"></i>&nbsp;Power event was cancelled!', { type: 'success'});
608+
feather.replace();
576609
checkShutdown();
577610
return;
578611
}
@@ -603,6 +636,7 @@ function outputShutdown(data,act) {
603636
if(restm>0){
604637
str += restm + " m";
605638
}
639+
if(str==""){ str="<font class='text-danger'>&lt; 1 min</font>"; }
606640
console.log(str);
607641
var action = (act=="1") ? "shutdown" : "reboot";
608642
if(act=="unknown"){
@@ -824,7 +858,8 @@ function togglep(force){
824858
y+=10;
825859
}else{
826860
$('.py').width(y+'%');
827-
updatedb();
861+
updatedb();
862+
checkShutdown();
828863
y=0;
829864
}
830865
}, (((upd_time_interval*1000)-1.5)/10));
@@ -893,6 +928,27 @@ function loginToServer(){
893928
authorize(document.getElementById('inputPassword2').value);
894929
}
895930
});
931+
function checkLauth(){
932+
document.getElementById("pwrauth").innerHTML="<div class='alert alert-info' role='alert'><i data-feather='chevrons-right'></i>&nbsp;Checking authorization ...</div>";
933+
feather.replace();
934+
var xmlhttp = new XMLHttpRequest();
935+
xmlhttp.onreadystatechange = function() {
936+
if (this.readyState == 4 && this.status == 200) {
937+
console.log(this.responseText);
938+
if(this.responseText=="invalid"){
939+
$("#pwrauth").html('<label for="inputPassword2" class="sr-only">Password</label><div class="input-group"><div class="input-group-prepend"><div class="input-group-text"><i data-feather="key"></i></div></div><input type="password" class="form-control" id="inputPassword2" placeholder="Password"></div>');
940+
}else{
941+
$("#pwrauth").html('<div class="alert alert-success" role="alert"><i data-feather="check-circle"></i>&nbsp;Authenticated</div>');
942+
}
943+
feather.replace();
944+
}
945+
};
946+
xmlhttp.open("POST", "backend/serv.php", true);
947+
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
948+
setTimeout(() => {
949+
xmlhttp.send("check=true");
950+
}, 1000);
951+
}
896952
</script>
897953

898954
<script src="js/radialIndicator-2.0.0.min.js"></script>
@@ -928,13 +984,15 @@ function addWarning(problem, icon){
928984
}
929985

930986
$('#exampleModalCenter').on('shown.bs.modal', function (e) {
931-
checkShutdown();
932-
if(shutdownCurrent){
933-
document.getElementById("currentState").innerHTML='<div class="alert alert-danger" role="alert"><i data-feather="alert-circle"></i>&nbsp;Existing shutdown will be overwritten.&nbsp;<button class="btn btn-sm btn-outline-danger" onclick="cancelShutdown();$(\'#exampleModalCenter\').modal(\'hide\');">Remove</button></div>';
934-
}else{
935-
document.getElementById("currentState").innerHTML='<div class="alert alert-success" role="alert"><i data-feather="check-circle"></i>&nbsp;Currently there is no other power event planned.</div>';
936-
}
937-
feather.replace();
987+
checkShutdown(function(){
988+
if(shutdownCurrent){
989+
document.getElementById("currentState").innerHTML='<div class="alert alert-danger" role="alert"><i data-feather="alert-circle"></i>&nbsp;Existing shutdown will be overwritten.&nbsp;<button class="btn btn-sm btn-outline-danger" onclick="cancelShutdown();$(\'#exampleModalCenter\').modal(\'hide\');">Remove</button></div>';
990+
}else{
991+
document.getElementById("currentState").innerHTML='<div class="alert alert-success" role="alert"><i data-feather="check-circle"></i>&nbsp;Currently there is no other power event planned.</div>';
992+
}
993+
feather.replace();
994+
});
995+
checkLauth();
938996
});
939997

940998
function toggleDarkMode() {

js/mdtoast.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)