my nvim and vscode are finally using the same settings

This commit is contained in:
waveringana 2024-01-25 13:03:29 -05:00
parent 58077a5d63
commit a5e03facbe
11 changed files with 757 additions and 757 deletions

View file

@ -1,21 +1,21 @@
module.exports = { module.exports = {
env: { env: {
browser: true, browser: true,
es2021: true, es2021: true,
node: true, node: true,
}, },
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
overrides: [], overrides: [],
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
parserOptions: { parserOptions: {
ecmaVersion: "latest", ecmaVersion: "latest",
sourceType: "module", sourceType: "module",
}, },
plugins: ["@typescript-eslint"], plugins: ["@typescript-eslint"],
rules: { rules: {
indent: ["error", 2, { SwitchCase: 1 }], indent: ["error", 4, { SwitchCase: 1 }],
"linebreak-style": ["error", "unix"], "linebreak-style": ["error", "unix"],
quotes: ["error", "double"], quotes: ["error", "double"],
semi: ["error", "always"], semi: ["error", "always"],
}, },
}; };

View file

@ -25,17 +25,17 @@ const server = http.createServer(app);
const port = normalizePort(process.env.EBPORT || "3000"); const port = normalizePort(process.env.EBPORT || "3000");
function normalizePort(val: string) { function normalizePort(val: string) {
const port = parseInt(val, 10); const port = parseInt(val, 10);
if (isNaN(port)) { if (isNaN(port)) {
return val; return val;
} }
if (port >= 0) { if (port >= 0) {
return port; return port;
} }
return false; return false;
} }
app.set("port", port); app.set("port", port);
@ -44,56 +44,56 @@ server.on("error", onError);
server.on("listening", onListening); server.on("listening", onListening);
function onError(error: any) { function onError(error: any) {
if (error.syscall !== "listen") { if (error.syscall !== "listen") {
throw error; throw error;
} }
const bind = typeof port === "string" const bind = typeof port === "string"
? "Pipe " + port ? "Pipe " + port
: "Port " + port; : "Port " + port;
// handle specific listen errors with friendly messages // handle specific listen errors with friendly messages
switch (error.code) { switch (error.code) {
case "EACCES": case "EACCES":
console.error(bind + " requires elevated privileges"); console.error(bind + " requires elevated privileges");
process.exit(1); process.exit(1);
break; break;
case "EADDRINUSE": case "EADDRINUSE":
console.error(bind + " is already in use"); console.error(bind + " is already in use");
process.exit(1); process.exit(1);
break; break;
default: default:
throw error; throw error;
} }
} }
// Check if there is an existing DB or not, then check if it needs to be updated to new schema // Check if there is an existing DB or not, then check if it needs to be updated to new schema
db.get("SELECT * FROM sqlite_master WHERE name ='users' and type='table'", async (err, row) => { db.get("SELECT * FROM sqlite_master WHERE name ='users' and type='table'", async (err, row) => {
if (!row) createDatabase(3); if (!row) createDatabase(3);
else checkVersion(); else checkVersion();
}); });
function checkVersion () { function checkVersion () {
db.get("PRAGMA user_version", (err: Error, row: any) => { db.get("PRAGMA user_version", (err: Error, row: any) => {
if (row && row.user_version) { if (row && row.user_version) {
const version = row.user_version; const version = row.user_version;
if (version != 3) console.log("DATABASE IS OUTDATED"); if (version != 3) console.log("DATABASE IS OUTDATED");
updateDatabase(version, 3); updateDatabase(version, 3);
} else { } else {
// Because ver 1 does not have user_version set, we can safely assume that it is ver 1 // Because ver 1 does not have user_version set, we can safely assume that it is ver 1
updateDatabase(1, 3); updateDatabase(1, 3);
} }
}); });
} }
function onListening() { function onListening() {
const addr = server.address(); const addr = server.address();
const bind = typeof addr === "string" const bind = typeof addr === "string"
? "pipe " + addr ? "pipe " + addr
: "port " + addr.port; : "port " + addr.port;
console.log("Embedder version: " + version); console.log("Embedder version: " + version);
console.log("Listening on " + bind); console.log("Listening on " + bind);
} }
app.enable("trust proxy"); app.enable("trust proxy");
@ -104,20 +104,20 @@ app.set("view engine", "ejs");
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({ app.use(express.urlencoded({
extended: false extended: false
})); }));
app.use(cookieParser()); app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public"))); app.use(express.static(path.join(__dirname, "public")));
app.use(express.static(path.join(__dirname, "public"))); app.use(express.static(path.join(__dirname, "public")));
app.use(session({ app.use(session({
secret: process.env.EBSECRET || "pleasechangeme", secret: process.env.EBSECRET || "pleasechangeme",
resave: false, resave: false,
saveUninitialized: false, saveUninitialized: false,
store: new SQLiteStore({ store: new SQLiteStore({
db: "sessions.db", db: "sessions.db",
dir: "./var/db" dir: "./var/db"
}) as session.Store }) as session.Store
})); }));
app.use(passport.authenticate("session")); app.use(passport.authenticate("session"));
@ -129,26 +129,26 @@ app.use("/", settingsRouter);
app.use("/uploads", express.static("uploads")); app.use("/uploads", express.static("uploads"));
async function prune () { async function prune () {
db.all("SELECT * FROM media", (err: Error, rows: []) => { db.all("SELECT * FROM media", (err: Error, rows: []) => {
console.log("Uploaded files: " + rows.length); console.log("Uploaded files: " + rows.length);
console.log(rows); console.log(rows);
});
console.log("Vacuuming database...");
db.run("VACUUM");
db.each("SELECT path FROM media WHERE expire < ?", [Date.now()], (err: Error, row: MediaRow) => {
console.log(`Expired row: ${row}`);
fs.unlink(`uploads/${row.path}`, (err) => {
if (err && err.errno == -4058) {
console.log("File already deleted");
} else {
if (err) console.log(err);
}
}); });
});
await expire("media", "expire", Date.now()); console.log("Vacuuming database...");
db.run("VACUUM");
db.each("SELECT path FROM media WHERE expire < ?", [Date.now()], (err: Error, row: MediaRow) => {
console.log(`Expired row: ${row}`);
fs.unlink(`uploads/${row.path}`, (err) => {
if (err && err.errno == -4058) {
console.log("File already deleted");
} else {
if (err) console.log(err);
}
});
});
await expire("media", "expire", Date.now());
} }
setInterval(prune, 1000 * 60); //prune every minute setInterval(prune, 1000 * 60); //prune every minute

