2023-06-08 22:13:48 +02:00
process . env . NODE _ENV === "development"
? require ( "dotenv" ) . config ( { path : ` .env. ${ process . env . NODE _ENV } ` } )
: require ( "dotenv" ) . config ( ) ;
2023-06-08 06:31:35 +02:00
const { viewLocalFiles } = require ( "../utils/files" ) ;
2023-07-15 02:32:30 +02:00
const { exportData , unpackAndOverwriteImport } = require ( "../utils/files/data" ) ;
2023-06-17 01:01:27 +02:00
const {
2023-12-15 00:14:56 +01:00
checkProcessorAlive ,
2023-06-17 01:01:27 +02:00
acceptedFileTypes ,
} = require ( "../utils/files/documentProcessor" ) ;
2023-12-19 00:48:02 +01:00
const { purgeDocument , purgeFolder } = require ( "../utils/files/purgeDocument" ) ;
2023-12-04 17:38:15 +01:00
const { getVectorDbClass } = require ( "../utils/helpers" ) ;
2023-08-16 01:00:27 +02:00
const { updateENV , dumpENV } = require ( "../utils/helpers/updateENV" ) ;
2023-07-25 19:37:04 +02:00
const {
reqBody ,
makeJWT ,
userFromSession ,
multiUserMode ,
2024-01-10 22:18:48 +01:00
queryParams ,
2023-07-25 19:37:04 +02:00
} = require ( "../utils/http" ) ;
2023-12-07 23:11:51 +01:00
const {
setupDataImports ,
setupLogoUploads ,
setupPfpUploads ,
} = require ( "../utils/files/multer" ) ;
2023-07-21 00:25:47 +02:00
const { v4 } = require ( "uuid" ) ;
2023-07-25 19:37:04 +02:00
const { SystemSettings } = require ( "../models/systemSettings" ) ;
const { User } = require ( "../models/user" ) ;
const { validatedRequest } = require ( "../utils/middleware/validatedRequest" ) ;
2023-07-15 02:32:30 +02:00
const { handleImports } = setupDataImports ( ) ;
2023-08-15 00:22:55 +02:00
const { handleLogoUploads } = setupLogoUploads ( ) ;
2023-12-07 23:11:51 +01:00
const { handlePfpUploads } = setupPfpUploads ( ) ;
2023-09-11 22:07:48 +02:00
const fs = require ( "fs" ) ;
2023-08-15 00:22:55 +02:00
const path = require ( "path" ) ;
const {
getDefaultFilename ,
determineLogoFilepath ,
fetchLogo ,
validFilename ,
renameLogoFile ,
removeCustomLogo ,
2023-10-23 22:10:34 +02:00
LOGO _FILENAME ,
2023-08-15 00:22:55 +02:00
} = require ( "../utils/files/logo" ) ;
2023-08-15 02:42:17 +02:00
const { Telemetry } = require ( "../models/telemetry" ) ;
2023-08-17 02:30:46 +02:00
const { WelcomeMessages } = require ( "../models/welcomeMessages" ) ;
2023-08-24 04:15:07 +02:00
const { ApiKey } = require ( "../models/apiKeys" ) ;
2023-10-31 19:38:28 +01:00
const { getCustomModels } = require ( "../utils/helpers/customModels" ) ;
2023-11-09 02:36:54 +01:00
const { WorkspaceChats } = require ( "../models/workspaceChats" ) ;
const { Workspace } = require ( "../models/workspace" ) ;
2023-11-13 23:51:16 +01:00
const { flexUserRoleValid } = require ( "../utils/middleware/multiUserProtected" ) ;
2023-12-07 23:11:51 +01:00
const { fetchPfp , determinePfpFilepath } = require ( "../utils/files/pfp" ) ;
2023-06-04 04:28:07 +02:00
function systemEndpoints ( app ) {
if ( ! app ) return ;
2023-06-08 06:31:35 +02:00
app . get ( "/ping" , ( _ , response ) => {
2023-08-17 00:43:46 +02:00
response . status ( 200 ) . json ( { online : true } ) ;
2023-06-08 06:31:35 +02:00
} ) ;
2023-06-04 04:28:07 +02:00
2023-06-17 01:01:27 +02:00
app . get ( "/migrate" , async ( _ , response ) => {
2023-09-28 23:00:03 +02:00
const execSync = require ( "child_process" ) . execSync ;
execSync ( "npx prisma migrate deploy --schema=./prisma/schema.prisma" , {
stdio : "inherit" ,
} ) ;
2023-06-17 01:01:27 +02:00
response . sendStatus ( 200 ) ;
} ) ;
2023-08-16 01:00:27 +02:00
app . get ( "/env-dump" , async ( _ , response ) => {
if ( process . env . NODE _ENV !== "production" )
return response . sendStatus ( 200 ) . end ( ) ;
await dumpENV ( ) ;
response . sendStatus ( 200 ) . end ( ) ;
} ) ;
2023-07-25 19:37:04 +02:00
app . get ( "/setup-complete" , async ( _ , response ) => {
2023-06-08 22:13:48 +02:00
try {
2023-08-24 04:15:07 +02:00
const results = await SystemSettings . currentSettings ( ) ;
2023-06-08 22:13:48 +02:00
response . status ( 200 ) . json ( { results } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-08 06:31:35 +02:00
} ) ;
2023-06-04 04:28:07 +02:00
2023-07-25 19:37:04 +02:00
app . get (
"/system/check-token" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
if ( multiUserMode ( response ) ) {
const user = await userFromSession ( request , response ) ;
if ( ! user || user . suspended ) {
response . sendStatus ( 403 ) . end ( ) ;
return ;
}
response . sendStatus ( 200 ) . end ( ) ;
return ;
}
2023-06-09 20:27:27 +02:00
2023-07-25 19:37:04 +02:00
response . sendStatus ( 200 ) . end ( ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . post ( "/request-token" , async ( request , response ) => {
2023-06-09 20:27:27 +02:00
try {
2024-01-11 19:54:55 +01:00
const bcrypt = require ( "bcrypt" ) ;
2023-07-25 19:37:04 +02:00
if ( await SystemSettings . isMultiUserMode ( ) ) {
const { username , password } = reqBody ( request ) ;
2023-09-28 23:00:03 +02:00
const existingUser = await User . get ( { username } ) ;
2023-07-25 19:37:04 +02:00
if ( ! existingUser ) {
response . status ( 200 ) . json ( {
user : null ,
valid : false ,
token : null ,
message : "[001] Invalid login credentials." ,
} ) ;
return ;
}
if ( ! bcrypt . compareSync ( password , existingUser . password ) ) {
response . status ( 200 ) . json ( {
user : null ,
valid : false ,
token : null ,
message : "[002] Invalid login credentials." ,
} ) ;
return ;
}
if ( existingUser . suspended ) {
response . status ( 200 ) . json ( {
user : null ,
valid : false ,
token : null ,
message : "[004] Account suspended by admin." ,
} ) ;
return ;
}
2023-11-11 01:02:46 +01:00
await Telemetry . sendTelemetry (
"login_event" ,
{ multiUserMode : false } ,
existingUser ? . id
) ;
2023-07-25 19:37:04 +02:00
response . status ( 200 ) . json ( {
valid : true ,
user : existingUser ,
token : makeJWT (
{ id : existingUser . id , username : existingUser . username } ,
"30d"
) ,
message : null ,
2023-06-09 21:59:22 +02:00
} ) ;
2023-06-09 20:27:27 +02:00
return ;
2023-07-25 19:37:04 +02:00
} else {
const { password } = reqBody ( request ) ;
2024-01-11 19:54:55 +01:00
if (
! bcrypt . compareSync (
password ,
bcrypt . hashSync ( process . env . AUTH _TOKEN , 10 )
)
) {
2023-07-25 19:37:04 +02:00
response . status ( 401 ) . json ( {
valid : false ,
token : null ,
message : "[003] Invalid password provided" ,
} ) ;
return ;
}
2023-06-09 20:27:27 +02:00
2023-11-11 01:02:46 +01:00
await Telemetry . sendTelemetry ( "login_event" , { multiUserMode : false } ) ;
2023-07-25 19:37:04 +02:00
response . status ( 200 ) . json ( {
valid : true ,
token : makeJWT ( { p : password } , "30d" ) ,
message : null ,
} ) ;
}
2023-06-09 20:27:27 +02:00
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
2024-01-10 22:18:48 +01:00
app . get (
"/system/system-vectors" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
const query = queryParams ( request ) ;
const VectorDb = getVectorDbClass ( ) ;
const vectorCount = ! ! query . slug
? await VectorDb . namespaceCount ( query . slug )
: await VectorDb . totalVectors ( ) ;
response . status ( 200 ) . json ( { vectorCount } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-08 22:13:48 +02:00
}
2024-01-10 22:18:48 +01:00
) ;
2023-06-04 04:28:07 +02:00
2023-07-25 19:37:04 +02:00
app . delete (
"/system/remove-document" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
2023-12-19 00:48:02 +01:00
const { name } = reqBody ( request ) ;
await purgeDocument ( name ) ;
response . sendStatus ( 200 ) . end ( ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . delete (
"/system/remove-folder" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
const { name } = reqBody ( request ) ;
await purgeFolder ( name ) ;
2023-07-25 19:37:04 +02:00
response . sendStatus ( 200 ) . end ( ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-27 02:20:09 +02:00
}
2023-07-25 19:37:04 +02:00
) ;
2023-06-27 02:20:09 +02:00
2023-07-25 19:37:04 +02:00
app . get ( "/system/local-files" , [ validatedRequest ] , async ( _ , response ) => {
2023-06-08 22:13:48 +02:00
try {
const localFiles = await viewLocalFiles ( ) ;
response . status ( 200 ) . json ( { localFiles } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-08 06:31:35 +02:00
} ) ;
2023-06-17 01:01:27 +02:00
2023-07-25 19:37:04 +02:00
app . get (
"/system/document-processing-status" ,
[ validatedRequest ] ,
async ( _ , response ) => {
try {
2023-12-15 00:14:56 +01:00
const online = await checkProcessorAlive ( ) ;
2023-07-25 19:37:04 +02:00
response . sendStatus ( online ? 200 : 503 ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-17 01:01:27 +02:00
}
2023-07-25 19:37:04 +02:00
) ;
2023-06-17 01:01:27 +02:00
2023-07-25 19:37:04 +02:00
app . get (
"/system/accepted-document-types" ,
[ validatedRequest ] ,
async ( _ , response ) => {
try {
const types = await acceptedFileTypes ( ) ;
if ( ! types ) {
response . sendStatus ( 404 ) . end ( ) ;
return ;
}
response . status ( 200 ) . json ( { types } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
2023-06-17 01:01:27 +02:00
}
2023-07-25 19:37:04 +02:00
}
) ;
2023-06-17 01:01:27 +02:00
2023-07-25 19:37:04 +02:00
app . post (
"/system/update-env" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
2023-07-25 19:37:04 +02:00
async ( request , response ) => {
try {
const body = reqBody ( request ) ;
const { newValues , error } = updateENV ( body ) ;
2023-08-22 00:38:18 +02:00
if ( process . env . NODE _ENV === "production" ) await dumpENV ( ) ;
2023-07-25 19:37:04 +02:00
response . status ( 200 ) . json ( { newValues , error } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-17 01:01:27 +02:00
}
2023-07-25 19:37:04 +02:00
) ;
2023-06-26 20:38:38 +02:00
2023-07-25 19:37:04 +02:00
app . post (
"/system/update-password" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
2023-09-29 19:44:40 +02:00
// Cannot update password in multi - user mode.
if ( multiUserMode ( response ) ) {
response . sendStatus ( 401 ) . end ( ) ;
return ;
}
2023-07-25 19:37:04 +02:00
const { usePassword , newPassword } = reqBody ( request ) ;
2023-09-29 19:44:40 +02:00
const { error } = updateENV (
{
AuthToken : usePassword ? newPassword : "" ,
JWTSecret : usePassword ? v4 ( ) : "" ,
} ,
true
) ;
if ( process . env . NODE _ENV === "production" ) await dumpENV ( ) ;
2023-07-25 19:37:04 +02:00
response . status ( 200 ) . json ( { success : ! error , error } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-07-21 00:25:47 +02:00
}
2023-07-25 19:37:04 +02:00
) ;
2023-07-21 00:25:47 +02:00
2023-07-25 19:37:04 +02:00
app . post (
"/system/enable-multi-user" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
const { username , password } = reqBody ( request ) ;
const multiUserModeEnabled = await SystemSettings . isMultiUserMode ( ) ;
if ( multiUserModeEnabled ) {
response . status ( 200 ) . json ( {
success : false ,
error : "Multi-user mode is already enabled." ,
} ) ;
return ;
}
const { user , error } = await User . create ( {
username ,
password ,
role : "admin" ,
} ) ;
await SystemSettings . updateSettings ( {
multi _user _mode : true ,
users _can _delete _workspaces : false ,
limit _user _messages : false ,
message _limit : 25 ,
} ) ;
2023-09-29 19:44:40 +02:00
updateENV (
{
2023-10-05 23:34:30 +02:00
AuthToken : "" ,
2023-10-23 22:10:34 +02:00
JWTSecret : process . env . JWT _SECRET || v4 ( ) ,
2023-09-29 19:44:40 +02:00
} ,
true
) ;
if ( process . env . NODE _ENV === "production" ) await dumpENV ( ) ;
2023-11-11 01:02:46 +01:00
await Telemetry . sendTelemetry ( "enabled_multi_user_mode" , {
multiUserMode : true ,
} ) ;
2023-07-25 19:37:04 +02:00
response . status ( 200 ) . json ( { success : ! ! user , error } ) ;
} catch ( e ) {
2023-10-23 22:10:34 +02:00
await User . delete ( { } ) ;
await SystemSettings . updateSettings ( {
multi _user _mode : false ,
} ) ;
2023-07-25 19:37:04 +02:00
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
2023-06-26 20:38:38 +02:00
}
2023-07-25 19:37:04 +02:00
) ;
2023-07-15 02:32:30 +02:00
2023-10-23 22:10:34 +02:00
app . get ( "/system/multi-user-mode" , async ( request , response ) => {
try {
const multiUserMode = await SystemSettings . isMultiUserMode ( ) ;
response . status ( 200 ) . json ( { multiUserMode } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
2023-07-25 19:37:04 +02:00
app . get ( "/system/data-export" , [ validatedRequest ] , async ( _ , response ) => {
2023-07-15 02:32:30 +02:00
try {
const { filename , error } = await exportData ( ) ;
response . status ( 200 ) . json ( { filename , error } ) ;
} catch ( e ) {
console . log ( e . message , e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
2023-10-23 22:10:34 +02:00
app . get ( "/system/data-exports/:filename" , ( request , response ) => {
const exportLocation = _ _dirname + "/../storage/exports/" ;
const sanitized = path
. normalize ( request . params . filename )
. replace ( /^(\.\.(\/|\\|$))+/ , "" ) ;
const finalDestination = path . join ( exportLocation , sanitized ) ;
if ( ! fs . existsSync ( finalDestination ) ) {
response . status ( 404 ) . json ( {
error : 404 ,
msg : ` File ${ request . params . filename } does not exist in exports. ` ,
2023-07-25 19:37:04 +02:00
} ) ;
2023-10-23 22:10:34 +02:00
return ;
2023-07-25 19:37:04 +02:00
}
2023-10-23 22:10:34 +02:00
response . download ( finalDestination , request . params . filename , ( err ) => {
if ( err ) {
response . send ( {
error : err ,
msg : "Problem downloading the file" ,
} ) ;
}
// delete on download because endpoint is not authenticated.
fs . rmSync ( finalDestination ) ;
} ) ;
} ) ;
2023-07-15 02:32:30 +02:00
app . post (
"/system/data-import" ,
handleImports . single ( "file" ) ,
async function ( request , response ) {
const { originalname } = request . file ;
const { success , error } = await unpackAndOverwriteImport ( originalname ) ;
response . status ( 200 ) . json ( { success , error } ) ;
}
) ;
2023-08-15 00:22:55 +02:00
2023-10-23 22:10:34 +02:00
app . get ( "/system/logo" , async function ( request , response ) {
2023-08-15 00:22:55 +02:00
try {
2023-10-23 22:10:34 +02:00
const defaultFilename = getDefaultFilename ( ) ;
2023-08-15 00:22:55 +02:00
const logoPath = await determineLogoFilepath ( defaultFilename ) ;
2023-12-07 23:11:51 +01:00
const { found , buffer , size , mime } = fetchLogo ( logoPath ) ;
if ( ! found ) {
response . sendStatus ( 204 ) . end ( ) ;
return ;
}
2023-08-15 00:22:55 +02:00
response . writeHead ( 200 , {
"Content-Type" : mime || "image/png" ,
"Content-Disposition" : ` attachment; filename= ${ path . basename (
logoPath
) } ` ,
"Content-Length" : size ,
} ) ;
response . end ( Buffer . from ( buffer , "base64" ) ) ;
return ;
} catch ( error ) {
console . error ( "Error processing the logo request:" , error ) ;
response . status ( 500 ) . json ( { message : "Internal server error" } ) ;
}
} ) ;
2023-12-07 23:11:51 +01:00
app . get ( "/system/pfp/:id" , async function ( request , response ) {
try {
const { id } = request . params ;
const pfpPath = await determinePfpFilepath ( id ) ;
if ( ! pfpPath ) {
response . sendStatus ( 204 ) . end ( ) ;
return ;
}
const { found , buffer , size , mime } = fetchPfp ( pfpPath ) ;
if ( ! found ) {
response . sendStatus ( 204 ) . end ( ) ;
return ;
}
response . writeHead ( 200 , {
"Content-Type" : mime || "image/png" ,
"Content-Disposition" : ` attachment; filename= ${ path . basename ( pfpPath ) } ` ,
"Content-Length" : size ,
} ) ;
response . end ( Buffer . from ( buffer , "base64" ) ) ;
return ;
} catch ( error ) {
console . error ( "Error processing the logo request:" , error ) ;
response . status ( 500 ) . json ( { message : "Internal server error" } ) ;
}
} ) ;
app . post (
"/system/upload-pfp" ,
[ validatedRequest , flexUserRoleValid ] ,
handlePfpUploads . single ( "file" ) ,
async function ( request , response ) {
try {
const user = await userFromSession ( request , response ) ;
const uploadedFileName = request . randomFileName ;
if ( ! uploadedFileName ) {
return response . status ( 400 ) . json ( { message : "File upload failed." } ) ;
}
const userRecord = await User . get ( { id : user . id } ) ;
const oldPfpFilename = userRecord . pfpFilename ;
console . log ( "oldPfpFilename" , oldPfpFilename ) ;
if ( oldPfpFilename ) {
const oldPfpPath = path . join (
_ _dirname ,
` ../storage/assets/pfp/ ${ oldPfpFilename } `
) ;
if ( fs . existsSync ( oldPfpPath ) ) fs . unlinkSync ( oldPfpPath ) ;
}
const { success , error } = await User . update ( user . id , {
pfpFilename : uploadedFileName ,
} ) ;
return response . status ( success ? 200 : 500 ) . json ( {
message : success
? "Profile picture uploaded successfully."
: error || "Failed to update with new profile picture." ,
} ) ;
} catch ( error ) {
console . error ( "Error processing the profile picture upload:" , error ) ;
response . status ( 500 ) . json ( { message : "Internal server error" } ) ;
}
}
) ;
app . delete (
"/system/remove-pfp" ,
[ validatedRequest , flexUserRoleValid ] ,
async function ( request , response ) {
try {
const user = await userFromSession ( request , response ) ;
const userRecord = await User . get ( { id : user . id } ) ;
const oldPfpFilename = userRecord . pfpFilename ;
console . log ( "oldPfpFilename" , oldPfpFilename ) ;
if ( oldPfpFilename ) {
const oldPfpPath = path . join (
_ _dirname ,
` ../storage/assets/pfp/ ${ oldPfpFilename } `
) ;
if ( fs . existsSync ( oldPfpPath ) ) fs . unlinkSync ( oldPfpPath ) ;
}
const { success , error } = await User . update ( user . id , {
pfpFilename : null ,
} ) ;
return response . status ( success ? 200 : 500 ) . json ( {
message : success
? "Profile picture removed successfully."
: error || "Failed to remove profile picture." ,
} ) ;
} catch ( error ) {
console . error ( "Error processing the profile picture removal:" , error ) ;
response . status ( 500 ) . json ( { message : "Internal server error" } ) ;
}
}
) ;
2023-08-15 00:22:55 +02:00
app . post (
"/system/upload-logo" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
2023-08-15 00:22:55 +02:00
handleLogoUploads . single ( "logo" ) ,
async ( request , response ) => {
if ( ! request . file || ! request . file . originalname ) {
return response . status ( 400 ) . json ( { message : "No logo file provided." } ) ;
}
if ( ! validFilename ( request . file . originalname ) ) {
return response . status ( 400 ) . json ( {
message : "Invalid file name. Please choose a different file." ,
} ) ;
}
try {
const newFilename = await renameLogoFile ( request . file . originalname ) ;
const existingLogoFilename = await SystemSettings . currentLogoFilename ( ) ;
await removeCustomLogo ( existingLogoFilename ) ;
const { success , error } = await SystemSettings . updateSettings ( {
logo _filename : newFilename ,
} ) ;
return response . status ( success ? 200 : 500 ) . json ( {
message : success
? "Logo uploaded successfully."
: error || "Failed to update with new logo." ,
} ) ;
} catch ( error ) {
console . error ( "Error processing the logo upload:" , error ) ;
response . status ( 500 ) . json ( { message : "Error uploading the logo." } ) ;
}
}
) ;
2023-10-23 22:10:34 +02:00
app . get ( "/system/is-default-logo" , async ( request , response ) => {
try {
const currentLogoFilename = await SystemSettings . currentLogoFilename ( ) ;
const isDefaultLogo = currentLogoFilename === LOGO _FILENAME ;
response . status ( 200 ) . json ( { isDefaultLogo } ) ;
} catch ( error ) {
console . error ( "Error processing the logo request:" , error ) ;
response . status ( 500 ) . json ( { message : "Internal server error" } ) ;
}
} ) ;
2023-08-15 00:22:55 +02:00
app . get (
"/system/remove-logo" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
async ( _request , response ) => {
2023-08-15 00:22:55 +02:00
try {
const currentLogoFilename = await SystemSettings . currentLogoFilename ( ) ;
await removeCustomLogo ( currentLogoFilename ) ;
const { success , error } = await SystemSettings . updateSettings ( {
2023-10-23 22:10:34 +02:00
logo _filename : LOGO _FILENAME ,
2023-08-15 00:22:55 +02:00
} ) ;
return response . status ( success ? 200 : 500 ) . json ( {
message : success
? "Logo removed successfully."
: error || "Failed to update with new logo." ,
} ) ;
} catch ( error ) {
console . error ( "Error processing the logo removal:" , error ) ;
response . status ( 500 ) . json ( { message : "Error removing the logo." } ) ;
}
}
) ;
2023-08-17 02:30:46 +02:00
2023-08-31 00:28:30 +02:00
app . get (
"/system/can-delete-workspaces" ,
[ validatedRequest ] ,
async function ( request , response ) {
try {
if ( ! response . locals . multiUserMode ) {
return response . status ( 200 ) . json ( { canDelete : true } ) ;
}
2023-11-13 23:51:16 +01:00
const user = await userFromSession ( request , response ) ;
if ( [ "admin" , "manager" ] . includes ( user ? . role ) ) {
2023-08-31 00:28:30 +02:00
return response . status ( 200 ) . json ( { canDelete : true } ) ;
}
const canDelete = await SystemSettings . canDeleteWorkspaces ( ) ;
response . status ( 200 ) . json ( { canDelete } ) ;
} catch ( error ) {
console . error ( "Error fetching can delete workspaces:" , error ) ;
2023-09-11 22:07:48 +02:00
response . status ( 500 ) . json ( {
success : false ,
message : "Internal server error" ,
canDelete : false ,
} ) ;
2023-08-31 00:28:30 +02:00
}
}
) ;
2023-08-17 02:30:46 +02:00
app . get ( "/system/welcome-messages" , async function ( request , response ) {
try {
const welcomeMessages = await WelcomeMessages . getMessages ( ) ;
response . status ( 200 ) . json ( { success : true , welcomeMessages } ) ;
} catch ( error ) {
console . error ( "Error fetching welcome messages:" , error ) ;
response
. status ( 500 )
. json ( { success : false , message : "Internal server error" } ) ;
}
} ) ;
app . post (
"/system/set-welcome-messages" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
2023-08-17 02:30:46 +02:00
async ( request , response ) => {
try {
const { messages = [ ] } = reqBody ( request ) ;
if ( ! Array . isArray ( messages ) ) {
return response . status ( 400 ) . json ( {
success : false ,
message : "Invalid message format. Expected an array of messages." ,
} ) ;
}
await WelcomeMessages . saveAll ( messages ) ;
return response . status ( 200 ) . json ( {
success : true ,
message : "Welcome messages saved successfully." ,
} ) ;
} catch ( error ) {
console . error ( "Error processing the welcome messages:" , error ) ;
response . status ( 500 ) . json ( {
success : true ,
message : "Error saving the welcome messages." ,
} ) ;
}
}
) ;
2023-08-24 04:15:07 +02:00
2023-10-23 22:10:34 +02:00
app . get ( "/system/api-keys" , [ validatedRequest ] , async ( _ , response ) => {
2023-08-24 04:15:07 +02:00
try {
if ( response . locals . multiUserMode ) {
return response . sendStatus ( 401 ) . end ( ) ;
}
2023-10-23 22:10:34 +02:00
const apiKeys = await ApiKey . where ( { } ) ;
2023-08-24 04:15:07 +02:00
return response . status ( 200 ) . json ( {
2023-10-23 22:10:34 +02:00
apiKeys ,
2023-08-24 04:15:07 +02:00
error : null ,
} ) ;
} catch ( error ) {
console . error ( error ) ;
response . status ( 500 ) . json ( {
apiKey : null ,
error : "Could not find an API Key." ,
} ) ;
}
} ) ;
app . post (
"/system/generate-api-key" ,
[ validatedRequest ] ,
async ( _ , response ) => {
try {
if ( response . locals . multiUserMode ) {
return response . sendStatus ( 401 ) . end ( ) ;
}
const { apiKey , error } = await ApiKey . create ( ) ;
return response . status ( 200 ) . json ( {
apiKey ,
error ,
} ) ;
} catch ( error ) {
console . error ( error ) ;
response . status ( 500 ) . json ( {
apiKey : null ,
error : "Error generating api key." ,
} ) ;
}
}
) ;
app . delete ( "/system/api-key" , [ validatedRequest ] , async ( _ , response ) => {
try {
if ( response . locals . multiUserMode ) {
return response . sendStatus ( 401 ) . end ( ) ;
}
await ApiKey . delete ( ) ;
return response . status ( 200 ) . end ( ) ;
} catch ( error ) {
console . error ( error ) ;
response . status ( 500 ) . end ( ) ;
}
} ) ;
2023-10-31 19:38:28 +01:00
app . post (
"/system/custom-models" ,
[ validatedRequest ] ,
async ( request , response ) => {
try {
2023-11-14 21:31:44 +01:00
const { provider , apiKey = null , basePath = null } = reqBody ( request ) ;
const { models , error } = await getCustomModels (
provider ,
apiKey ,
basePath
) ;
2023-10-31 19:38:28 +01:00
return response . status ( 200 ) . json ( {
models ,
error ,
} ) ;
} catch ( error ) {
console . error ( error ) ;
response . status ( 500 ) . end ( ) ;
}
}
) ;
2023-11-09 02:36:54 +01:00
app . post (
"/system/workspace-chats" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
2023-11-09 02:36:54 +01:00
async ( request , response ) => {
try {
const { offset = 0 , limit = 20 } = reqBody ( request ) ;
const chats = await WorkspaceChats . whereWithData (
{ } ,
limit ,
offset * limit ,
{ id : "desc" }
) ;
const totalChats = await WorkspaceChats . count ( ) ;
const hasPages = totalChats > ( offset + 1 ) * limit ;
response . status ( 200 ) . json ( { chats : chats , hasPages , totalChats } ) ;
} catch ( e ) {
console . error ( e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . delete (
"/system/workspace-chats/:id" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
2023-11-09 02:36:54 +01:00
async ( request , response ) => {
try {
const { id } = request . params ;
await WorkspaceChats . delete ( { id : Number ( id ) } ) ;
2023-12-21 19:31:14 +01:00
response . sendStatus ( 200 ) . end ( ) ;
2023-11-09 02:36:54 +01:00
} catch ( e ) {
console . error ( e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . get (
"/system/export-chats" ,
2023-11-13 23:51:16 +01:00
[ validatedRequest , flexUserRoleValid ] ,
async ( _request , response ) => {
2023-11-09 02:36:54 +01:00
try {
const chats = await WorkspaceChats . whereWithData ( { } , null , null , {
id : "asc" ,
} ) ;
const workspaceIds = [
... new Set ( chats . map ( ( chat ) => chat . workspaceId ) ) ,
] ;
const workspacesWithPrompts = await Promise . all (
workspaceIds . map ( ( id ) => Workspace . get ( { id : Number ( id ) } ) )
) ;
const workspacePromptsMap = workspacesWithPrompts . reduce (
( acc , workspace ) => {
acc [ workspace . id ] = workspace . openAiPrompt ;
return acc ;
} ,
{ }
) ;
const workspaceChatsMap = chats . reduce ( ( acc , chat ) => {
const { prompt , response , workspaceId } = chat ;
const responseJson = JSON . parse ( response ) ;
if ( ! acc [ workspaceId ] ) {
acc [ workspaceId ] = {
messages : [
{
role : "system" ,
content :
workspacePromptsMap [ workspaceId ] ||
"Given the following conversation, relevant context, and a follow up question, reply with an answer to the current question the user is asking. Return only your response to the question given the above information following the users instructions as needed." ,
} ,
] ,
} ;
}
acc [ workspaceId ] . messages . push (
{
role : "user" ,
content : prompt ,
} ,
{
role : "assistant" ,
content : responseJson . text ,
}
) ;
return acc ;
} , { } ) ;
// Convert to JSONL
const jsonl = Object . values ( workspaceChatsMap )
. map ( ( workspaceChats ) => JSON . stringify ( workspaceChats ) )
. join ( "\n" ) ;
response . setHeader ( "Content-Type" , "application/jsonl" ) ;
response . status ( 200 ) . send ( jsonl ) ;
} catch ( e ) {
console . error ( e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
2023-12-07 23:11:51 +01:00
app . post ( "/system/user" , [ validatedRequest ] , async ( request , response ) => {
try {
const sessionUser = await userFromSession ( request , response ) ;
const { username , password } = reqBody ( request ) ;
const id = Number ( sessionUser . id ) ;
if ( ! id ) {
response . status ( 400 ) . json ( { success : false , error : "Invalid user ID" } ) ;
return ;
}
const updates = { } ;
if ( username ) {
updates . username = username ;
}
if ( password ) {
updates . password = password ;
}
if ( Object . keys ( updates ) . length === 0 ) {
response
. status ( 400 )
. json ( { success : false , error : "No updates provided" } ) ;
return ;
}
const { success , error } = await User . update ( id , updates ) ;
response . status ( 200 ) . json ( { success , error } ) ;
} catch ( e ) {
console . error ( e ) ;
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
2023-06-04 04:28:07 +02:00
}
2023-06-08 22:13:48 +02:00
module . exports = { systemEndpoints } ;