');
+
+ for (const [key,value] of Object.entries(data)) {
+ $(table).append(`
${DOMPurify.sanitize(key)}
${DOMPurify.sanitize(value)}
`);
+ }
+
+ callPopup(table.outerHTML, 'text');
+}
+
export let secret_state = {};
export async function writeSecret(key, value) {
@@ -64,4 +87,8 @@ export async function readSecretState() {
} catch {
console.error('Could not read secrets file');
}
-}
\ No newline at end of file
+}
+
+jQuery(() => {
+ $('#viewSecrets').on('click', viewSecrets);
+});
\ No newline at end of file
diff --git a/public/style.css b/public/style.css
index 017c4ded7..0d415f11d 100644
--- a/public/style.css
+++ b/public/style.css
@@ -109,6 +109,24 @@ body {
background-clip: content-box;
}
+table.responsiveTable {
+ width: 100%;
+ margin: 10px 0;
+}
+
+.responsiveTable tr {
+ display: flex;
+}
+
+.responsiveTable,
+.responsiveTable th,
+.responsiveTable td {
+ flex: 1;
+ border: 1px solid;
+ border-collapse: collapse;
+ word-break: break-all;
+ padding: 5px;
+}
.sysHR {
border-top: 2px solid grey;
diff --git a/readme.md b/readme.md
index 1fbfae648..5ac168377 100644
--- a/readme.md
+++ b/readme.md
@@ -125,6 +125,17 @@ Get in touch with the developers directly:
1. Run the `start.sh` script.
2. Enjoy.
+## API keys management
+
+SillyTavern saves your API keys to a `secrets.json` file in the server directory.
+
+By default they will not be exposed to a frontend after you enter them and reload the page.
+
+In order to enable viewing your keys by clicking a button in the API block:
+
+1. Set the value of `allowKeysExposure` to `true` in `config.conf` file.
+2. Restart the SillyTavern server.
+
## Remote connections
Most often this is for people who want to use SillyTavern on their mobile phones while at home.
diff --git a/server.js b/server.js
index 401f67d36..7aee9bb00 100644
--- a/server.js
+++ b/server.js
@@ -77,6 +77,7 @@ const whitelistMode = config.whitelistMode;
const autorun = config.autorun && !cliArguments.ssl;
const enableExtensions = config.enableExtensions;
const listen = config.listen;
+const allowKeysExposure = config.allowKeysExposure;
const axios = require('axios');
const tiktoken = require('@dqbd/tiktoken');
@@ -2894,6 +2895,27 @@ app.post('/generate_horde', jsonParser, async (request, response) => {
}
});
+app.post('/viewsecrets', jsonParser, async (_, response) => {
+ if (!allowKeysExposure) {
+ console.error('secrets.json could not be viewed unless the value of allowKeysExposure in config.conf is set to true');
+ return response.sendStatus(403);
+ }
+
+ if (!fs.existsSync(SECRETS_FILE)) {
+ console.error('secrets.json does not exist');
+ return response.sendStatus(404);
+ }
+
+ try {
+ const fileContents = fs.readFileSync(SECRETS_FILE);
+ const secrets = JSON.parse(fileContents);
+ return response.send(secrets);
+ } catch (error) {
+ console.error(error);
+ return response.sendStatus(500);
+ }
+});
+
function writeSecret(key, value) {
if (!fs.existsSync(SECRETS_FILE)) {
const emptyFile = JSON.stringify({});