Hide some ENV values.
This commit is contained in:
@@ -46,6 +46,11 @@ hr {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-masked {
|
||||||
|
color: transparent !important;
|
||||||
|
text-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
* {
|
* {
|
||||||
unicode-bidi: plaintext;
|
unicode-bidi: plaintext;
|
||||||
@@ -94,6 +99,10 @@ hr {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-masked {
|
||||||
|
text-shadow: 0 0 8px rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-borderless {
|
.is-borderless {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="columns is-multiline">
|
<div class="columns is-multiline">
|
||||||
<div class="column is-12 is-clearfix">
|
<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="is-pulled-right">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column is-12" v-if="toggleForm">
|
<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="field is-grouped">
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<input class="input" type="text" placeholder="Key" v-model="form_key">
|
<input class="input" type="text" placeholder="Key" v-model="form_key">
|
||||||
@@ -40,6 +40,12 @@
|
|||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<input class="input" type="text" placeholder="Value" v-model="form_value">
|
<input class="input" type="text" placeholder="Value" v-model="form_value">
|
||||||
</div>
|
</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">
|
<div class="control">
|
||||||
<button class="button is-primary" type="submit" :disabled="!form_key || !form_value">
|
<button class="button is-primary" type="submit" :disabled="!form_key || !form_value">
|
||||||
<span class="icon"><i class="fas fa-save"></i></span>
|
<span class="icon"><i class="fas fa-save"></i></span>
|
||||||
@@ -61,8 +67,17 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="env in envs" :key="env.key">
|
<tr v-for="env in envs" :key="env.key">
|
||||||
<td class="has-text-left">{{ env.key }}</td>
|
<td class="has-text-left">
|
||||||
<td class="has-text-left">{{ env.value }}</td>
|
{{ 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>
|
<td>
|
||||||
<div class="field is-grouped" style="justify-content: center">
|
<div class="field is-grouped" style="justify-content: center">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
@@ -72,6 +87,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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">
|
<div class="control">
|
||||||
<button class="button is-small is-danger" @click="deleteEnv(env)">
|
<button class="button is-small is-danger" @click="deleteEnv(env)">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
@@ -84,6 +106,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -91,6 +118,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import request from "~/utils/request.js";
|
import request from "~/utils/request.js";
|
||||||
|
import {awaitElement} from "~/utils/index.js";
|
||||||
|
|
||||||
useHead({title: 'Environment Variables'})
|
useHead({title: 'Environment Variables'})
|
||||||
|
|
||||||
@@ -99,6 +127,7 @@ const toggleForm = ref(false)
|
|||||||
const form_key = ref(null)
|
const form_key = ref(null)
|
||||||
const form_value = ref(null)
|
const form_value = ref(null)
|
||||||
const file = ref('.env')
|
const file = ref('.env')
|
||||||
|
const copyAPI = navigator.clipboard
|
||||||
|
|
||||||
const loadContent = async () => {
|
const loadContent = async () => {
|
||||||
envs.value = []
|
envs.value = []
|
||||||
@@ -126,7 +155,7 @@ const deleteEnv = async (env) => {
|
|||||||
|
|
||||||
const addVariable = async () => {
|
const addVariable = async () => {
|
||||||
const key = form_key.value.toUpperCase()
|
const key = form_key.value.toUpperCase()
|
||||||
|
|
||||||
if (!key.startsWith('WS_')) {
|
if (!key.startsWith('WS_')) {
|
||||||
alert('Key must start with WS_')
|
alert('Key must start with WS_')
|
||||||
return
|
return
|
||||||
@@ -150,4 +179,19 @@ const editEnv = (env) => {
|
|||||||
form_value.value = env.value
|
form_value.value = env.value
|
||||||
toggleForm.value = true
|
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>
|
</script>
|
||||||
|
|||||||
@@ -41,4 +41,22 @@ const humanFileSize = (bytes = 0, showUnit = true, decimals = 2, mod = 1000) =>
|
|||||||
return `${(bytes / (mod ** factor)).toFixed(decimals)}${showUnit ? sz[factor] : ''}`;
|
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';
|
public const string URL = '%{api.prefix}/system/env';
|
||||||
|
|
||||||
|
private const array MASK = [
|
||||||
|
'WS_API_KEY',
|
||||||
|
'WS_CACHE_URL'
|
||||||
|
];
|
||||||
|
|
||||||
private EnvFile $envfile;
|
private EnvFile $envfile;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -43,6 +48,7 @@ final class Env
|
|||||||
$response['data'][] = [
|
$response['data'][] = [
|
||||||
'key' => $key,
|
'key' => $key,
|
||||||
'value' => $val,
|
'value' => $val,
|
||||||
|
'mask' => in_array($key, self::MASK),
|
||||||
'urls' => [
|
'urls' => [
|
||||||
'self' => (string)$request->getUri()->withPath(parseConfigValue(self::URL . '/' . $key)),
|
'self' => (string)$request->getUri()->withPath(parseConfigValue(self::URL . '/' . $key)),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user