🔧 refactor: Organize Sharing/Agent Components and Improve Type Safety

refactor: organize Sharing/Agent components, improve type safety for resource types and access role ids, rename enums to PascalCase

refactor: organize Sharing/Agent components, improve type safety for resource types and access role ids

chore: move sharing related components to dedicated "Sharing" directory

chore: remove PublicSharingToggle component and update index exports

chore: move non-sidepanel agent components to `~/components/Agents`

chore: move AgentCategoryDisplay component with tests

chore: remove commented out code

refactor: change PERMISSION_BITS from const to enum for better type safety

refactor: reorganize imports in GenericGrantAccessDialog and update index exports for hooks

refactor: update type definitions to use ACCESS_ROLE_IDS for improved type safety

refactor: remove unused canAccessPromptResource middleware and related code

refactor: remove unused prompt access roles from createAccessRoleMethods

refactor: update resourceType in AclEntry type definition to remove unused 'prompt' value

refactor: introduce ResourceType enum and update resourceType usage across data provider files for improved type safety

refactor: update resourceType usage to ResourceType enum across sharing and permissions components for improved type safety

refactor: standardize resourceType usage to ResourceType enum across agent and prompt models, permissions controller, and middleware for enhanced type safety

refactor: update resourceType references from PROMPT_GROUP to PROMPTGROUP for consistency across models, middleware, and components

refactor: standardize access role IDs and resource type usage across agent, file, and prompt models for improved type safety and consistency

chore: add typedefs for TUpdateResourcePermissionsRequest and TUpdateResourcePermissionsResponse to enhance type definitions

chore: move SearchPicker to PeoplePicker dir

refactor: implement debouncing for query changes in SearchPicker for improved performance

chore: fix typing, import order for agent admin settings

fix: agent admin settings, prevent agent form submission

refactor: rename `ACCESS_ROLE_IDS` to `AccessRoleIds`

refactor: replace PermissionBits with PERMISSION_BITS

refactor: replace PERMISSION_BITS with PermissionBits
This commit is contained in:
Danny Avila 2025-07-28 17:52:36 -04:00
parent ae732b2ebc
commit 81b32e400a
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
96 changed files with 781 additions and 798 deletions

View file

