Files
nosys_libs/lockbox/vue/components/tabs/TabCreateUser.vue
2026-01-25 13:55:46 +10:00

125 lines
4.8 KiB
Vue

<script setup>
import { ref } from 'vue';
import { TabPanel} from '@headlessui/vue'
import * as secp from '@noble/secp256k1'
import { KeyIcon, ArrowPathIcon, ClipboardDocumentIcon } from '@heroicons/vue/24/solid'
import Card from '@/components/cards/Card.vue';
import CardHeader from '@/components/cards/CardHeader.vue';
import CardTitle from '@/components/cards/CardTitle.vue';
import CardDescription from '@/components/cards/CardDescription.vue';
import CardContent from '@/components/cards/CardContent.vue';
import Label from '@/components/labels/Label.vue';
import InputText from '@/components/inputs/InputText.vue';
import Button from '@/components/buttons/Button.vue';
import ToogleSwitch from '@/components/buttons/ToogleSwitch.vue';
const privateKeyInput = ref("")
const privateKeyB64 = ref("")
const publicKeyB64 = ref("")
const isTextEnabled = ref(true)
async function generate() {
var array = null
if (isTextEnabled.value){
const encoder = new TextEncoder();
const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(privateKeyInput.value));
array = new Uint8Array(hashBuffer);
privateKeyB64.value = btoa(String.fromCharCode(...array))
}else{
try {
const decoded = atob(privateKeyInput.value)
const bytes = new Uint8Array(decoded.length)
for (let i = 0; i < decoded.length; i++) {
bytes[i] = decoded.charCodeAt(i)
}
if (bytes.length !== 32) {
throw new Error('Tamanho inválido')
}
array = bytes
} catch (e) {
array = new Uint8Array(32)
crypto.getRandomValues(array)
privateKeyInput.value = btoa(String.fromCharCode(...array))
}
}
generatePublicKey(array)
}
function generatePublicKey(privateKeyBytes) {
const publicKeyBytes = secp.getPublicKey(privateKeyBytes)
publicKeyB64.value = btoa(String.fromCharCode(...publicKeyBytes))
}
function onSwitchChanged(newValue) {
privateKeyInput.value = ""
privateKeyB64.value = ""
publicKeyB64.value = ""
}
function copy(text){
navigator.clipboard.writeText(text)
}
</script>
<template>
<TabPanel>
<Card>
<CardHeader>
<CardTitle class="flex items-center gap-2 text-yellow-400">
<KeyIcon class="h-5 w-5" />
Create New User
</CardTitle>
<CardDescription class="text-slate-200">
Generate a new ECDSA keypair for user authentication
</CardDescription>
</CardHeader>
<CardContent class=" space-y-2">
<!-- Private key Characteres input -->
<div class="space-y-2">
<div class="flex flex-row gap-4">
<Label>Private Key</Label>
<ToogleSwitch v-model="isTextEnabled" @update:modelValue="onSwitchChanged"/>
<Label>Text Password</Label>
</div>
<div class="flex gap-2">
<InputText id="privateKey" type="password" v-model="privateKeyInput" placeholder="" class="border-gray-700 bg-slate-300 w-full"/>
<Button @click="generate()" class="gap-2">
<ArrowPathIcon class="h-4 w-4"/>
<span v-if="!privateKeyInput">Generate</span>
</Button>
<Button v-if="privateKeyInput" @click="copy(privateKeyInput)" class="flex items-center gap-2">
<ClipboardDocumentIcon class="h-4 w-4"/>
</Button>
</div>
</div>
<!-- Public Key -->
<div class="space-y-2">
<Label forId="publicKey" class="text-slate-300">Public Key</Label>
<div class="flex gap-2">
<InputText id="publicKey" type="text" v-model="publicKeyB64" placeholder="" class="border-gray-700 bg-slate-300 w-full"/>
<Button @click="copy(publicKeyB64)" class="flex items-center gap-2">
<ClipboardDocumentIcon class="h-4 w-4"/>
Copy
</Button>
</div>
</div>
<!-- Private Key -->
<div class="space-y-2" v-if="isTextEnabled">
<Label forId="privateKeyB64" class="text-slate-300">Private Key</Label>
<div class="flex gap-2">
<InputText id="privateKeyB64" type="password" v-model="privateKeyB64" placeholder="" class="border-gray-700 bg-slate-300 w-full"/>
<Button @click="copy(privateKeyB64)" class="flex items-center gap-2">
<ClipboardDocumentIcon class="h-4 w-4"/>
Copy
</Button>
</div>
</div>
</CardContent>
</Card>
</TabPanel>
</template>