412 lines
17 KiB
HTML
412 lines
17 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
<title>Tesses Backup</title>
|
||
|
<!--Import Google Icon Font-->
|
||
|
<link href="./css/font.css" rel="stylesheet">
|
||
|
<!--Import materialize.css-->
|
||
|
<link type="text/css" rel="stylesheet" href="./css/materialize.min.css" media="screen,projection"/>
|
||
|
</head>
|
||
|
<body>
|
||
|
|
||
|
<nav>
|
||
|
<div class="nav-wrapper teal lighten-2">
|
||
|
<a href="#" class="brand-logo">Tesses Backup</a>
|
||
|
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||
|
<li><a href="#view">View</a></li>
|
||
|
<li><a href="#login" id="loginnav">Login</a></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</nav>
|
||
|
<div class="container spapage" id="index">
|
||
|
<h3>Backup your computer or other device over http(s)</h3>
|
||
|
<h5>Start by doing something</h5>
|
||
|
<ul>
|
||
|
<li><a href="#login" id="loginlink">Login</a></li>
|
||
|
<li><a href="#changepassword">Change Password</a></li>
|
||
|
<li><a href="#view">View/Download Backup Files</a></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div class="container spapage" id="changepassword">
|
||
|
<h1>Change Password</h1>
|
||
|
<div class="row">
|
||
|
<div class="input-field col s12">
|
||
|
<input id="username2" type="text" class="validate">
|
||
|
<label for="username2">Username</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="input-field col s12">
|
||
|
<input id="password2" type="password" class="validate">
|
||
|
<label for="password2">Password</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="input-field col s12">
|
||
|
<input id="password3" type="password" class="validate">
|
||
|
<label for="password3">New Password</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="input-field col s12">
|
||
|
<input id="password4" type="password" class="validate">
|
||
|
<label for="password4">Confirm New Password</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<button onclick="changepassword()" class="waves-effect waves-light btn">Login</button>
|
||
|
</div>
|
||
|
<div class="container spapage" id="logout">
|
||
|
<h1>Logout</h1>
|
||
|
<button onclick="logout()" class="waves-effect waves-light btn">Logout</button>
|
||
|
</div>
|
||
|
<div class="container spapage" id="login">
|
||
|
<h1>Login</h1>
|
||
|
<div class="row">
|
||
|
<div class="input-field col s12">
|
||
|
<input id="username" type="text" class="validate">
|
||
|
<label for="username">Username</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="row">
|
||
|
<div class="input-field col s12">
|
||
|
<input id="password" type="password" class="validate">
|
||
|
<label for="password">Password</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<button onclick="login()" class="waves-effect waves-light btn">Login</button>
|
||
|
</div>
|
||
|
<div class="container spapage" id="view">
|
||
|
<h3>View/Download Backup Files</h3>
|
||
|
<div class="row">
|
||
|
|
||
|
<div class="input-field col s12">
|
||
|
<input id="path" type="text" class="validate" value="/">
|
||
|
<label for="path">Path</label>
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
<button onclick="up()" class="btn waves-effect waves-light">Up
|
||
|
</button>
|
||
|
<button onclick="gopath()" class="btn waves-effect waves-light">Go
|
||
|
</button>
|
||
|
|
||
|
|
||
|
|
||
|
<div class="collection" id="storage_page">
|
||
|
<!-- <a href="#!" class="collection-item"><i class="secondary-content material-icons">folder</i> Alvin</a>
|
||
|
<a href="#!" class="collection-item"><span class="secondary-content new badge" data-badge-caption="kB">4</span>Alvin</a>-->
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
<script src="./js/materialize.min.js"></script>
|
||
|
<script src="./js/spa.min.js"></script>
|
||
|
<script>
|
||
|
|
||
|
var files = [];
|
||
|
const loginNav = document.getElementById('loginnav');
|
||
|
const loginLink = document.getElementById('loginlink');
|
||
|
|
||
|
const username = document.getElementById('username');
|
||
|
const password = document.getElementById('password');
|
||
|
const username2 = document.getElementById('username2');
|
||
|
const password2 = document.getElementById('password2');
|
||
|
const password3 = document.getElementById('password3');
|
||
|
const password4 = document.getElementById('password4');
|
||
|
const storage_page = document.getElementById('storage_page');
|
||
|
const _path = document.getElementById('path');
|
||
|
function gopath()
|
||
|
{
|
||
|
storage_page.innerHTML="";
|
||
|
getfiles().forEach(e=>{
|
||
|
/*<a href="#!" class="collection-item"><i class="secondary-content material-icons">folder</i> Alvin</a>
|
||
|
<a href="#!" class="collection-item"><span class="secondary-content new badge" data-badge-caption="kB">4</span>Alvin</a>*/
|
||
|
if(e.IsFile)
|
||
|
{
|
||
|
var elmt=document.createElement('a');
|
||
|
elmt.href = e.Path;
|
||
|
elmt.download = e.Name;
|
||
|
elmt.classList.add('collection-item');
|
||
|
elmt.innerText = e.Name;
|
||
|
var span = document.createElement('span');
|
||
|
span.setAttribute('data-badge-caption',e.Unit);
|
||
|
span.innerText = e.Size;
|
||
|
span.classList.add('secondary-content');
|
||
|
span.classList.add('new');
|
||
|
span.classList.add('badge');
|
||
|
elmt.appendChild(span);
|
||
|
storage_page.appendChild(elmt);
|
||
|
}else{
|
||
|
var elmt=document.createElement('a');
|
||
|
elmt.href = '#view';
|
||
|
elmt.onclick = function () {
|
||
|
_path.value = e.Path;
|
||
|
gopath();
|
||
|
};
|
||
|
elmt.classList.add('collection-item');
|
||
|
elmt.innerText = e.Name;
|
||
|
var span = document.createElement('i');
|
||
|
span.innerText='folder';
|
||
|
span.classList.add('secondary-content');
|
||
|
span.classList.add('material-icons');
|
||
|
elmt.appendChild(span);
|
||
|
storage_page.appendChild(elmt);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
function getfiles()
|
||
|
{
|
||
|
var items=_path.value.split('/');
|
||
|
|
||
|
var files2=files;
|
||
|
items.forEach(e=>{
|
||
|
files2.forEach(f=>{
|
||
|
if(f.Name === e)
|
||
|
{
|
||
|
files2=f.Entries;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
return files2;
|
||
|
|
||
|
}
|
||
|
function up()
|
||
|
{
|
||
|
var items=_path.value.split('/');
|
||
|
|
||
|
items.pop();
|
||
|
var v= items.join('/');
|
||
|
if(!v.startsWith('/')) v= `/${v}`;
|
||
|
_path.value = v;
|
||
|
gopath();
|
||
|
|
||
|
|
||
|
}
|
||
|
function changepassword()
|
||
|
{
|
||
|
fetch('./api/v1/ChangePassword',{
|
||
|
method: 'post',
|
||
|
body: JSON.stringify({
|
||
|
'UserName': username2.value,
|
||
|
'OldPassword': password2.value,
|
||
|
'NewPassword': password3.value,
|
||
|
'ConfirmNewPassword': password4.value
|
||
|
})
|
||
|
}).then(e=>e.json()).then(e=>{
|
||
|
if(e.Success)
|
||
|
{
|
||
|
|
||
|
M.toast({html: 'Changed password successfully'});
|
||
|
|
||
|
|
||
|
//Yay success
|
||
|
}else{
|
||
|
//fail
|
||
|
M.toast({html: `Failed Reason: ${e.ErrorData}`})
|
||
|
}
|
||
|
window.location.hash="#index";
|
||
|
});
|
||
|
}
|
||
|
function logout()
|
||
|
{
|
||
|
fetch('./api/v1/Logout',{
|
||
|
|
||
|
method: 'post',
|
||
|
body: JSON.stringify({
|
||
|
'Key': localStorage.getItem('key')
|
||
|
})
|
||
|
|
||
|
}).then(e=>e.json()).then(e=>{
|
||
|
try{
|
||
|
localStorage.removeItem('key');
|
||
|
}catch(e)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
if(e.Success)
|
||
|
{
|
||
|
|
||
|
M.toast({html: 'Logged out successfully'});
|
||
|
|
||
|
handleLoggedIn();
|
||
|
|
||
|
//Yay success
|
||
|
}else{
|
||
|
//fail
|
||
|
M.toast({html: `Failed Reason: ${e.ErrorData}`})
|
||
|
}
|
||
|
window.location.hash="#index";
|
||
|
});
|
||
|
|
||
|
}
|
||
|
function login()
|
||
|
{
|
||
|
fetch('./api/v1/Login',{
|
||
|
method: 'post',
|
||
|
body: JSON.stringify({
|
||
|
'Username': username.value,
|
||
|
'Password': password.value
|
||
|
})
|
||
|
}).then(e=>e.json()).then(e=>{
|
||
|
if(e.Success)
|
||
|
{
|
||
|
localStorage.setItem('key',e.Key);
|
||
|
M.toast({html: 'Logged in'});
|
||
|
|
||
|
handleLoggedIn();
|
||
|
|
||
|
//Yay success
|
||
|
}else{
|
||
|
//fail
|
||
|
M.toast({html: `Failed Reason: ${e.ErrorData}`})
|
||
|
}
|
||
|
window.location.hash="#index";
|
||
|
});
|
||
|
|
||
|
}
|
||
|
function handleLoggedIn()
|
||
|
{
|
||
|
if(localStorage.getItem('key')===null)
|
||
|
{
|
||
|
|
||
|
|
||
|
//logged out
|
||
|
loginNav.innerText = "Login";
|
||
|
loginLink.innerText = "Login";
|
||
|
loginNav.href = "#login";
|
||
|
loginLink.href = "#login";
|
||
|
}else{
|
||
|
|
||
|
fetch("./api/v1/Devices",{
|
||
|
method: 'post',
|
||
|
body: JSON.stringify({
|
||
|
'Key': localStorage.getItem('key')
|
||
|
})
|
||
|
}).then(e=>e.json()).then(e=>{
|
||
|
|
||
|
if(e.Success)
|
||
|
{
|
||
|
|
||
|
e.Devices.forEach(f=>{
|
||
|
|
||
|
var deviceId= f.DeviceId;
|
||
|
var deviceName=f.DeviceName;
|
||
|
|
||
|
var dir = {
|
||
|
Name: deviceName,
|
||
|
IsFile: false,
|
||
|
Entries: [],
|
||
|
Path: `/${deviceName}`,
|
||
|
Size: 0,
|
||
|
Unit: "bytes"
|
||
|
};
|
||
|
files.push(dir);
|
||
|
fetch("./api/v1/Backups",{
|
||
|
method: 'post',
|
||
|
body: JSON.stringify({
|
||
|
'Key': localStorage.getItem('key'),
|
||
|
'DeviceId': deviceId
|
||
|
})
|
||
|
}).then(g=>g.json()).then(g=>{
|
||
|
if(g.Success)
|
||
|
{
|
||
|
|
||
|
g.Backups.forEach(h=>{
|
||
|
var backupId=h.BackupId;
|
||
|
var backupName = h.Creation;
|
||
|
var item2 = {
|
||
|
Name: backupName,
|
||
|
IsFile: false,
|
||
|
Entries: [],
|
||
|
Path: `/${deviceName}/${backupName}`,
|
||
|
Size: 0,
|
||
|
Unit: "bytes"
|
||
|
};
|
||
|
dir.Entries.push(item2);
|
||
|
fetch("./api/v1/Backup",{
|
||
|
method: 'post',
|
||
|
body: JSON.stringify({
|
||
|
"Key": localStorage.getItem('key'),
|
||
|
"BackupId": backupId
|
||
|
})
|
||
|
}).then(l=>l.json()).then(l=>{
|
||
|
|
||
|
var cb;
|
||
|
cb=(entry,ls,path)=>{
|
||
|
ls.forEach(m=>{
|
||
|
if(m.IsFile)
|
||
|
{
|
||
|
var sz=0;
|
||
|
var unit="bytes";
|
||
|
|
||
|
if(m.Length < 1024)
|
||
|
{
|
||
|
sz = m.Length;
|
||
|
unit = "bytes";
|
||
|
}else if(m.Length < (1024 * 1024))
|
||
|
{
|
||
|
sz = Math.round(m.Length / 1024);
|
||
|
unit = "kiB";
|
||
|
}else if(m.Length < (1024*1024*1024))
|
||
|
{
|
||
|
sz = Math.round(m.Length / (1024*1024));
|
||
|
unit = "MiB";
|
||
|
}else if(m.Length < (1024*1024*1024*1024))
|
||
|
{
|
||
|
sz = Math.round(m.Length / (1024*1024*1024));
|
||
|
unit = "GiB";
|
||
|
}else{
|
||
|
sz = Math.round(m.Length / (1024*1024*1024*1024));
|
||
|
unit = "TiB";
|
||
|
}
|
||
|
|
||
|
var item3 = {
|
||
|
Name: m.Name,
|
||
|
IsFile: true,
|
||
|
Entries: [],
|
||
|
Path: `./api/v1/File?key=${localStorage.getItem('key')}&hash=${m.Hash}&device=${deviceId}`,
|
||
|
Size: sz,
|
||
|
Unit: unit
|
||
|
};
|
||
|
entry.push(item3);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var item4 = {
|
||
|
Name: m.Name,
|
||
|
IsFile: false,
|
||
|
Entries: [],
|
||
|
Path: `${path}/${m.Name}`,
|
||
|
Size: 0,
|
||
|
Unit: "bytes"
|
||
|
};
|
||
|
|
||
|
entry.push(item4);
|
||
|
cb(item4.Entries,m.SubEntries,`${path}/${m.Name}`);
|
||
|
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
cb(item2.Entries,l.BackupData,`/${deviceName}/${backupName}`);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
gopath();
|
||
|
}
|
||
|
});
|
||
|
loginNav.innerText = "Logout";
|
||
|
loginLink.innerText = "Logout";
|
||
|
loginNav.href="#logout";
|
||
|
loginLink.href = "#logout";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
handleLoggedIn();
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|