View file

@ -9,176 +9,176 @@ export const db = new sqlite3.Database("./var/db/media.db");
/**Create the database schema for the embedders app*/ /**Create the database schema for the embedders app*/
export function createDatabase(version: number) { export function createDatabase(version: number) {
console.log("Creating database"); console.log("Creating database");
db.run( db.run(
"CREATE TABLE IF NOT EXISTS users ( \ "CREATE TABLE IF NOT EXISTS users ( \
id INTEGER PRIMARY KEY, \ id INTEGER PRIMARY KEY, \
username TEXT UNIQUE, \ username TEXT UNIQUE, \
hashed_password BLOB, \ hashed_password BLOB, \
expire INTEGER, \ expire INTEGER, \
salt BLOB \ salt BLOB \
)", )",
() => createUser("admin", process.env.EBPASS || "changeme"), () => createUser("admin", process.env.EBPASS || "changeme"),
); );
db.run( db.run(
"CREATE TABLE IF NOT EXISTS media ( \ "CREATE TABLE IF NOT EXISTS media ( \
id INTEGER PRIMARY KEY, \ id INTEGER PRIMARY KEY, \
path TEXT NOT NULL, \ path TEXT NOT NULL, \
expire INTEGER, \ expire INTEGER, \
username TEXT \ username TEXT \
)", )",
); );
db.run( db.run(
"CREATE TABLE IF NOT EXISTS settings ( \ "CREATE TABLE IF NOT EXISTS settings ( \
id INTEGER PRIMARY KEY, \ id INTEGER PRIMARY KEY, \
downsclaing BOOLEAN, \ downsclaing BOOLEAN, \
namerandomization BOOLEAN \ namerandomization BOOLEAN \
)", )",
); );
db.run(`PRAGMA user_version = ${version}`); db.run(`PRAGMA user_version = ${version}`);
} }
/**Updates old Database schema to new */ /**Updates old Database schema to new */
export function updateDatabase(oldVersion: number, newVersion: number) { export function updateDatabase(oldVersion: number, newVersion: number) {
if (oldVersion == 1) { if (oldVersion == 1) {
console.log(`Updating database from ${oldVersion} to ${newVersion}`); console.log(`Updating database from ${oldVersion} to ${newVersion}`);
db.run("PRAGMA user_version = 3", (err) => { db.run("PRAGMA user_version = 3", (err) => {
if (err) return; if (err) return;
}); });
db.run("ALTER TABLE media ADD COLUMN username TEXT", (err) => { db.run("ALTER TABLE media ADD COLUMN username TEXT", (err) => {
if (err) return; if (err) return;
}); });
db.run("ALTER TABLE users ADD COLUMN expire TEXT", (err) => { db.run("ALTER TABLE users ADD COLUMN expire TEXT", (err) => {
if (err) return; if (err) return;
}); });
db.run( db.run(
"CREATE TABLE IF NOT EXISTS settings ( \ "CREATE TABLE IF NOT EXISTS settings ( \
id INTEGER PRIMARY KEY, \ id INTEGER PRIMARY KEY, \
downsclaing BOOLEAN, \ downsclaing BOOLEAN, \
namerandomization BOOLEAN \ namerandomization BOOLEAN \
)", )",
); );
} }
if (oldVersion == 2) { if (oldVersion == 2) {
console.log(`Updating database from ${oldVersion} to ${newVersion}`); console.log(`Updating database from ${oldVersion} to ${newVersion}`);
db.run("PRAGMA user_version = 3", (err) => { db.run("PRAGMA user_version = 3", (err) => {
if (err) return; if (err) return;
}); });
db.run( db.run(
"CREATE TABLE IF NOT EXISTS settings ( \ "CREATE TABLE IF NOT EXISTS settings ( \
id INTEGER PRIMARY KEY, \ id INTEGER PRIMARY KEY, \
downsclaing BOOLEAN, \ downsclaing BOOLEAN, \
namerandomization BOOLEAN \ namerandomization BOOLEAN \
)", )",
); );
} }
} }
/**Inserts into the media table */ /**Inserts into the media table */
export function insertToDB( export function insertToDB(
filename: string, filename: string,
expireDate: Date, expireDate: Date,
username: string, username: string,
): Promise<void> { ): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const params: MediaParams = [filename, expireDate, username]; const params: MediaParams = [filename, expireDate, username];
db.run( db.run(
"INSERT INTO media (path, expire, username) VALUES (?, ?, ?)", "INSERT INTO media (path, expire, username) VALUES (?, ?, ?)",
params, params,
function (err) { function (err) {
if (err) { if (err) {
console.log(err); console.log(err);
reject(err); reject(err);
} else { } else {
console.log(`Uploaded ${filename} to database`); console.log(`Uploaded ${filename} to database`);
if (expireDate == null) console.log("It will not expire"); if (expireDate == null) console.log("It will not expire");
else if (expireDate != null || expireDate != undefined) else if (expireDate != null || expireDate != undefined)
console.log(`It will expire on ${expireDate}`); console.log(`It will expire on ${expireDate}`);
resolve(); resolve();
} }
}, },
); );
}); });
} }
/**Searches the database and returns images with partial or exact keysearches */ /**Searches the database and returns images with partial or exact keysearches */
export function searchImages(imagename: string, partial: boolean) { export function searchImages(imagename: string, partial: boolean) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log(`searching for ${imagename}`); console.log(`searching for ${imagename}`);
}); });
} }
export function updateImageName(oldimagename: string, newname: string) { export function updateImageName(oldimagename: string, newname: string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log(`updating ${oldimagename} to ${newname}`); console.log(`updating ${oldimagename} to ${newname}`);
}); });
} }
/**Inserts a new user to the database */ /**Inserts a new user to the database */
export function createUser(username: string, password: string) { export function createUser(username: string, password: string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log(`Creating user ${username}`); console.log(`Creating user ${username}`);
const salt = crypto.randomBytes(16); const salt = crypto.randomBytes(16);
db.run( db.run(
"INSERT OR IGNORE INTO users (username, hashed_password, salt) VALUES (?, ?, ?)", "INSERT OR IGNORE INTO users (username, hashed_password, salt) VALUES (?, ?, ?)",
[username, crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256"), salt], [username, crypto.pbkdf2Sync(password, salt, 310000, 32, "sha256"), salt],
); );
resolve(null); resolve(null);
}); });
} }
/**Selects the path for a file given ID */ /**Selects the path for a file given ID */
export function getPath(id: number | string) { export function getPath(id: number | string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const query = "SELECT path FROM media WHERE id = ?"; const query = "SELECT path FROM media WHERE id = ?";
db.get(query, [id], (err: Error, path: object) => { db.get(query, [id], (err: Error, path: object) => {
if (err) { if (err) {
reject(err); reject(err);
} }
resolve(path); resolve(path);
});
}); });
});
} }
/**Deletes from database given an ID */ /**Deletes from database given an ID */
export function deleteId(database: string, id: number | string) { export function deleteId(database: string, id: number | string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const query = `DELETE FROM ${database} WHERE id = ?`; const query = `DELETE FROM ${database} WHERE id = ?`;
db.run(query, [id], (err: Error) => { db.run(query, [id], (err: Error) => {
if (err) { if (err) {
reject(err); reject(err);
return; return;
} }
resolve(null); resolve(null);
});
}); });
});
} }
/**Expires a database row given a Date in unix time */ /**Expires a database row given a Date in unix time */
export function expire(database: string, column: string, expiration: number) { export function expire(database: string, column: string, expiration: number) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const query = `SELECT * FROM ${database} WHERE ${column} < ?`; const query = `SELECT * FROM ${database} WHERE ${column} < ?`;
db.each(query, [expiration], async (err: Error, row: GenericRow) => { db.each(query, [expiration], async (err: Error, row: GenericRow) => {
if (err) reject(err); if (err) reject(err);
await deleteId(database, row.id); await deleteId(database, row.id);
resolve(null); resolve(null);
});
}); });
});
} }
/**A generic database row */ /**A generic database row */

