mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-11-19 20:50:09 +01:00
Merge branch 'master' of github.com:Mintplex-Labs/anything-llm into render
This commit is contained in:
commit
c6ad94d81a
@ -124,7 +124,7 @@ function isWithin(outer, inner) {
|
||||
|
||||
function normalizePath(filepath = "") {
|
||||
const result = path
|
||||
.normalize(filepath.trim())
|
||||
.normalize(filepath.replace(/\s/g, "-").trim())
|
||||
.replace(/^(\.\.(\/|\\|$))+/, "")
|
||||
.trim();
|
||||
if (["..", ".", "/"].includes(result)) throw new Error("Invalid path.");
|
||||
|
@ -108,10 +108,13 @@ export default function Footer() {
|
||||
rel="noreferrer"
|
||||
className="transition-all duration-300 p-2 rounded-full text-white bg-sidebar-button hover:bg-menu-item-selected-gradient hover:border-slate-100 hover:border-opacity-50 border-transparent border"
|
||||
>
|
||||
{React.createElement(ICON_COMPONENTS[item.icon], {
|
||||
{React.createElement(
|
||||
ICON_COMPONENTS?.[item.icon] ?? ICON_COMPONENTS.Info,
|
||||
{
|
||||
weight: "fill",
|
||||
className: "h-5 w-5",
|
||||
})}
|
||||
}
|
||||
)}
|
||||
</a>
|
||||
))}
|
||||
{!isMobile && <SettingsButton />}
|
||||
|
@ -33,10 +33,7 @@ function adminEndpoints(app) {
|
||||
[validatedRequest, strictMultiUserRoleValid([ROLES.admin, ROLES.manager])],
|
||||
async (_request, response) => {
|
||||
try {
|
||||
const users = (await User.where()).map((user) => {
|
||||
const { password, ...rest } = user;
|
||||
return rest;
|
||||
});
|
||||
const users = await User.where();
|
||||
response.status(200).json({ users });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -73,10 +73,7 @@ function apiAdminEndpoints(app) {
|
||||
return;
|
||||
}
|
||||
|
||||
const users = (await User.where()).map((user) => {
|
||||
const { password, ...rest } = user;
|
||||
return rest;
|
||||
});
|
||||
const users = await User.where();
|
||||
response.status(200).json({ users });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -115,7 +115,7 @@ function systemEndpoints(app) {
|
||||
|
||||
if (await SystemSettings.isMultiUserMode()) {
|
||||
const { username, password } = reqBody(request);
|
||||
const existingUser = await User.get({ username: String(username) });
|
||||
const existingUser = await User._get({ username: String(username) });
|
||||
|
||||
if (!existingUser) {
|
||||
await EventLogs.logEvent(
|
||||
@ -193,7 +193,7 @@ function systemEndpoints(app) {
|
||||
// Return recovery codes to frontend
|
||||
response.status(200).json({
|
||||
valid: true,
|
||||
user: existingUser,
|
||||
user: User.filterFields(existingUser),
|
||||
token: makeJWT(
|
||||
{ id: existingUser.id, username: existingUser.username },
|
||||
"30d"
|
||||
@ -206,7 +206,7 @@ function systemEndpoints(app) {
|
||||
|
||||
response.status(200).json({
|
||||
valid: true,
|
||||
user: existingUser,
|
||||
user: User.filterFields(existingUser),
|
||||
token: makeJWT(
|
||||
{ id: existingUser.id, username: existingUser.username },
|
||||
"30d"
|
||||
@ -1029,7 +1029,7 @@ function systemEndpoints(app) {
|
||||
|
||||
const updates = {};
|
||||
if (username) {
|
||||
updates.username = String(username);
|
||||
updates.username = User.validations.username(String(username));
|
||||
}
|
||||
if (password) {
|
||||
updates.password = String(password);
|
||||
|
@ -111,6 +111,7 @@ function workspaceEndpoints(app) {
|
||||
handleFileUpload,
|
||||
],
|
||||
async function (request, response) {
|
||||
try {
|
||||
const Collector = new CollectorApi();
|
||||
const { originalname } = request.file;
|
||||
const processingOnline = await Collector.online();
|
||||
@ -126,7 +127,8 @@ function workspaceEndpoints(app) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { success, reason } = await Collector.processDocument(originalname);
|
||||
const { success, reason } =
|
||||
await Collector.processDocument(originalname);
|
||||
if (!success) {
|
||||
response.status(500).json({ success: false, error: reason }).end();
|
||||
return;
|
||||
@ -144,6 +146,10 @@ function workspaceEndpoints(app) {
|
||||
response.locals?.user?.id
|
||||
);
|
||||
response.status(200).json({ success: true, error: null });
|
||||
} catch (e) {
|
||||
console.log(e.message, e);
|
||||
response.sendStatus(500).end();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -151,6 +157,7 @@ function workspaceEndpoints(app) {
|
||||
"/workspace/:slug/upload-link",
|
||||
[validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])],
|
||||
async (request, response) => {
|
||||
try {
|
||||
const Collector = new CollectorApi();
|
||||
const { link = "" } = reqBody(request);
|
||||
const processingOnline = await Collector.online();
|
||||
@ -182,6 +189,10 @@ function workspaceEndpoints(app) {
|
||||
response.locals?.user?.id
|
||||
);
|
||||
response.status(200).json({ success: true, error: null });
|
||||
} catch (e) {
|
||||
console.log(e.message, e);
|
||||
response.sendStatus(500).end();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -10,6 +10,20 @@ const User = {
|
||||
"role",
|
||||
"suspended",
|
||||
],
|
||||
validations: {
|
||||
username: (newValue = "") => {
|
||||
try {
|
||||
if (String(newValue).length > 100)
|
||||
throw new Error("Username cannot be longer than 100 characters");
|
||||
if (String(newValue).length < 2)
|
||||
throw new Error("Username must be at least 2 characters");
|
||||
return String(newValue);
|
||||
} catch (e) {
|
||||
throw new Error(e.message);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// validations for the above writable fields.
|
||||
castColumnValue: function (key, value) {
|
||||
switch (key) {
|
||||
@ -19,6 +33,12 @@ const User = {
|
||||
return String(value);
|
||||
}
|
||||
},
|
||||
|
||||
filterFields: function (user = {}) {
|
||||
const { password, ...rest } = user;
|
||||
return { ...rest };
|
||||
},
|
||||
|
||||
create: async function ({ username, password, role = "default" }) {
|
||||
const passwordCheck = this.checkPasswordComplexity(password);
|
||||
if (!passwordCheck.checkedOK) {
|
||||
@ -30,12 +50,12 @@ const User = {
|
||||
const hashedPassword = bcrypt.hashSync(password, 10);
|
||||
const user = await prisma.users.create({
|
||||
data: {
|
||||
username,
|
||||
username: this.validations.username(username),
|
||||
password: hashedPassword,
|
||||
role,
|
||||
role: String(role),
|
||||
},
|
||||
});
|
||||
return { user, error: null };
|
||||
return { user: this.filterFields(user), error: null };
|
||||
} catch (error) {
|
||||
console.error("FAILED TO CREATE USER.", error.message);
|
||||
return { user: null, error: error.message };
|
||||
@ -69,7 +89,13 @@ const User = {
|
||||
// and force-casts to the proper type;
|
||||
Object.entries(updates).forEach(([key, value]) => {
|
||||
if (this.writable.includes(key)) {
|
||||
if (this.validations.hasOwnProperty(key)) {
|
||||
updates[key] = this.validations[key](
|
||||
this.castColumnValue(key, value)
|
||||
);
|
||||
} else {
|
||||
updates[key] = this.castColumnValue(key, value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
delete updates[key];
|
||||
@ -127,6 +153,17 @@ const User = {
|
||||
},
|
||||
|
||||
get: async function (clause = {}) {
|
||||
try {
|
||||
const user = await prisma.users.findFirst({ where: clause });
|
||||
return user ? this.filterFields({ ...user }) : null;
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
// Returns user object with all fields
|
||||
_get: async function (clause = {}) {
|
||||
try {
|
||||
const user = await prisma.users.findFirst({ where: clause });
|
||||
return user ? { ...user } : null;
|
||||
@ -162,7 +199,7 @@ const User = {
|
||||
where: clause,
|
||||
...(limit !== null ? { take: limit } : {}),
|
||||
});
|
||||
return users;
|
||||
return users.map((usr) => this.filterFields(usr));
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
return [];
|
||||
|
@ -38,7 +38,10 @@ class VoyageAiEmbedder {
|
||||
Array.isArray(textInput) ? textInput : [textInput],
|
||||
{ modelName: this.model }
|
||||
);
|
||||
return result || [];
|
||||
|
||||
// If given an array return the native Array[Array] format since that should be the outcome.
|
||||
// But if given a single string, we need to flatten it so that we have a 1D array.
|
||||
return (Array.isArray(textInput) ? result : result.flat()) || [];
|
||||
}
|
||||
|
||||
async embedChunks(textChunks = []) {
|
||||
@ -50,6 +53,12 @@ class VoyageAiEmbedder {
|
||||
return embeddings;
|
||||
} catch (error) {
|
||||
console.error("Voyage AI Failed to embed:", error);
|
||||
if (
|
||||
error.message.includes(
|
||||
"Cannot read properties of undefined (reading '0')"
|
||||
)
|
||||
)
|
||||
throw new Error("Voyage AI failed to embed: Rate limit reached");
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user