🧑‍💻 Add UI for generating API tokens (/token)

This commit is contained in:
2023-02-20 01:03:52 +01:00
parent b254847e74
commit 0e5e693422
5 changed files with 172 additions and 1 deletions

View File

@ -20,7 +20,9 @@ const route = useRoute();
const routeName = computed(() => route.name);
const isDataView = computed(() => {
return (
routeName.value != "title.settings" && routeName.value != "title.login"
routeName.value != "title.settings" &&
routeName.value != "title.login" &&
routeName.value != "title.token"
);
});
</script>

View File

@ -0,0 +1,21 @@
<!-- From https://github.com/lucide-icons/lucide -->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
<path d="M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"></path>
<path d="M16 4h2a2 2 0 0 1 2 2v4"></path>
<path d="M21 14H11"></path>
<path d="m15 10-4 4 4 4"></path>
</svg>
</template>

View File

@ -5,6 +5,7 @@ import SubstitutionView from "../views/SubstitutionView.vue";
import HistoryView from "../views/HistoryView.vue";
import SettingsView from "../views/SettingsView.vue";
import LoginView from "../views/LoginView.vue";
import TokenView from "../views/TokenView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@ -38,6 +39,11 @@ const router = createRouter({
name: "title.login",
component: LoginView,
},
{
path: "/token",
name: "title.token",
component: TokenView,
},
],
});

View File

@ -6,6 +6,7 @@ export const strings = {
history: "History",
settings: "Settings",
login: "Login",
token: "Token",
},
settings: {
heading: {
@ -88,6 +89,9 @@ export const strings = {
noHistory: "No substitutions for this day have changed yet",
},
},
token: {
header: "Generate API-Token",
},
},
de: {
title: {

138
src/views/TokenView.vue Normal file
View File

@ -0,0 +1,138 @@
<script setup>
import { ref } from "vue";
import clipboardCopyIcon from "../components/icons/clipboard-copy-icon.vue";
const password = ref("");
const token = ref("");
const token_element = ref("");
function generate() {
fetch(`/api/token?password=${password.value}`, { method: "post" })
.then((e) => {
if (e.status == 401) {
alert("Invalid password!");
return;
} else if (e.status != 200) {
alert("Failed requesting API-Token!");
return;
}
return e.json();
})
.then((e) => (token.value = e));
}
function copy() {
const element = token_element.value;
element.select();
element.setSelectionRange(0, 99999);
document.execCommand("copy");
}
</script>
<template>
<div class="login">
<h1>{{ $t("token.header") }}</h1>
<div class="form" v-if="!token">
<input
type="password"
name="password"
autocomplete="current-password"
placeholder="Password"
v-model="password"
/>
<button type="submit" @click="generate">Generate</button>
</div>
<div class="token" @click="copy" v-else>
<input
type="text"
readonly
ref="token_element"
v-bind:value="token.token"
/>
<clipboardCopyIcon />
</div>
</div>
</template>
<style scoped>
.login {
padding: 50px 10px;
}
.login {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: Arial, Helvetica, sans-serif;
color: var(--text-color);
}
.form {
display: flex;
flex-direction: column;
gap: 10px;
width: 250px;
}
.form * {
height: 30px;
}
input {
border: 0px;
outline: none;
background-color: var(--element-color);
padding: 0px 5px;
font-size: 15px;
margin: 5px 0;
border: 2px solid var(--element-border-input);
border-radius: 5px;
transition: 0.2s all;
}
input:hover,
input:focus {
background-color: var(--element-color-hover);
border-radius: 8px;
}
button {
outline: none;
padding: 5px 5px;
border: 2px solid var(--element-border-action);
border-radius: 5px;
font-size: 15px;
color: var(--text-color);
background-color: var(--element-color);
cursor: pointer;
transition: 0.2s all;
}
button:hover {
background-color: var(--element-color-hover);
border-radius: 8px;
}
.token {
font-size: 18px;
padding: 20px;
border: 2px dashed gray;
cursor: pointer;
border-radius: 6px;
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
.token input {
border: unset;
outline: unset;
font-size: 16px;
cursor: pointer;
font-family: monospace;
width: 360px;
max-width: 60vw;
}
</style>