@ -4,12 +4,13 @@
const mongoose = require('mongoose');
const { logger } = require('@librechat/data-schemas');
const { ResourceType } = require('librechat-data-provider');
const {
getAvailableRoles,
ensurePrincipalExists,
getEffectivePermissions,
ensureGroupPrincipalExists,
bulkUpdateResourcePermissions,
ensureGroupPrincipalExists,
getEffectivePermissions,
ensurePrincipalExists,
getAvailableRoles,
} = require('~/server/services/PermissionService');
const { AclEntry } = require('~/db/models');
const {
@ -18,8 +19,8 @@ const {
calculateRelevanceScore,
} = require('~/models');
const {
searchEntraIdPrincipals,
entraIdPrincipalFeatureEnabled,
searchEntraIdPrincipals,
} = require('~/server/services/GraphApiService');
/**
@ -27,6 +28,18 @@ const {
* Delegates validation and logic to PermissionService
*/
/**
* Validates that the resourceType is one of the supported enum values
* @param {string} resourceType - The resource type to validate
* @throws {Error} If resourceType is not valid
*/
const validateResourceType = (resourceType) => {
const validTypes = Object.values(ResourceType);
if (!validTypes.includes(resourceType)) {
throw new Error(`Invalid resourceType: ${resourceType}. Valid types: ${validTypes.join(', ')}`);
}
};
/**
* Bulk update permissions for a resource (grant, update, remove)
* @route PUT /api/{resourceType}/{resourceId}/permissions
@ -41,6 +54,8 @@ const {
const updateResourcePermissions = async (req, res) => {
try {
const { resourceType, resourceId } = req.params;
validateResourceType(resourceType);
/** @type {TUpdateResourcePermissionsRequest} */
const { updated, removed, public: isPublic, publicAccessRoleId } = req.body;
const { id: userId } = req.user;
@ -163,6 +178,7 @@ const updateResourcePermissions = async (req, res) => {
const getResourcePermissions = async (req, res) => {
try {
const { resourceType, resourceId } = req.params;
validateResourceType(resourceType);
// Use aggregation pipeline for efficient single-query data retrieval
const results = await AclEntry.aggregate([
@ -278,6 +294,7 @@ const getResourcePermissions = async (req, res) => {
const getResourceRoles = async (req, res) => {
try {
const { resourceType } = req.params;
validateResourceType(resourceType);
const roles = await getAvailableRoles({ resourceType });
@ -305,6 +322,8 @@ const getResourceRoles = async (req, res) => {
const getUserEffectivePermissions = async (req, res) => {
try {
const { resourceType, resourceId } = req.params;
validateResourceType(resourceType);
const { id: userId } = req.user;
const permissionBits = await getEffectivePermissions({

View file

@ -1,30 +1,33 @@
const { z } = require('zod');
const fs = require('fs').promises;
const { nanoid } = require('nanoid');
const { logger, PermissionBits } = require('@librechat/data-schemas');
const { logger } = require('@librechat/data-schemas');
const { agentCreateSchema, agentUpdateSchema } = require('@librechat/api');
const {
Tools,
SystemRoles,
FileSources,
ResourceType,
AccessRoleIds,
EToolResources,
actionDelimiter,
PermissionBits,
removeNullishValues,
} = require('librechat-data-provider');
const {
getAgent,
createAgent,
updateAgent,
deleteAgent,
getListAgentsByAccess,
countPromotedAgents,
revertAgentVersion,
createAgent,
updateAgent,
deleteAgent,
getAgent,
} = require('~/models/Agent');
const {
grantPermission,
findAccessibleResources,
findPubliclyAccessibleResources,
findAccessibleResources,
hasPublicPermission,
grantPermission,
} = require('~/server/services/PermissionService');
const { getStrategyFunctions } = require('~/server/services/Files/strategies');
const { resizeAvatar } = require('~/server/services/Files/images/avatar');
@ -79,9 +82,9 @@ const createAgentHandler = async (req, res) => {
await grantPermission({
principalType: 'user',
principalId: userId,
resourceType: 'agent',
resourceType: ResourceType.AGENT,
resourceId: agent._id,
accessRoleId: 'agent_owner',
accessRoleId: AccessRoleIds.AGENT_OWNER,
grantedBy: userId,
});
logger.debug(
@ -146,7 +149,7 @@ const getAgentHandler = async (req, res, expandProperties = false) => {
// Check if agent is public
const isPublic = await hasPublicPermission({
resourceType: 'agent',
resourceType: ResourceType.AGENT,
resourceId: agent._id,
requiredPermissions: PermissionBits.VIEW,
});
@ -345,9 +348,9 @@ const duplicateAgentHandler = async (req, res) => {
await grantPermission({
principalType: 'user',
principalId: userId,
resourceType: 'agent',
resourceType: ResourceType.AGENT,
resourceId: newAgent._id,
accessRoleId: 'agent_owner',
accessRoleId: AccessRoleIds.AGENT_OWNER,
grantedBy: userId,
});
logger.debug(
@ -440,11 +443,11 @@ const getListAgentsHandler = async (req, res) => {
// Get agent IDs the user has VIEW access to via ACL
const accessibleIds = await findAccessibleResources({
userId,
resourceType: 'agent',
resourceType: ResourceType.AGENT,
requiredPermissions: requiredPermission,
});
const publiclyAccessibleIds = await findPubliclyAccessibleResources({
resourceType: 'agent',
resourceType: ResourceType.AGENT,
requiredPermissions: PermissionBits.VIEW,
});
// Use the new ACL-aware function