Hide some ENV values.
This commit is contained in:
@@ -46,6 +46,11 @@ hr {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.is-masked {
|
||||
color: transparent !important;
|
||||
text-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
* {
|
||||
unicode-bidi: plaintext;
|
||||
@@ -94,6 +99,10 @@ hr {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.is-masked {
|
||||
text-shadow: 0 0 8px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.is-borderless {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-12 is-clearfix">
|
||||
<span class="title is-4">Environment Variables</span>
|
||||
<span id="env_page_title" class="title is-4">Environment Variables</span>
|
||||
|
||||
<div class="is-pulled-right">
|
||||
<div class="field is-grouped">
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
|
||||
<div class="column is-12" v-if="toggleForm">
|
||||
<form @submit.prevent="addVariable">
|
||||
<form id="env_add_form" @submit.prevent="addVariable">
|
||||
<div class="field is-grouped">
|
||||
<div class="control is-expanded">
|
||||
<input class="input" type="text" placeholder="Key" v-model="form_key">
|
||||
@@ -40,6 +40,12 @@
|
||||
<div class="control is-expanded">
|
||||
<input class="input" type="text" placeholder="Value" v-model="form_value">
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-danger" type="button"
|
||||
v-tooltip="'Cancel'" @click="form_key=null; form_value=null; toggleForm=false">
|
||||
<span class="icon"><i class="fas fa-cancel"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-primary" type="submit" :disabled="!form_key || !form_value">
|
||||
<span class="icon"><i class="fas fa-save"></i></span>
|
||||
@@ -61,8 +67,17 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="env in envs" :key="env.key">
|
||||
<td class="has-text-left">{{ env.key }}</td>
|
||||
<td class="has-text-left">{{ env.value }}</td>
|
||||
<td class="has-text-left">
|
||||
{{ env.key }}
|
||||
<div class="is-pulled-right" v-if="env.mask">
|
||||
<span class="icon is-small has-tooltip" v-tooltip="'The value of this key is masked.'">
|
||||
<i class="fas fa-lock"></i>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="has-text-left" :class="{ 'is-masked': env.mask, 'is-unselectable': env.mask }">
|
||||
{{ env.value }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="field is-grouped" style="justify-content: center">
|
||||
<div class="control">
|
||||
@@ -72,6 +87,13 @@
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control" v-if="copyAPI">
|
||||
<button class="button is-small is-warning" @click="copyValue(env)">
|
||||
<span class="icon">
|
||||
<i class="fas fa-copy"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-small is-danger" @click="deleteEnv(env)">
|
||||
<span class="icon">
|
||||
@@ -84,6 +106,11 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="is-hidden-mobile">
|
||||
<Message message_class="is-info" title="Informational">
|
||||
Some variables values are masked for security reasons. If you need to see the value, click on edit.
|
||||
</Message>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,6 +118,7 @@
|
||||
|
||||
<script setup>
|
||||
import request from "~/utils/request.js";
|
||||
import {awaitElement} from "~/utils/index.js";
|
||||
|
||||
useHead({title: 'Environment Variables'})
|
||||
|
||||
@@ -99,6 +127,7 @@ const toggleForm = ref(false)
|
||||
const form_key = ref(null)
|
||||
const form_value = ref(null)
|
||||
const file = ref('.env')
|
||||
const copyAPI = navigator.clipboard
|
||||
|
||||
const loadContent = async () => {
|
||||
envs.value = []
|
||||
@@ -150,4 +179,19 @@ const editEnv = (env) => {
|
||||
form_value.value = env.value
|
||||
toggleForm.value = true
|
||||
}
|
||||
|
||||
const copyValue = (env) => navigator.clipboard.writeText(env.value)
|
||||
|
||||
watch(toggleForm, (value) => {
|
||||
if (!value) {
|
||||
form_key.value = null
|
||||
form_value.value = null
|
||||
} else {
|
||||
awaitElement('#env_page_title', (_, el) => el.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start',
|
||||
inline: 'nearest'
|
||||
}))
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -41,4 +41,22 @@ const humanFileSize = (bytes = 0, showUnit = true, decimals = 2, mod = 1000) =>
|
||||
return `${(bytes / (mod ** factor)).toFixed(decimals)}${showUnit ? sz[factor] : ''}`;
|
||||
}
|
||||
|
||||
export {ag_set, ag, humanFileSize}
|
||||
const awaitElement = (sel, callback) => {
|
||||
let interval = undefined;
|
||||
|
||||
let $elm = document.querySelector(sel)
|
||||
|
||||
if ($elm) {
|
||||
return callback(sel, $elm);
|
||||
}
|
||||
|
||||
interval = setInterval(() => {
|
||||
let $elm = document.querySelector(sel);
|
||||
if ($elm) {
|
||||
clearInterval(interval);
|
||||
callback(sel, $elm);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
export {ag_set, ag, humanFileSize, awaitElement}
|
||||
|
||||
@@ -17,6 +17,11 @@ final class Env
|
||||
{
|
||||
public const string URL = '%{api.prefix}/system/env';
|
||||
|
||||
private const array MASK = [
|
||||
'WS_API_KEY',
|
||||
'WS_CACHE_URL'
|
||||
];
|
||||
|
||||
private EnvFile $envfile;
|
||||
|
||||
public function __construct()
|
||||
@@ -43,6 +48,7 @@ final class Env
|
||||
$response['data'][] = [
|
||||
'key' => $key,
|
||||
'value' => $val,
|
||||
'mask' => in_array($key, self::MASK),
|
||||
'urls' => [
|
||||
'self' => (string)$request->getUri()->withPath(parseConfigValue(self::URL . '/' . $key)),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user