View file

@ -37,7 +37,7 @@ export let currentEncoding: EncodingType = EncodingType.CPU;
* @param {EncodingType} type - The encoding type to set. * @param {EncodingType} type - The encoding type to set.
*/ */
export const setEncodingType = (type: EncodingType) => { export const setEncodingType = (type: EncodingType) => {
currentEncoding = type; currentEncoding = type;
}; };
/** /**
@ -52,31 +52,31 @@ export const setEncodingType = (type: EncodingType) => {
* @throws Will throw an error if the executable is not found and the installer path is not available. * @throws Will throw an error if the executable is not found and the installer path is not available.
*/ */
const getExecutablePath = ( const getExecutablePath = (
envVar: string, envVar: string,
executable: string, executable: string,
installer: { path: string }, installer: { path: string },
): string => { ): string => {
if (process.env[envVar]) { if (process.env[envVar]) {
return process.env[envVar]; return process.env[envVar];
} }
try { try {
return which.sync(executable); return which.sync(executable);
} catch (error) { } catch (error) {
return installer.path; return installer.path;
} }
}; };
const ffmpegPath = getExecutablePath( const ffmpegPath = getExecutablePath(
"EB_FFMPEG_PATH", "EB_FFMPEG_PATH",
"ffmpeg", "ffmpeg",
ffmpegInstaller, ffmpegInstaller,
); );
const ffprobePath = getExecutablePath( const ffprobePath = getExecutablePath(
"EB_FFPROBE_PATH", "EB_FFPROBE_PATH",
"ffprobe", "ffprobe",
ffprobeInstaller, ffprobeInstaller,
); );
console.log(`Using ffmpeg from path: ${ffmpegPath}`); console.log(`Using ffmpeg from path: ${ffmpegPath}`);
@ -86,20 +86,20 @@ ffmpeg.setFfmpegPath(ffmpegPath!);
ffmpeg.setFfprobePath(ffprobePath!); ffmpeg.setFfprobePath(ffprobePath!);
const checkEnvForEncoder = () => { const checkEnvForEncoder = () => {
const envEncoder = process.env.EB_ENCODER?.toUpperCase(); const envEncoder = process.env.EB_ENCODER?.toUpperCase();
if (envEncoder && Object.keys(EncodingType).includes(envEncoder)) { if (envEncoder && Object.keys(EncodingType).includes(envEncoder)) {
setEncodingType( setEncodingType(
EncodingType[envEncoder as keyof typeof EncodingType] as EncodingType, EncodingType[envEncoder as keyof typeof EncodingType] as EncodingType,
); );
console.log( console.log(
`Setting encoding type to ${envEncoder} based on environment variable.`, `Setting encoding type to ${envEncoder} based on environment variable.`,
); );
} else if (envEncoder) { } else if (envEncoder) {
console.warn( console.warn(
`Invalid encoder value "${envEncoder}" in environment variable, defaulting to CPU.`, `Invalid encoder value "${envEncoder}" in environment variable, defaulting to CPU.`,
); );
} }
}; };
checkEnvForEncoder(); checkEnvForEncoder();
@ -120,57 +120,57 @@ checkEnvForEncoder();
* }); * });
*/ */
export const ffmpegDownscale = ( export const ffmpegDownscale = (
path: string, path: string,
filename: string, filename: string,
extension: string, extension: string,
): Promise<void> => { ): Promise<void> => {
const startTime = Date.now(); const startTime = Date.now();
const outputOptions = [ const outputOptions = [
"-vf", "-vf",
"scale=-2:720", "scale=-2:720",
"-c:v", "-c:v",
currentEncoding, currentEncoding,
"-c:a", "-c:a",
"copy", "copy",
"-pix_fmt", "-pix_fmt",
"yuv420p", "yuv420p",
]; ];
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const progressFile = `uploads/${filename}${extension}-progress.json`; const progressFile = `uploads/${filename}${extension}-progress.json`;
ffmpeg() ffmpeg()
.input(path) .input(path)
.outputOptions(outputOptions) .outputOptions(outputOptions)
.output(`uploads/720p-${filename}${extension}`) .output(`uploads/720p-${filename}${extension}`)
.on("progress", function (progress) { .on("progress", function (progress) {
fs.writeFileSync( fs.writeFileSync(
progressFile, progressFile,
JSON.stringify({ progress: progress.percent / 100 }), JSON.stringify({ progress: progress.percent / 100 }),
); );
}) })
.on("end", () => { .on("end", () => {
console.log( console.log(
`720p copy complete using ${currentEncoding}, took ${ `720p copy complete using ${currentEncoding}, took ${
Date.now() - startTime Date.now() - startTime
}ms to complete`, }ms to complete`,
); );
// Delete the .processing file // Delete the .processing file
fs.unlinkSync(progressFile); fs.unlinkSync(progressFile);
resolve(); resolve();
}) })
.on("error", (e) => { .on("error", (e) => {
// Ensure to delete the .processing file even on error // Ensure to delete the .processing file even on error
if (fs.existsSync(progressFile)) { if (fs.existsSync(progressFile)) {
fs.unlinkSync(progressFile); fs.unlinkSync(progressFile);
} }
reject(new Error(e)); reject(new Error(e));
}) })
.run(); .run();
}); });
}; };
/** /**
@ -189,80 +189,80 @@ export const ffmpegDownscale = (
* }); * });
*/ */
export const ffmpegConvert = ( export const ffmpegConvert = (
path: string, path: string,
filename: string, filename: string,
extension: string, extension: string,
): Promise<void> => { ): Promise<void> => {
const startTime = Date.now(); const startTime = Date.now();
const outputOptions = [ const outputOptions = [
"-vf", "-vf",
"scale=-2:720", "scale=-2:720",
"-c:v", "-c:v",
currentEncoding, currentEncoding,
"-c:a", "-c:a",
"copy", "copy",
"-movflags", "-movflags",
"+faststart", "+faststart",
"-pix_fmt", "-pix_fmt",
"yuv420p", "yuv420p",
]; ];
let outputFormat: string; let outputFormat: string;
if (videoExtensions.includes(extension)) {
outputFormat = ".gif";
} else if (extension == ".gif") {
outputFormat = ".mp4";
} else {
return new Promise<void>((resolve, reject) => {
reject(`Submitted file is neither a video nor a gif: ${path}`);
});
}
if (videoExtensions.includes(extension)) {
outputFormat = ".gif";
} else if (extension == ".gif") {
outputFormat = ".mp4";
} else {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
reject(`Submitted file is neither a video nor a gif: ${path}`); const progressFile = `uploads/${filename}${extension}-progress.json`;
ffmpeg()
.input(path)
.outputOptions(outputOptions)
.output("uploads/")
.outputFormat(outputFormat)
.output(`uploads/${filename}${outputFormat}`)
.on("progress", function (progress) {
fs.writeFileSync(
progressFile,
JSON.stringify({ progress: progress.percent / 100 }),
);
})
.on("end", function () {
console.log(
`Conversion complete, took ${Date.now() - startTime} to complete`,
);
console.log(`uploads/${filename}${outputFormat}`);
resolve();
})
.on("error", (e) => reject(e))
.run();
}); });
}
return new Promise<void>((resolve, reject) => {
const progressFile = `uploads/${filename}${extension}-progress.json`;
ffmpeg()
.input(path)
.outputOptions(outputOptions)
.output("uploads/")
.outputFormat(outputFormat)
.output(`uploads/${filename}${outputFormat}`)
.on("progress", function (progress) {
fs.writeFileSync(
progressFile,
JSON.stringify({ progress: progress.percent / 100 }),
);
})
.on("end", function () {
console.log(
`Conversion complete, took ${Date.now() - startTime} to complete`,
);
console.log(`uploads/${filename}${outputFormat}`);
resolve();
})
.on("error", (e) => reject(e))
.run();
});
}; };
export const ffProbe = async ( export const ffProbe = async (
path: string, path: string,
filename: string, filename: string,
extension: string, extension: string,
) => { ) => {
return new Promise<FfprobeData>((resolve, reject) => { return new Promise<FfprobeData>((resolve, reject) => {
if ( if (
!videoExtensions.includes(extension) && !videoExtensions.includes(extension) &&
!imageExtensions.includes(extension) !imageExtensions.includes(extension)
) { ) {
console.log(`Extension is ${extension}`); console.log(`Extension is ${extension}`);
reject(`Submitted file is neither a video nor an image: ${path}`); reject(`Submitted file is neither a video nor an image: ${path}`);
} }
ffprobe(path, (err, data) => { ffprobe(path, (err, data) => {
if (err) reject(err); if (err) reject(err);
resolve(data); resolve(data);
});
}); });
});
}; };

