feat-user_settings): add ability to import and delete an identity, formatting

This commit is contained in:
Tasia Iso 2024-03-21 20:10:35 +01:00
parent 5474c5a101
commit 2a928dcafc
10 changed files with 109 additions and 40 deletions

View File

@ -1,4 +1 @@
{ {"type": "tildefriends-app", "emoji": "⚙️"}
"type": "tildefriends-app",
"emoji": "⚙️"
}

View File

@ -9,13 +9,19 @@ tfrpc.register(async function createID(id) {
tfrpc.register(async function getPrivateKey(id) { tfrpc.register(async function getPrivateKey(id) {
return bip39Words(await ssb.getPrivateKey(id)); return bip39Words(await ssb.getPrivateKey(id));
}); });
tfrpc.register(async function addID(id) {
return await ssb.addIdentity(bip39Bytes(id));
});
tfrpc.register(async function deleteID(id) {
return await ssb.deleteIdentity(id);
});
tfrpc.register(async function getThemes() { tfrpc.register(async function getThemes() {
// TODO // TODO
return ['solarized', 'gruvbox', 'light']; return ['solarized', 'gruvbox', 'light'];
}); });
tfrpc.register(async function setTheme() { tfrpc.register(async function setTheme() {
// TODO // TODO
console.warn("setTheme called - not implemented") console.warn('setTheme called - not implemented');
return null; return null;
}); });
tfrpc.register(async function reload() { tfrpc.register(async function reload() {

View File

@ -1 +0,0 @@
/* */

View File

@ -1 +0,0 @@
/* */

View File

@ -22,7 +22,7 @@ class TfDeleteAccountButtonElement extends LitElement {
render() { render() {
return html` return html`
<link rel="stylesheet" href="/static/tildefriends-v1.css"/> <link rel="stylesheet" href="/static/tildefriends-v1.css" />
<span>This action is irreversible !</span> <span>This action is irreversible !</span>

View File

@ -20,7 +20,7 @@ class TfIdentityManagerElement extends LitElement {
async createIdentity() { async createIdentity() {
try { try {
let id = await tfrpc.rpc.createID(); const id = await tfrpc.rpc.createID();
alert('Successfully created: ' + id); alert('Successfully created: ' + id);
await tfrpc.rpc.reload(); await tfrpc.rpc.reload();
} catch (err) { } catch (err) {
@ -28,13 +28,50 @@ class TfIdentityManagerElement extends LitElement {
} }
} }
async importIdentity() {
const words = this.renderRoot?.querySelector('#import-id-textarea').value;
if (!words) return;
try {
const newID = await tfrpc.rpc.addID(words);
if (newID) alert('Successfully imported a new identity');
else alert('This identity already exists or is invalid.');
await tfrpc.rpc.reload();
} catch (err) {
alert('Error importing identity: ' + err);
}
}
async exportIdentity(id) { async exportIdentity(id) {
alert('Your private key is:\n' + (await tfrpc.rpc.getPrivateKey(id))); alert(
'Your private key is:\n' +
(await tfrpc.rpc.getPrivateKey(id)) +
'\nDo not share it with anyone!'
);
}
async deleteIdentity(id) {
try {
if (
prompt(
'Are you sure you want to delete "' +
id +
'"? It cannot be recovered without the exported phrase.\\n\\nEnter the word "DELETE" to confirm you wish to delete it.'
) === 'DELETE'
) {
if (await tfrpc.rpc.deleteID(id)) {
alert('Successfully deleted ID: ' + id);
}
await tfrpc.rpc.reload();
}
} catch (e) {
alert('Error deleting ID: ' + e);
}
} }
render() { render() {
return html` return html` <link rel="stylesheet" href="/static/tildefriends-v1.css" />
<link rel="stylesheet" href="/static/tildefriends-v1.css"/>
<style> <style>
.id-span { .id-span {
font-family: monospace; font-family: monospace;
@ -43,27 +80,37 @@ class TfIdentityManagerElement extends LitElement {
</style> </style>
<h4>Create a new identity</h4> <h4>Create a new identity</h4>
<button id="create-id" class="green" @click=${this.createIdentity}>Create Identity</button> <button id="create-id" class="green" @click=${this.createIdentity}>
Create Identity
</button>
<h4>Import an SSB Identity from 12 BIP39 English Words</h4> <h4>Import an SSB Identity from 12 BIP39 English Words</h4>
<textarea id="add-id" style="width: 100%" rows="4"></textarea> <textarea id="import-id-textarea" style="width: 100%" rows="4"></textarea>
<button class="green">[Not implemented] Import Identity</button> <button class="green" @click=${this.importIdentity}>
Import Identity
</button>
<h4>Warning !</h4> <h4>Warning !</h4>
<strong>Anybody that has access to your private key can gain total access over your account.</strong> <strong
<br><br> >Anybody that knows your private key can gain total access over your
account.</strong
>
<br /><br />
Tilde Friends' contributors will never ask you for your private key ! Tilde Friends' contributors will never ask you for your private key !
<ul> <ul>
${this.ids.map( ${this.ids.map(
(id) => (id) =>
html` html` <li>
<li> <button class="blue" @click=${() => this.exportIdentity(id)}>
<button class="blue" @click=${() => this.exportIdentity(id)}>Export Identity</button> Export Identity
<button class="red">[Not implemented] Delete Identity</button> </button>
<span class="id-span">${id}</span> <button class="red" @click=${() => this.deleteIdentity(id)}>
</li>` Delete Identity
)} </button>
<span class="id-span">${id}</span>
</li>`
)}
</ul>`; </ul>`;
} }
} }

View File

@ -37,7 +37,7 @@ class TfPasswordFormElement extends LitElement {
render() { render() {
return html` return html`
<link rel="stylesheet" href="/static/tildefriends-v1.css"/> <link rel="stylesheet" href="/static/tildefriends-v1.css" />
<style> <style>
.grid { .grid {
@ -48,19 +48,33 @@ class TfPasswordFormElement extends LitElement {
<div class="grid"> <div class="grid">
<label for="current">Current password:</label> <label for="current">Current password:</label>
<input type="password" id="current" name="current" autocomplete="current-password" /> <input
type="password"
id="current"
name="current"
autocomplete="current-password"
/>
<label for="new">Enter new password:</label> <label for="new">Enter new password:</label>
<input type="password" id="new" name="new" autocomplete="new-password" /> <input
type="password"
id="new"
name="new"
autocomplete="new-password"
/>
<label for="repeat">Repeat new password:</label> <label for="repeat">Repeat new password:</label>
<input type="password" id="repeat" name="repeat" autocomplete="new-password" /> <input
type="password"
id="repeat"
name="repeat"
autocomplete="new-password"
/>
</div> </div>
<button @click=${this.submitPassword} class="red"> <button @click=${this.submitPassword} class="red">
[Not implemented] Change my password [Not implemented] Change my password
</button> </button>
`; `;
} }
} }

View File

@ -26,12 +26,18 @@ class TfThemePickerElement extends LitElement {
render() { render() {
return html` return html`
<link rel="stylesheet" href="/static/tildefriends-v1.css"/> <link rel="stylesheet" href="/static/tildefriends-v1.css" />
<label for="theme">[Not implemented] Choose your theme:</label> <label for="theme">[Not implemented] Choose your theme:</label>
<select name="theme" ?hidden=${!this.themes?.length} @change=${this.changed}> <select
${(this.themes ?? []).map((id) => html`<option value=${id}>${id}</option>`)} name="theme"
?hidden=${!this.themes?.length}
@change=${this.changed}
>
${(this.themes ?? []).map(
(id) => html`<option value=${id}>${id}</option>`
)}
</select> </select>
`; `;
} }

View File

@ -18,8 +18,8 @@ body {
button, button,
.button, .button,
input[type=button], input[type='button'],
input[type=submit], input[type='submit'],
select { select {
border: none; border: none;
border-radius: 8px; border-radius: 8px;
@ -75,7 +75,8 @@ table {
width: 100%; width: 100%;
} }
td, th { td,
th {
border: 1px solid #ffffff40; border: 1px solid #ffffff40;
text-align: left; text-align: left;
padding: 8px; padding: 8px;