add whole app LOL

Co-authored-by: Alpisc <Alpisc@users.noreply.github.com>
This commit is contained in:
Mystikfluu
2023-01-14 21:20:37 +01:00
co-authored by Alpisc
parent 981a2641c0
commit ddf53e5908
13 changed files with 695 additions and 146 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

+22 -22
View File
@@ -6,32 +6,32 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title id="pageTitle">IPass - x.x.x</title>
<script type="module" src="/main.js"></script>
<script type="module" src="/pwprompt.js"></script>
</head>
<body>
<h1>IPass</h1>
<div class="container">
<table>
<thead>
<tr>
<td>Entry name</td>
<td>Username</td>
<td>Password</td>
</tr>
<tr>
<td class="entry_name">
ENTRY-NAME-HERE
</td>
<td class="hidden entry_user">
<input type="text" name="" id="" value="ENTRY-USERNAME-HERE">
</td>
<td class="hidden entry_pass">
<input type="text" name="" id="" value="ENTRY-PASSWORD-HERE">
</td>
</tr>
</thead>
</table>
<p id="lockLabel">Locked</p>
<img alt="Lock" id="lockImg" src="/images/security_lock_locked.png" height=50 width=50></img>
<br>
<div id="table_div">
<div id="table_entries">
<div>Entry name</div>
<div class="entry_name" id="createEntry_name"><input type="text" placeholder="New Entry Name"></div>
</div>
<div id="table_users">
<div>Username</div>
<div class="entry_user" id="createEntry_user"><input type="text" placeholder="New Username"></div>
</div>
<div id="table_pwds">
<div>Password</div>
<div class="entry_pass" id="createEntry_pass"><input type="password" placeholder="New Password"></div>
</div>
<div id="table_actions">
<div>Action</div>
<div class="button" id="createEntry_actions"><button>Create</button></div>
</div>
</div>
</body>
</html>
+277 -17
View File
@@ -1,23 +1,283 @@
const { invoke } = window.__TAURI__.tauri;
let greetInputEl;
let greetMsgEl;
let master_pw;
let lock_status = true;
async function greet() {
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
}
async function updateTitle() {
document.getElementById("pageTitle").innerText = `IPass - ${await invoke("get_version")}`;
}
// async function greet() {
// // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
// greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
// }
window.addEventListener("DOMContentLoaded", () => {
updateTitle()
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document
.querySelector("#greet-button")
.addEventListener("click", () => greet());
document.getElementById("lockImg").addEventListener("click",toggleLock);
startup();
});
async function startup() {
document.querySelector("#createEntry_actions > button").addEventListener("click",createEntry);
let entries = await invoke("get_entries");
console.log(entries);
for(let i = 0; i < entries.length; i++) {
buildEntry(entries[i]);
}
for (let input of document.querySelectorAll('input[readonly]')) {
input.addEventListener('click', async function() {
if(!input.hasAttribute("readonly"))return
if(input.getAttribute("type")!="text" && lock_status)return
let to_copy = input.value
if(!lock_status) {
let isUsername = input.parentElement.classList.contains("entry_user")
let entry_name = input.parentElement.id.slice(0,input.parentElement.id.length-5)
console.log(entry_name,input.parentElement.id)
let info = await invoke("get_entry",{
name: entry_name,
mpw: await get_pw()
})
if(isUsername) {
to_copy = info[0]
} else {
if(input.parentElement.classList.contains("entry_name")) {
to_copy = entry_name
} else {
to_copy = info[1]
}
}
}
navigator.clipboard.writeText(to_copy).then(function() {
let originalColor = input.style.borderColor;
input.style.borderColor = "lightgreen";
setTimeout(function(){
input.style.borderColor = originalColor;
},250)
console.log('Text copied to clipboard');
}, function(err) {
let originalColor = input.style.borderColor;
input.style.borderColor = "red";
setTimeout(function(){
input.style.borderColor = originalColor;
},500)
console.error('Failed to copy text: ', err);
});
});
}
}
function buildEntry(entry) {
let nameDiv = document.createElement("div");
nameDiv.setAttribute("class", "entry_name");
nameDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_name`)
let nameInput = document.createElement("input");
nameInput.setAttribute("type", "text");
nameInput.setAttribute("placeholder", "New Entry Name");
nameInput.setAttribute("value", entry);
nameInput.setAttribute("readonly", true);
nameInput.setAttribute("unselectable", "on")
nameDiv.appendChild(nameInput);
let userDiv = document.createElement("div");
userDiv.setAttribute("class", "entry_user");
userDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_user`)
let userInput = document.createElement("input");
userInput.setAttribute("type", "password");
userInput.setAttribute("placeholder", "New Username");
userInput.setAttribute("value", "PLACEHOLDER");
userInput.setAttribute("readonly", true);
userInput.setAttribute("unselectable", "on")
userDiv.appendChild(userInput);
let passDiv = document.createElement("div");
passDiv.setAttribute("class", "entry_pass");
passDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_pass`)
let passInput = document.createElement("input");
passInput.setAttribute("type", "password");
passInput.setAttribute("placeholder", "New Password");
passInput.setAttribute("value", "PLACEHOLDER!");
passInput.setAttribute("readonly", true);
passInput.setAttribute("unselectable", "on")
passDiv.appendChild(passInput);
let showButton = document.createElement("button");
showButton.innerText = "Show";
showButton.addEventListener("click",showEntry.bind(showButton, entry),false);
showButton.setAttribute("class", "showbutton");
let editButton = document.createElement("button");
editButton.innerText = "Edit";
editButton.addEventListener("click", editEntry.bind(editButton, entry), false);
editButton.setAttribute("class", "editbutton");
let actionDiv = document.createElement("div")
actionDiv.appendChild(showButton)
actionDiv.appendChild(editButton)
actionDiv.setAttribute("id",`${entry.replaceAll(" ","-")}_actions`)
document.getElementById("table_entries").appendChild(nameDiv)
document.getElementById("table_users").appendChild(userDiv)
document.getElementById("table_pwds").appendChild(passDiv)
document.getElementById("table_actions").appendChild(actionDiv)
}
async function editEntry(entry) {
let entry_user = document.querySelector(`#${entry.replaceAll(" ","-")}_user > input`);
let entry_pass = document.querySelector(`#${entry.replaceAll(" ","-")}_pass > input`);
let entry_name = document.querySelector(`#${entry.replaceAll(" ","-")}_name > input`);
let show_button = document.querySelector(`#${entry.replaceAll(" ","-")}_actions > .showbutton`);
if(this.innerText == "Edit") {
let info = await invoke("get_entry",{
name: entry_name.value,
mpw: await get_pw()
})
entry_user.value = info[0];
entry_pass.value = info[1];
entry_user.removeAttribute("readonly");
entry_user.setAttribute("unselectable", "off")
entry_user.type = "text";
entry_pass.removeAttribute("readonly");
entry_pass.setAttribute("unselectable", "off")
entry_pass.type = "text";
entry_name.removeAttribute("readonly");
entry_name.setAttribute("unselectable", "off")
show_button.disabled = true;
this.innerText = "Save";
this.Name = entry_name.value
} else {
//To Delete: this.Name
let isDeleted = await invoke("remove_entry", {name: this.Name})
if(!isDeleted) {
alert("Could not edit entry!")
return;
}
let success = await invoke("create_entry", {name: entry_name.value, username: entry_user.value, pw: entry_pass.value, mpw: await get_pw()});
if(!success) {
alert("Could not edit entry!")
return;
}
entry_user.setAttribute("readonly", true);
entry_user.setAttribute("unselectable", "off")
entry_user.type = "password"
entry_user.value = "PLACEHOLDER"
entry_pass.setAttribute("readonly", true);
entry_pass.setAttribute("unselectable", "off")
entry_pass.type = "password"
entry_pass.value = "PLACEHOLDER!"
entry_name.setAttribute("readonly", true);
entry_name.setAttribute("unselectable", "off")
show_button.disabled = false;
this.innerText = "Edit";
}
}
async function ask_pw() {
return await password_prompt("Enter your master password to proceed");
}
async function get_pw() {
let mpw = master_pw;
if(lock_status){
mpw = await ask_pw();
}
return mpw;
}
async function showEntry(entry_name) {
let entry_user = document.querySelector(`#${entry_name.replaceAll(" ","-")}_user > input`);
let entry_pass = document.querySelector(`#${entry_name.replaceAll(" ","-")}_pass > input`);
if(this.innerText == "Show"){
let info = await invoke("get_entry",{
name: entry_name,
mpw: await get_pw()
})
entry_user.value = info[0];
entry_pass.value = info[1];
entry_user.type = "text";
entry_pass.type = "text";
this.innerText = "Hide";
} else {
entry_user.value = "PLACEHOLDER";
entry_pass.value = "PLACEHOLDER!";
entry_user.type = "password";
entry_pass.type = "password";
this.innerText = "Show";
}
}
async function createEntry() {
let entryNameField = document.querySelector("#createEntry_name > input");
let entryUserField = document.querySelector("#createEntry_user > input");
let entryPassField = document.querySelector("#createEntry_pass > input");
if(entryNameField.value == "" || entryUserField.value == "") {
alert("Not all needed fields filled out!");
return;
}
if(entryPassField.value == "") {
if(!(confirm("No password provided, do you want to generate a secure password?"))) {
alert("Cant create entry without password!");
return;
}
entryPassField.value = await invoke("random_password");
}
let mpw = await get_pw()
let success = await invoke("create_entry", {name: entryNameField.value, username: entryNameField.value, pw: entryPassField.value, mpw: mpw});
if(success) {
alert("Successfully created entry!");
buildEntry(entryNameField.value)
entryNameField.value = ""
entryUserField.value = ""
entryPassField.value = ""
} else {
alert("A critical error occured during entry creation");
}
}
async function toggleLock() {
let txt = (lock_status && "Unlocked") || "Locked";
let src = (lock_status && "/images/security_lock_unlocked.png") || "/images/security_lock_locked.png";
if(lock_status){
master_pw = await ask_pw();
console.log(master_pw)
if(master_pw == "" || master_pw == null)return;
}
document.getElementById("lockLabel").innerText = txt;
document.getElementById("lockImg").src = src;
lock_status = !lock_status;
}
+59
View File
@@ -0,0 +1,59 @@
window.password_prompt = async function(label_message, button_message, arg3, arg4, arg5) {
return new Promise((res,rej) => {
let callback,width,height;
if (typeof label_message !== "string") label_message = "Password:";
if (typeof button_message !== "string") button_message = "Submit";
if (typeof arg3 === "function") {
callback = arg3;
}
else if (typeof arg3 === "number" && typeof arg4 === "number" && typeof arg5 === "function") {
width = arg3;
height = arg4;
callback = arg5;
}
if (typeof width !== "number") width = 200;
if (typeof height !== "number") height = 100;
if (typeof callback !== "function") callback = function(){};
let submit = function() {
callback(input.value);
document.body.removeChild(div);
window.removeEventListener("resize", resize, false);
res(input.value)
};
let resize = function() {
div.style.left = ((window.innerWidth / 2) - (width / 2)) + "px";
div.style.top = ((window.innerHeight / 2) - (height / 2)) + "px";
};
let div = document.createElement("div");
div.id = "password_prompt";
let label = document.createElement("label");
label.id = "password_prompt_label";
label.innerHTML = label_message;
label.for = "password_prompt_input";
div.appendChild(label);
div.appendChild(document.createElement("br"));
let input = document.createElement("input");
input.id = "password_prompt_input";
input.type = "password";
input.addEventListener("keyup", function(event) {
if (event.key == "Enter") submit();
}, false);
div.appendChild(input);
div.appendChild(document.createElement("br"));
let button = document.createElement("button");
button.innerHTML = button_message;
button.addEventListener("click", submit, false);
div.appendChild(button);
document.body.appendChild(div);
window.addEventListener("resize", resize, false);
})
};
+92 -38
View File
@@ -1,5 +1,5 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-family: MonoLisa, Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
@@ -16,7 +16,6 @@
--fg-color: #303034; /* post background */
--bg-color: #1B1B1E; /* page background etc */
--text-color: #ECEAF1; /* text */
--blue-ish: #587291; /* buttons etc */
color: var(--text-color);
background-color: var(--bg-color);
@@ -28,48 +27,55 @@ a:hover {
input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
color: var(--text-color);
background-color: var(--fg-color);
.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.row {
display: flex;
justify-content: center;
}
a {
border-radius: 8px;
border: 1px solid transparent;
font-weight: 500;
color: #646cff;
text-decoration: inherit;
font-family: inherit;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
@media only screen and (max-width: 600px) {
input,
button {
padding: 4px 8px;
font-size: 0.8em;
}
}
@media only screen and (min-width: 600px) and (max-width: 900px) {
input,
button {
padding: 5px 10px;
font-size: 0.9em;
}
}
@media only screen and (min-width: 900px) {
input,
button {
padding: 6.4px 12.8px;
font-size: 1em;
}
}
tr {
width: 50%;
}
input:not([readonly]){
color: var(--fg-color);
background-color: var(--text-color);
}
h1 {
text-align: center;
}
input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
button {
cursor: pointer;
}
@@ -83,6 +89,54 @@ button {
outline: none;
}
#greet-input {
margin-right: 5px;
#lockImg {
position: absolute;
top: 1em;
right: 1em;
}
#lockLabel {
position: absolute;
top: 1em;
right: 4em;
}
#table_div {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
}
.entry_name,.entry_user,.entry_pass {
width: 70%;
}
.entry_name > input,.entry_user > input,.entry_pass > input {
width: 100%;
}
.table_actions>div>button {
height: 40%;
}
input[type="password"] {
user-select: none;
}
#password_prompt {
background: white;
color: black;
border: 1px solid black;
width: 50%;
height: 25%;
position: fixed;
left: 25%;
top: 25%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
border: 3px double var(--fg-color);
border-radius: 5%;
}