mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-03 12:47:35 +01:00
Update module imports
This commit is contained in:
parent
a0e6030836
commit
0c8ccf1765
19
recover.js
19
recover.js
@ -1,7 +1,12 @@
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import yaml from 'yaml';
|
import yaml from 'yaml';
|
||||||
import storage from 'node-persist';
|
import storage from 'node-persist';
|
||||||
import * as users from './src/users.js';
|
import {
|
||||||
|
initUserStorage,
|
||||||
|
getPasswordSalt,
|
||||||
|
getPasswordHash,
|
||||||
|
toKey,
|
||||||
|
} from './src/users.js';
|
||||||
|
|
||||||
const userAccount = process.argv[2];
|
const userAccount = process.argv[2];
|
||||||
const userPassword = process.argv[3];
|
const userPassword = process.argv[3];
|
||||||
@ -22,7 +27,7 @@ async function initStorage() {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
await users.initUserStorage(dataRoot);
|
await initUserStorage(dataRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
@ -31,22 +36,22 @@ async function main() {
|
|||||||
/**
|
/**
|
||||||
* @type {import('./src/users').User}
|
* @type {import('./src/users').User}
|
||||||
*/
|
*/
|
||||||
const user = await storage.get(users.toKey(userAccount));
|
const user = await storage.get(toKey(userAccount));
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.error(`User "${userAccount}" not found.`);
|
console.error(`User "${userAccount}" not found.`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.enabled) {
|
if (!user.enabled) {
|
||||||
console.log('User is disabled. Enabling...');
|
console.log('User is disabled. Enabling...');
|
||||||
user.enabled = true;
|
user.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userPassword) {
|
if (userPassword) {
|
||||||
console.log('Setting new password...');
|
console.log('Setting new password...');
|
||||||
const salt = users.getPasswordSalt();
|
const salt = getPasswordSalt();
|
||||||
const passwordHash = users.getPasswordHash(userPassword, salt);
|
const passwordHash = getPasswordHash(userPassword, salt);
|
||||||
user.password = passwordHash;
|
user.password = passwordHash;
|
||||||
user.salt = salt;
|
user.salt = salt;
|
||||||
} else {
|
} else {
|
||||||
@ -55,7 +60,7 @@ async function main() {
|
|||||||
user.salt = '';
|
user.salt = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
await storage.setItem(users.toKey(userAccount), user);
|
await storage.setItem(toKey(userAccount), user);
|
||||||
console.log('User recovered. A program will exit now.');
|
console.log('User recovered. A program will exit now.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
server.js
60
server.js
@ -36,13 +36,27 @@ util.inspect.defaultOptions.maxStringLength = null;
|
|||||||
util.inspect.defaultOptions.depth = 4;
|
util.inspect.defaultOptions.depth = 4;
|
||||||
|
|
||||||
// local library imports
|
// local library imports
|
||||||
import * as loader from './src/plugin-loader.js';
|
import{ loadPlugins } from './src/plugin-loader.js';
|
||||||
import * as userModule from './src/users.js';
|
import {
|
||||||
|
initUserStorage,
|
||||||
|
getCsrfSecret,
|
||||||
|
getCookieSecret,
|
||||||
|
getCookieSessionName,
|
||||||
|
getAllEnabledUsers,
|
||||||
|
ensurePublicDirectoriesExist,
|
||||||
|
getUserDirectoriesList,
|
||||||
|
migrateSystemPrompts,
|
||||||
|
migrateUserData,
|
||||||
|
requireLoginMiddleware,
|
||||||
|
setUserDataMiddleware,
|
||||||
|
shouldRedirectToLogin,
|
||||||
|
tryAutoLogin,
|
||||||
|
router as userDataRouter,
|
||||||
|
} from './src/users.js';
|
||||||
import basicAuthMiddleware from './src/middleware/basicAuth.js';
|
import basicAuthMiddleware from './src/middleware/basicAuth.js';
|
||||||
import whitelistMiddleware from './src/middleware/whitelist.js';
|
import whitelistMiddleware from './src/middleware/whitelist.js';
|
||||||
import multerMonkeyPatch from './src/middleware/multerMonkeyPatch.js';
|
import multerMonkeyPatch from './src/middleware/multerMonkeyPatch.js';
|
||||||
import initRequestProxy from './src/request-proxy.js';
|
import initRequestProxy from './src/request-proxy.js';
|
||||||
import * as contentManager from './src/endpoints/content-manager.js';
|
|
||||||
import {
|
import {
|
||||||
getVersion,
|
getVersion,
|
||||||
getConfigValue,
|
getConfigValue,
|
||||||
@ -81,7 +95,7 @@ import { router as worldInfoRouter } from './src/endpoints/worldinfo.js';
|
|||||||
import { router as statsRouter, init as statsInit, onExit as statsOnExit } from './src/endpoints/stats.js';
|
import { router as statsRouter, init as statsInit, onExit as statsOnExit } from './src/endpoints/stats.js';
|
||||||
import { router as backgroundsRouter } from './src/endpoints/backgrounds.js';
|
import { router as backgroundsRouter } from './src/endpoints/backgrounds.js';
|
||||||
import { router as spritesRouter } from './src/endpoints/sprites.js';
|
import { router as spritesRouter } from './src/endpoints/sprites.js';
|
||||||
import { router as contentManagerRouter } from './src/endpoints/content-manager.js';
|
import { router as contentManagerRouter, checkForNewContent } from './src/endpoints/content-manager.js';
|
||||||
import { router as settingsRouter, init as settingsInit } from './src/endpoints/settings.js';
|
import { router as settingsRouter, init as settingsInit } from './src/endpoints/settings.js';
|
||||||
import { router as stableDiffusionRouter } from './src/endpoints/stable-diffusion.js';
|
import { router as stableDiffusionRouter } from './src/endpoints/stable-diffusion.js';
|
||||||
import { router as hordeRouter } from './src/endpoints/horde.js';
|
import { router as hordeRouter } from './src/endpoints/horde.js';
|
||||||
@ -349,21 +363,21 @@ function getSessionCookieAge() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.use(cookieSession({
|
app.use(cookieSession({
|
||||||
name: userModule.getCookieSessionName(),
|
name: getCookieSessionName(),
|
||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
maxAge: getSessionCookieAge(),
|
maxAge: getSessionCookieAge(),
|
||||||
secret: userModule.getCookieSecret(),
|
secret: getCookieSecret(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.use(userModule.setUserDataMiddleware);
|
app.use(setUserDataMiddleware);
|
||||||
|
|
||||||
// CSRF Protection //
|
// CSRF Protection //
|
||||||
if (!disableCsrf) {
|
if (!disableCsrf) {
|
||||||
const COOKIES_SECRET = userModule.getCookieSecret();
|
const COOKIES_SECRET = getCookieSecret();
|
||||||
|
|
||||||
const { generateToken, doubleCsrfProtection } = doubleCsrf({
|
const { generateToken, doubleCsrfProtection } = doubleCsrf({
|
||||||
getSecret: userModule.getCsrfSecret,
|
getSecret: getCsrfSecret,
|
||||||
cookieName: 'X-CSRF-Token',
|
cookieName: 'X-CSRF-Token',
|
||||||
cookieOptions: {
|
cookieOptions: {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
@ -394,7 +408,7 @@ if (!disableCsrf) {
|
|||||||
// Static files
|
// Static files
|
||||||
// Host index page
|
// Host index page
|
||||||
app.get('/', (request, response) => {
|
app.get('/', (request, response) => {
|
||||||
if (userModule.shouldRedirectToLogin(request)) {
|
if (shouldRedirectToLogin(request)) {
|
||||||
const query = request.url.split('?')[1];
|
const query = request.url.split('?')[1];
|
||||||
const redirectUrl = query ? `/login?${query}` : '/login';
|
const redirectUrl = query ? `/login?${query}` : '/login';
|
||||||
return response.redirect(redirectUrl);
|
return response.redirect(redirectUrl);
|
||||||
@ -411,7 +425,7 @@ app.get('/login', async (request, response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const autoLogin = await userModule.tryAutoLogin(request, basicAuthMode);
|
const autoLogin = await tryAutoLogin(request, basicAuthMode);
|
||||||
|
|
||||||
if (autoLogin) {
|
if (autoLogin) {
|
||||||
return response.redirect('/');
|
return response.redirect('/');
|
||||||
@ -430,7 +444,7 @@ app.use(express.static(process.cwd() + '/public', {}));
|
|||||||
app.use('/api/users', usersPublicRouter);
|
app.use('/api/users', usersPublicRouter);
|
||||||
|
|
||||||
// Everything below this line requires authentication
|
// Everything below this line requires authentication
|
||||||
app.use(userModule.requireLoginMiddleware);
|
app.use(requireLoginMiddleware);
|
||||||
app.get('/api/ping', (_, response) => response.sendStatus(204));
|
app.get('/api/ping', (_, response) => response.sendStatus(204));
|
||||||
|
|
||||||
// File uploads
|
// File uploads
|
||||||
@ -438,7 +452,7 @@ app.use(multer({ dest: uploadsPath, limits: { fieldSize: 10 * 1024 * 1024 } }).s
|
|||||||
app.use(multerMonkeyPatch);
|
app.use(multerMonkeyPatch);
|
||||||
|
|
||||||
// User data mount
|
// User data mount
|
||||||
app.use('/', userModule.router);
|
app.use('/', userDataRouter);
|
||||||
// Private endpoints
|
// Private endpoints
|
||||||
app.use('/api/users', usersPrivateRouter);
|
app.use('/api/users', usersPrivateRouter);
|
||||||
// Admin endpoints
|
// Admin endpoints
|
||||||
@ -625,15 +639,15 @@ const preSetupTasks = async function () {
|
|||||||
}
|
}
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
const directories = await userModule.getUserDirectoriesList();
|
const directories = await getUserDirectoriesList();
|
||||||
await contentManager.checkForNewContent(directories);
|
await checkForNewContent(directories);
|
||||||
await ensureThumbnailCache();
|
await ensureThumbnailCache();
|
||||||
cleanUploads();
|
cleanUploads();
|
||||||
|
|
||||||
await settingsInit();
|
await settingsInit();
|
||||||
await statsInit();
|
await statsInit();
|
||||||
|
|
||||||
const cleanupPlugins = await loadPlugins();
|
const cleanupPlugins = await initializePlugins();
|
||||||
const consoleTitle = process.title;
|
const consoleTitle = process.title;
|
||||||
|
|
||||||
let isExiting = false;
|
let isExiting = false;
|
||||||
@ -740,10 +754,10 @@ const postSetupTasks = async function (v6Failed, v4Failed) {
|
|||||||
* Loads server plugins from a directory.
|
* Loads server plugins from a directory.
|
||||||
* @returns {Promise<Function>} Function to be run on server exit
|
* @returns {Promise<Function>} Function to be run on server exit
|
||||||
*/
|
*/
|
||||||
async function loadPlugins() {
|
async function initializePlugins() {
|
||||||
try {
|
try {
|
||||||
const pluginDirectory = path.join(serverDirectory, 'plugins');
|
const pluginDirectory = path.join(serverDirectory, 'plugins');
|
||||||
const cleanupPlugins = await loader.loadPlugins(app, pluginDirectory);
|
const cleanupPlugins = await loadPlugins(app, pluginDirectory);
|
||||||
return cleanupPlugins;
|
return cleanupPlugins;
|
||||||
} catch {
|
} catch {
|
||||||
console.log('Plugin loading failed.');
|
console.log('Plugin loading failed.');
|
||||||
@ -883,7 +897,7 @@ async function verifySecuritySettings() {
|
|||||||
logSecurityAlert('Your SillyTavern is currently insecurely open to the public. Enable whitelisting, basic authentication or user accounts.');
|
logSecurityAlert('Your SillyTavern is currently insecurely open to the public. Enable whitelisting, basic authentication or user accounts.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const users = await userModule.getAllEnabledUsers();
|
const users = await getAllEnabledUsers();
|
||||||
const unprotectedUsers = users.filter(x => !x.password);
|
const unprotectedUsers = users.filter(x => !x.password);
|
||||||
const unprotectedAdminUsers = unprotectedUsers.filter(x => x.admin);
|
const unprotectedAdminUsers = unprotectedUsers.filter(x => x.admin);
|
||||||
|
|
||||||
@ -901,10 +915,10 @@ async function verifySecuritySettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// User storage module needs to be initialized before starting the server
|
// User storage module needs to be initialized before starting the server
|
||||||
userModule.initUserStorage(dataRoot)
|
initUserStorage(dataRoot)
|
||||||
.then(userModule.ensurePublicDirectoriesExist)
|
.then(ensurePublicDirectoriesExist)
|
||||||
.then(userModule.migrateUserData)
|
.then(migrateUserData)
|
||||||
.then(userModule.migrateSystemPrompts)
|
.then(migrateSystemPrompts)
|
||||||
.then(verifySecuritySettings)
|
.then(verifySecuritySettings)
|
||||||
.then(preSetupTasks)
|
.then(preSetupTasks)
|
||||||
.finally(startServer);
|
.finally(startServer);
|
||||||
|
@ -16,7 +16,7 @@ import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';
|
|||||||
import { jsonParser, urlencodedParser } from '../express-common.js';
|
import { jsonParser, urlencodedParser } from '../express-common.js';
|
||||||
import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer } from '../util.js';
|
import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer } from '../util.js';
|
||||||
import { TavernCardValidator } from '../validator/TavernCardValidator.js';
|
import { TavernCardValidator } from '../validator/TavernCardValidator.js';
|
||||||
import * as characterCardParser from '../character-card-parser.js';
|
import { parse, write } from '../character-card-parser.js';
|
||||||
import { readWorldInfoFile } from './worldinfo.js';
|
import { readWorldInfoFile } from './worldinfo.js';
|
||||||
import { invalidateThumbnail } from './thumbnails.js';
|
import { invalidateThumbnail } from './thumbnails.js';
|
||||||
import { importRisuSprites } from './sprites.js';
|
import { importRisuSprites } from './sprites.js';
|
||||||
@ -38,7 +38,7 @@ async function readCharacterData(inputFile, inputFormat = 'png') {
|
|||||||
return characterDataCache.get(cacheKey);
|
return characterDataCache.get(cacheKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = characterCardParser.parse(inputFile, inputFormat);
|
const result = parse(inputFile, inputFormat);
|
||||||
characterDataCache.set(cacheKey, result);
|
characterDataCache.set(cacheKey, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
|
|||||||
const inputImage = await getInputImage();
|
const inputImage = await getInputImage();
|
||||||
|
|
||||||
// Get the chunks
|
// Get the chunks
|
||||||
const outputImage = characterCardParser.write(inputImage, data);
|
const outputImage = write(inputImage, data);
|
||||||
const outputImagePath = path.join(request.user.directories.characters, `${outputFile}.png`);
|
const outputImagePath = path.join(request.user.directories.characters, `${outputFile}.png`);
|
||||||
|
|
||||||
writeFileAtomicSync(outputImagePath, outputImage);
|
writeFileAtomicSync(outputImagePath, outputImage);
|
||||||
|
@ -5,15 +5,16 @@ import { Buffer } from 'node:buffer';
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import sanitize from 'sanitize-filename';
|
import sanitize from 'sanitize-filename';
|
||||||
|
import { sync as writeFileAtomicSync } from 'write-file-atomic';
|
||||||
|
|
||||||
import { getConfigValue, color } from '../util.js';
|
import { getConfigValue, color } from '../util.js';
|
||||||
import { jsonParser } from '../express-common.js';
|
import { jsonParser } from '../express-common.js';
|
||||||
import { sync as writeFileAtomicSync } from 'write-file-atomic';
|
import { write } from '../character-card-parser.js';
|
||||||
|
|
||||||
const contentDirectory = path.join(process.cwd(), 'default/content');
|
const contentDirectory = path.join(process.cwd(), 'default/content');
|
||||||
const scaffoldDirectory = path.join(process.cwd(), 'default/scaffold');
|
const scaffoldDirectory = path.join(process.cwd(), 'default/scaffold');
|
||||||
const contentIndexPath = path.join(contentDirectory, 'index.json');
|
const contentIndexPath = path.join(contentDirectory, 'index.json');
|
||||||
const scaffoldIndexPath = path.join(scaffoldDirectory, 'index.json');
|
const scaffoldIndexPath = path.join(scaffoldDirectory, 'index.json');
|
||||||
import * as characterCardParser from '../character-card-parser.js';
|
|
||||||
|
|
||||||
const WHITELIST_GENERIC_URL_DOWNLOAD_SOURCES = getConfigValue('whitelistImportDomains', []);
|
const WHITELIST_GENERIC_URL_DOWNLOAD_SOURCES = getConfigValue('whitelistImportDomains', []);
|
||||||
|
|
||||||
@ -397,7 +398,7 @@ async function downloadPygmalionCharacter(id) {
|
|||||||
const avatarResult = await fetch(avatarUrl);
|
const avatarResult = await fetch(avatarUrl);
|
||||||
const avatarBuffer = await avatarResult.buffer();
|
const avatarBuffer = await avatarResult.buffer();
|
||||||
|
|
||||||
const cardBuffer = characterCardParser.write(avatarBuffer, JSON.stringify(characterData));
|
const cardBuffer = write(avatarBuffer, JSON.stringify(characterData));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
buffer: cardBuffer,
|
buffer: cardBuffer,
|
||||||
|
@ -8,9 +8,8 @@ import express from 'express';
|
|||||||
import { jsonParser } from '../express-common.js';
|
import { jsonParser } from '../express-common.js';
|
||||||
import { getUserAvatar, toKey, getPasswordHash, getPasswordSalt, createBackupArchive, ensurePublicDirectoriesExist, toAvatarKey } from '../users.js';
|
import { getUserAvatar, toKey, getPasswordHash, getPasswordSalt, createBackupArchive, ensurePublicDirectoriesExist, toAvatarKey } from '../users.js';
|
||||||
import { SETTINGS_FILE } from '../constants.js';
|
import { SETTINGS_FILE } from '../constants.js';
|
||||||
import * as contentManager from './content-manager.js';
|
import { checkForNewContent, CONTENT_TYPES } from './content-manager.js';
|
||||||
import { color, Cache } from '../util.js';
|
import { color, Cache } from '../util.js';
|
||||||
import { checkForNewContent } from './content-manager.js';
|
|
||||||
|
|
||||||
const RESET_CACHE = new Cache(5 * 60 * 1000);
|
const RESET_CACHE = new Cache(5 * 60 * 1000);
|
||||||
|
|
||||||
@ -168,7 +167,7 @@ router.post('/reset-settings', jsonParser, async (request, response) => {
|
|||||||
|
|
||||||
const pathToFile = path.join(request.user.directories.root, SETTINGS_FILE);
|
const pathToFile = path.join(request.user.directories.root, SETTINGS_FILE);
|
||||||
await fsPromises.rm(pathToFile, { force: true });
|
await fsPromises.rm(pathToFile, { force: true });
|
||||||
await contentManager.checkForNewContent([request.user.directories], [contentManager.CONTENT_TYPES.SETTINGS]);
|
await checkForNewContent([request.user.directories], [CONTENT_TYPES.SETTINGS]);
|
||||||
|
|
||||||
return response.sendStatus(204);
|
return response.sendStatus(204);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user