View file

@ -11,11 +11,11 @@ declare global {
} }
/**Splits a file name into its name and then its extension */ /**Splits a file name into its name and then its extension */
export function extension(str: string) { export function extension(str: string) {
const file = str.split("/").pop(); const file = str.split("/").pop();
return [ return [
file.substr(0, file.lastIndexOf(".")), file.substr(0, file.lastIndexOf(".")),
file.substr(file.lastIndexOf("."), file.length).toLowerCase(), file.substr(file.lastIndexOf("."), file.length).toLowerCase(),
]; ];
} }
/**Type for user data */ /**Type for user data */
export interface User { export interface User {
@ -37,21 +37,21 @@ export interface oembedObj {
} }
export const videoExtensions = [ export const videoExtensions = [
".mp4", ".mp4",
".mov", ".mov",
".avi", ".avi",
".flv", ".flv",
".mkv", ".mkv",
".wmv", ".wmv",
".webm", ".webm",
]; ];
export const imageExtensions = [ export const imageExtensions = [
".jpg", ".jpg",
".jpeg", ".jpeg",
".png", ".png",
".gif", ".gif",
".bmp", ".bmp",
".svg", ".svg",
".tiff", ".tiff",
".webp", ".webp",
]; ];

View file

@ -8,40 +8,40 @@ import { insertToDB } from "./db";
import { ffmpegDownscale, ffProbe } from "./ffmpeg"; import { ffmpegDownscale, ffProbe } from "./ffmpeg";
export const checkAuth: Middleware = (req, res, next) => { export const checkAuth: Middleware = (req, res, next) => {
if (!req.user) { if (!req.user) {
return res.status(401); return res.status(401);
} }
next(); next();
}; };
/**Checks shareX auth key */ /**Checks shareX auth key */
export const checkSharexAuth: Middleware = (req, res, next) => { export const checkSharexAuth: Middleware = (req, res, next) => {
const auth = const auth =
process.env.EBAPI_KEY || process.env.EBPASS || "pleaseSetAPI_KEY"; process.env.EBAPI_KEY || process.env.EBPASS || "pleaseSetAPI_KEY";
let key = null; let key = null;
if (req.headers["key"]) { if (req.headers["key"]) {
key = req.headers["key"]; key = req.headers["key"];
} else { } else {
return res return res
.status(400) .status(400)
.send( .send(
"{success: false, message: 'No key provided', fix: 'Provide a key'}", "{success: false, message: 'No key provided', fix: 'Provide a key'}",
); );
} }
if (auth != key) { if (auth != key) {
return res return res
.status(401) .status(401)
.send( .send(
"{success: false, message: 'Invalid key', fix: 'Provide a valid key'}", "{success: false, message: 'Invalid key', fix: 'Provide a valid key'}",
); );
} }
const shortKey = key.substr(0, 3) + "..."; const shortKey = key.substr(0, 3) + "...";
console.log(`Authenicated user with key: ${shortKey}`); console.log(`Authenicated user with key: ${shortKey}`);
next(); next();
}; };
/** /**
@ -53,50 +53,50 @@ export const checkSharexAuth: Middleware = (req, res, next) => {
* *
*/ */
export const createEmbedData: Middleware = async (req, res, next) => { export const createEmbedData: Middleware = async (req, res, next) => {
const files = req.files as Express.Multer.File[]; const files = req.files as Express.Multer.File[];
for (const file in files) { for (const file in files) {
const [filename, fileExtension] = extension(files[file].filename); const [filename, fileExtension] = extension(files[file].filename);
const isMedia = const isMedia =
videoExtensions.includes(fileExtension) || videoExtensions.includes(fileExtension) ||
imageExtensions.includes(fileExtension); imageExtensions.includes(fileExtension);
const oembed: oembedObj = { const oembed: oembedObj = {
type: "video", type: "video",
version: "1.0", version: "1.0",
provider_name: "embedder", provider_name: "embedder",
provider_url: "https://github.com/WaveringAna/embedder", provider_url: "https://github.com/WaveringAna/embedder",
cache_age: 86400, cache_age: 86400,
html: `<iframe src='${req.protocol}://${req.get( html: `<iframe src='${req.protocol}://${req.get(
"host", "host",
)}/gifv/${filename}${fileExtension}'></iframe>`, )}/gifv/${filename}${fileExtension}'></iframe>`,
}; };
if (isMedia) { if (isMedia) {
let ffProbeData; let ffProbeData;
try { try {
ffProbeData = await ffProbe( ffProbeData = await ffProbe(
`uploads/${files[file].filename}`, `uploads/${files[file].filename}`,
filename, filename,
fileExtension, fileExtension,
);
} catch (error) {
console.log(`Error: ${error}`);
}
oembed.width = ffProbeData.streams[0].width;
oembed.height = ffProbeData.streams[0].height;
}
fs.writeFile(
`uploads/oembed-${filename}${fileExtension}.json`,
JSON.stringify(oembed),
function (err) {
if (err) return next(err);
console.log(`oembed file created ${filename}${fileExtension}.json`);
},
); );
} catch (error) {
console.log(`Error: ${error}`);
}
oembed.width = ffProbeData.streams[0].width;
oembed.height = ffProbeData.streams[0].height;
} }
next();
fs.writeFile(
`uploads/oembed-${filename}${fileExtension}.json`,
JSON.stringify(oembed),
function (err) {
if (err) return next(err);
console.log(`oembed file created ${filename}${fileExtension}.json`);
},
);
}
next();
}; };
/** /**
@ -108,59 +108,59 @@ export const createEmbedData: Middleware = async (req, res, next) => {
* *
*/ */
export const convertTo720p: Middleware = (req, res, next) => { export const convertTo720p: Middleware = (req, res, next) => {
const files = req.files as Express.Multer.File[]; const files = req.files as Express.Multer.File[];
console.log("convert to 720p running"); console.log("convert to 720p running");
for (const file in files) { for (const file in files) {
const [filename, fileExtension] = extension(files[file].filename); const [filename, fileExtension] = extension(files[file].filename);
//Skip if not a video //Skip if not a video
if (!videoExtensions.includes(fileExtension) && fileExtension !== ".gif") { if (!videoExtensions.includes(fileExtension) && fileExtension !== ".gif") {
console.log(`${files[file].filename} is not a video file`); console.log(`${files[file].filename} is not a video file`);
continue; continue;
}
console.log(`Creating 720p for ${files[file].filename}`);
ffmpegDownscale(
`uploads/${filename}${fileExtension}`,
filename,
fileExtension,
)
.then(() => {
//Nothing for now, can fire event flag that it is done to front end when react conversion is done
})
.catch((error) => {
console.log(`Error: ${error}`);
});
} }
console.log(`Creating 720p for ${files[file].filename}`); next();
ffmpegDownscale(
`uploads/${filename}${fileExtension}`,
filename,
fileExtension,
)
.then(() => {
//Nothing for now, can fire event flag that it is done to front end when react conversion is done
})
.catch((error) => {
console.log(`Error: ${error}`);
});
}
next();
}; };
/**Middleware for handling uploaded files. Inserts it into the database */ /**Middleware for handling uploaded files. Inserts it into the database */
export const handleUpload: Middleware = async (req, res, next) => { export const handleUpload: Middleware = async (req, res, next) => {
if (!req.file && !req.files) { if (!req.file && !req.files) {
console.log("No files were uploaded"); console.log("No files were uploaded");
return res.status(400).send("No files were uploaded."); return res.status(400).send("No files were uploaded.");
} }
const files = req.files ? (req.files as Express.Multer.File[]) : req.file; const files = req.files ? (req.files as Express.Multer.File[]) : req.file;
const username = req.user ? req.user.username : "sharex"; const username = req.user ? req.user.username : "sharex";
const expireDate: Date = req.body.expire const expireDate: Date = req.body.expire
? new Date(Date.now() + req.body.expire * 24 * 60 * 60 * 1000) ? new Date(Date.now() + req.body.expire * 24 * 60 * 60 * 1000)
: null; : null;
try { try {
if (files instanceof Array) { if (files instanceof Array) {
await Promise.all( await Promise.all(
files.map((file) => insertToDB(file.filename, expireDate, username)), files.map((file) => insertToDB(file.filename, expireDate, username)),
); );
} else { } else {
await insertToDB(files.filename, expireDate, username); await insertToDB(files.filename, expireDate, username);
}
next();
} catch (error) {
console.error("Error in handleUpload:", error);
res.status(500).send("Error processing files.");
} }
next();
} catch (error) {
console.error("Error in handleUpload:", error);
res.status(500).send("Error processing files.");
}
}; };

View file

@ -14,126 +14,126 @@ export type FileNameCallback = (error: Error | null, filename: string) => void;
let randomizeNames = false; let randomizeNames = false;
if (process.env["EB_RANDOMIZE_NAMES"] === "true") { if (process.env["EB_RANDOMIZE_NAMES"] === "true") {
randomizeNames = true; randomizeNames = true;
} }
console.log(`Randomize names is set ${randomizeNames}`); console.log(`Randomize names is set ${randomizeNames}`);
export const fileStorage = multer.diskStorage({ export const fileStorage = multer.diskStorage({
destination: ( destination: (
request: Request, request: Request,
file: Express.Multer.File, file: Express.Multer.File,
callback: DestinationCallback, callback: DestinationCallback,
): void => { ): void => {
callback(null, __dirname + "/../../uploads"); callback(null, __dirname + "/../../uploads");
}, },
filename: ( filename: (
request: Request, request: Request,
file: Express.Multer.File, file: Express.Multer.File,
callback: FileNameCallback, callback: FileNameCallback,
): void => { ): void => {
const [filename, fileExtension] = extension(file.originalname); const [filename, fileExtension] = extension(file.originalname);
console.log(`Uploading ${file}`); console.log(`Uploading ${file}`);
db.all( db.all(
"SELECT * FROM media WHERE path = ?", "SELECT * FROM media WHERE path = ?",
[filename + fileExtension], [filename + fileExtension],
(err: Error, exists: []) => { (err: Error, exists: []) => {
if (err) { if (err) {
console.log(err); console.log(err);
callback(err, null); callback(err, null);
} }
let filenameSet = true; let filenameSet = true;
let existsBool = false; let existsBool = false;
let suffix: number; let suffix: number;
if ( if (
request.body.title != "" || request.body.title != "" ||
request.body.title != null || request.body.title != null ||
request.body.title != undefined request.body.title != undefined
) { ) {
filenameSet = false; filenameSet = false;
} }
if (exists.length != 0) { if (exists.length != 0) {
existsBool = true; existsBool = true;
suffix = new Date().getTime() / 1000; suffix = new Date().getTime() / 1000;
} }
console.log(request.body.title); console.log(request.body.title);
if (randomizeNames) { if (randomizeNames) {
//Random string of 8 alphanumeric characters //Random string of 8 alphanumeric characters
//Chance of collision is extremely low, not worth checking for //Chance of collision is extremely low, not worth checking for
console.log("Randomizing name"); console.log("Randomizing name");
callback( callback(
null, null,
Math.random().toString(36).slice(2, 10) + fileExtension, Math.random().toString(36).slice(2, 10) + fileExtension,
); );
return; return;
} }
if (filenameSet && existsBool) { if (filenameSet && existsBool) {
console.log( console.log(
`filenameSet is ${filenameSet} and existsBool is ${existsBool}`, `filenameSet is ${filenameSet} and existsBool is ${existsBool}`,
); );
callback(null, request.body.title + "-" + suffix + fileExtension); callback(null, request.body.title + "-" + suffix + fileExtension);
return; return;
} }
if (!filenameSet && existsBool) { if (!filenameSet && existsBool) {
console.log( console.log(
`filenameSet is ${filenameSet} and existsBool is ${existsBool}`, `filenameSet is ${filenameSet} and existsBool is ${existsBool}`,
); );
callback(null, filename + "-" + suffix + fileExtension); callback(null, filename + "-" + suffix + fileExtension);
return; return;
} }
if (filenameSet && !existsBool) { if (filenameSet && !existsBool) {
console.log( console.log(
`filenameSet is ${filenameSet} and existsBool is ${existsBool}`, `filenameSet is ${filenameSet} and existsBool is ${existsBool}`,
); );
callback(null, request.body.title + fileExtension); callback(null, request.body.title + fileExtension);
return; return;
} }
if (!filenameSet && !existsBool) { if (!filenameSet && !existsBool) {
console.log( console.log(
`filenameSet is ${filenameSet} and existsBool is ${existsBool}`, `filenameSet is ${filenameSet} and existsBool is ${existsBool}`,
); );
callback(null, filename + fileExtension); callback(null, filename + fileExtension);
return; return;
} }
}, },
); );
}, },
}); });
export let allowedMimeTypes = [ export let allowedMimeTypes = [
"image/png", "image/png",
"image/jpg", "image/jpg",
"image/jpeg", "image/jpeg",
"image/gif", "image/gif",
"image/webp", "image/webp",
"video/mp4", "video/mp4",
"video/mov", "video/mov",
"video/webm", "video/webm",
"audio/mpeg", "audio/mpeg",
"audio/ogg", "audio/ogg",
]; ];
export const setAllowedMimeTypes = (mimeTypes: string[]): void => { export const setAllowedMimeTypes = (mimeTypes: string[]): void => {
allowedMimeTypes = mimeTypes; allowedMimeTypes = mimeTypes;
}; };
export const fileFilter = ( export const fileFilter = (
request: Request, request: Request,
file: Express.Multer.File, file: Express.Multer.File,
callback: FileFilterCallback, callback: FileFilterCallback,
): void => { ): void => {
if (allowedMimeTypes.includes(file.mimetype)) { if (allowedMimeTypes.includes(file.mimetype)) {
callback(null, true); callback(null, true);
} else { } else {
callback(null, false); callback(null, false);
} }
}; };

View file

@ -6,24 +6,24 @@ import {createUser} from "../lib/db";
const router: Router = express.Router(); const router: Router = express.Router();
/**Middleware to check if a user is actually signed in */ /**Middleware to check if a user is actually signed in */
const adminCheck: Middleware = (req: Request, res: Response, next: NextFunction) => { const adminCheck: Middleware = (req: Request, res: Response, next: NextFunction) => {
if (!req.user) if (!req.user)
return res.status(403).send("You are not authorized to perform this action"); return res.status(403).send("You are not authorized to perform this action");
else { else {
if (req.user.username != "admin") if (req.user.username != "admin")
return res.status(403).send("You are not authorized to perform this action"); return res.status(403).send("You are not authorized to perform this action");
} }
next(); next();
}; };
router.get("/adduser", adminCheck, (req: Request, res: Response) => { router.get("/adduser", adminCheck, (req: Request, res: Response) => {
res.locals.filter = null; res.locals.filter = null;
res.render("adduser", { user: req.user }); res.render("adduser", { user: req.user });
}); });
router.post("/adduser", adminCheck, (req: Request, res: Response) => { router.post("/adduser", adminCheck, (req: Request, res: Response) => {
createUser(req.body.username, req.body.password); createUser(req.body.username, req.body.password);
res.redirect("/"); res.redirect("/");
}); });
export default router; export default router;

View file

@ -9,77 +9,77 @@ import { db, UserRow } from "../lib/db";
const router = express.Router(); const router = express.Router();
passport.use( passport.use(
new LocalStrategy(function verify(username, password, cb) { new LocalStrategy(function verify(username, password, cb) {
db.get( db.get(
"SELECT * FROM users WHERE username = ?", "SELECT * FROM users WHERE username = ?",
[username], [username],
function (err: Error, row: UserRow) { function (err: Error, row: UserRow) {
if (err) { if (err) {
return cb(err); return cb(err);
} }
if (!row) { if (!row) {
return cb(null, false, { return cb(null, false, {
message: "Incorrect username or password.", message: "Incorrect username or password.",
}); });
} }
crypto.pbkdf2( crypto.pbkdf2(
password, password,
row.salt, row.salt,
310000, 310000,
32, 32,
"sha256", "sha256",
function (err, hashedPassword) { function (err, hashedPassword) {
if (err) { if (err) {
return cb(err); return cb(err);
} }
if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) { if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) {
return cb(null, false, { return cb(null, false, {
message: "Incorrect username or password.", message: "Incorrect username or password.",
}); });
} }
return cb(null, row); return cb(null, row);
}, },
);
},
); );
}, }),
);
}),
); );
passport.serializeUser(function (user: User, cb) { passport.serializeUser(function (user: User, cb) {
process.nextTick(function () { process.nextTick(function () {
cb(null, { cb(null, {
id: user.id, id: user.id,
username: user.username, username: user.username,
});
}); });
});
}); });
passport.deserializeUser(function (user: User, cb) { passport.deserializeUser(function (user: User, cb) {
process.nextTick(function () { process.nextTick(function () {
return cb(null, user); return cb(null, user);
}); });
}); });
router.get("/login", function (req, res) { router.get("/login", function (req, res) {
res.render("login"); res.render("login");
}); });
router.post( router.post(
"/login/password", "/login/password",
passport.authenticate("local", { passport.authenticate("local", {
successRedirect: "/", successRedirect: "/",
failureRedirect: "/login", failureRedirect: "/login",
}), }),
); );
router.post("/logout", function (req, res, next) { router.post("/logout", function (req, res, next) {
req.logout(function (err) { req.logout(function (err) {
if (err) { if (err) {
return next(err); return next(err);
} }
res.redirect("/"); res.redirect("/");
}); });
}); });
export default router; export default router;

View file

@ -1,8 +1,8 @@
import type { import type {
RequestHandler as Middleware, RequestHandler as Middleware,
Request, Request,
Response, Response,
NextFunction, NextFunction,
} from "express"; } from "express";
import multer from "multer"; import multer from "multer";
@ -18,184 +18,184 @@ import { extension, videoExtensions } from "../lib/lib";
import { db, MediaRow, getPath, deleteId } from "../lib/db"; import { db, MediaRow, getPath, deleteId } from "../lib/db";
import { fileStorage } from "../lib/multer"; import { fileStorage } from "../lib/multer";
import { import {
checkAuth, checkAuth,
checkSharexAuth, checkSharexAuth,
convertTo720p, convertTo720p,
createEmbedData, createEmbedData,
handleUpload, handleUpload,
} from "../lib/middleware"; } from "../lib/middleware";
const upload = multer({ storage: fileStorage /**, fileFilter: fileFilter**/ }); //maybe make this a env variable? const upload = multer({ storage: fileStorage /**, fileFilter: fileFilter**/ }); //maybe make this a env variable?
/**Middleware to grab media from media database */ /**Middleware to grab media from media database */
const fetchMedia: Middleware = (req, res, next) => { const fetchMedia: Middleware = (req, res, next) => {
const admin: boolean = req.user.username == "admin" ? true : false; const admin: boolean = req.user.username == "admin" ? true : false;
/**Check if the user is an admin, if so, show all posts from all users */ /**Check if the user is an admin, if so, show all posts from all users */
const query: string = const query: string =
admin == true admin == true
? "SELECT * FROM media" ? "SELECT * FROM media"
: `SELECT * FROM media WHERE username = '${req.user.username}'`; : `SELECT * FROM media WHERE username = '${req.user.username}'`;
db.all(query, (err: Error, rows: []) => { db.all(query, (err: Error, rows: []) => {
if (err) return next(err); if (err) return next(err);
const files = rows.map((row: MediaRow) => { const files = rows.map((row: MediaRow) => {
return { return {
id: row.id, id: row.id,
path: row.path, path: row.path,
expire: row.expire, expire: row.expire,
username: row.username, username: row.username,
url: "/" + row.id, url: "/" + row.id,
}; };
});
res.locals.files = files.reverse(); //reverse so newest files appear first
res.locals.Count = files.length;
next();
}); });
res.locals.files = files.reverse(); //reverse so newest files appear first
res.locals.Count = files.length;
next();
});
}; };
const router = express.Router(); const router = express.Router();
router.get( router.get(
"/", "/",
(req: Request, res: Response, next: NextFunction) => { (req: Request, res: Response, next: NextFunction) => {
if (!req.user) return res.render("home"); if (!req.user) return res.render("home");
next(); next();
}, },
fetchMedia, fetchMedia,
(req: Request, res: Response) => { (req: Request, res: Response) => {
res.locals.filter = null; res.locals.filter = null;
res.render("index", { user: req.user }); res.render("index", { user: req.user });
} }
); );
router.get("/media-list", fetchMedia, (req: Request, res: Response) => { router.get("/media-list", fetchMedia, (req: Request, res: Response) => {
res.render("partials/_fileList", { user: req.user }); res.render("partials/_fileList", { user: req.user });
}); });
router.get( router.get(
"/gifv/:file", "/gifv/:file",
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const url = `${req.protocol}://${req.get("host")}/uploads/${ const url = `${req.protocol}://${req.get("host")}/uploads/${
req.params.file req.params.file
}`; }`;
let width; let width;
let height; let height;
const [filename, fileExtension] = extension(`uploads/${req.params.file}`); const [filename, fileExtension] = extension(`uploads/${req.params.file}`);
if ( if (
fileExtension == ".mp4" || fileExtension == ".mp4" ||
fileExtension == ".mov" || fileExtension == ".mov" ||
fileExtension == ".webm" || fileExtension == ".webm" ||
fileExtension == ".gif" fileExtension == ".gif"
) { ) {
const imageData = ffProbe( const imageData = ffProbe(
`uploads/${req.params.file}`, `uploads/${req.params.file}`,
filename, filename,
fileExtension fileExtension
); );
width = (await imageData).streams[0].width; width = (await imageData).streams[0].width;
height = (await imageData).streams[0].height; height = (await imageData).streams[0].height;
return res.render("gifv", { return res.render("gifv", {
url: url, url: url,
host: `${req.protocol}://${req.get("host")}`, host: `${req.protocol}://${req.get("host")}`,
width: width, width: width,
height: height, height: height,
}); });
} else { } else {
const imageData = await imageProbe( const imageData = await imageProbe(
fs.createReadStream(`uploads/${req.params.file}`) fs.createReadStream(`uploads/${req.params.file}`)
); );
return res.render("gifv", { return res.render("gifv", {
url: url, url: url,
host: `${req.protocol}://${req.get("host")}`, host: `${req.protocol}://${req.get("host")}`,
width: imageData.width, width: imageData.width,
height: imageData.height, height: imageData.height,
}); });
}
} }
}
); );
router.post( router.post(
"/", "/",
[ [
checkAuth, checkAuth,
upload.array("fileupload"), upload.array("fileupload"),
convertTo720p, convertTo720p,
createEmbedData, createEmbedData,
handleUpload, handleUpload,
fetchMedia, fetchMedia,
], ],
(req: Request, res: Response) => { (req: Request, res: Response) => {
return res.render("partials/_fileList", { user: req.user }); // Render only the file list partial return res.render("partials/_fileList", { user: req.user }); // Render only the file list partial
} }
); );
router.post( router.post(
"/sharex", "/sharex",
[checkSharexAuth, upload.single("fileupload"), createEmbedData, handleUpload], [checkSharexAuth, upload.single("fileupload"), createEmbedData, handleUpload],
(req: Request, res: Response) => { (req: Request, res: Response) => {
return res.send( return res.send(
`${req.protocol}://${req.get("host")}/uploads/${req.file.filename}` `${req.protocol}://${req.get("host")}/uploads/${req.file.filename}`
); );
} }
); );
router.get( router.get(
"/:id(\\d+)/delete", "/:id(\\d+)/delete",
[checkAuth], [checkAuth],
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const filename: any = await getPath(req.params.id); const filename: any = await getPath(req.params.id);
const filePath = path.join(__dirname , "../../uploads/" + filename.path); const filePath = path.join(__dirname , "../../uploads/" + filename.path);
const oembed = path.join( const oembed = path.join(
__dirname , "../../uploads/oembed-" + filename.path + ".json" __dirname , "../../uploads/oembed-" + filename.path + ".json"
); );
const [fileName, fileExtension] = extension(filePath); const [fileName, fileExtension] = extension(filePath);
const filesToDelete = [filePath, oembed]; const filesToDelete = [filePath, oembed];
if ( if (
videoExtensions.includes(fileExtension) || videoExtensions.includes(fileExtension) ||
fileExtension == ".gif" fileExtension == ".gif"
) { ) {
filesToDelete.push( filesToDelete.push(
path.join(__dirname , "../../uploads/720p-" + filename.path) path.join(__dirname , "../../uploads/720p-" + filename.path)
); );
} }
// Wait for all file deletions and database operations to complete // Wait for all file deletions and database operations to complete
await Promise.all( await Promise.all(
filesToDelete.map(async (path) => { filesToDelete.map(async (path) => {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
fs.unlink(path, async (err) => { fs.unlink(path, async (err) => {
console.log(`Deleting ${path}`); console.log(`Deleting ${path}`);
if (err) { if (err) {
if ([-4058, -2].includes(err.errno)) { if ([-4058, -2].includes(err.errno)) {
//file not found //file not found
console.log("File not found, deleting from database"); console.log("File not found, deleting from database");
await deleteId("media", req.params.id); await deleteId("media", req.params.id);
} }
console.error(`Error deleting file ${path}:`, err); console.error(`Error deleting file ${path}:`, err);
reject(err); reject(err);
return; return;
} }
await deleteId("media", req.params.id); await deleteId("media", req.params.id);
resolve(); resolve();
}); });
});
})
).catch((err) => {
console.error("Error deleting files:", err);
return next(err);
}); });
})
).catch((err) => {
console.error("Error deleting files:", err);
return next(err);
});
next(); next();
}, },
[fetchMedia], [fetchMedia],
(req: Request, res: Response) => { (req: Request, res: Response) => {
return res.render("partials/_fileList", { user: req.user }); return res.render("partials/_fileList", { user: req.user });
} }
); );
export default router; export default router;

View file

@ -20,7 +20,7 @@ const fetchUsers = (): Promise<[UserRow]> => {
resolve(rows); resolve(rows);
}); });
}); });
} };
const fetchSettings: Middleware = async (req, res, next) => { const fetchSettings: Middleware = async (req, res, next) => {
res.locals.users = req.user.username == "admin" ? await fetchUsers() : null; res.locals.users = req.user.username == "admin" ? await fetchUsers() : null;