Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions .github/workflows/config-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Config Migration Tests
on:
pull_request:
paths:
- 'config/**'
- 'api/models/**'
- 'api/db/**'
- 'packages/data-schemas/src/**'
- 'packages/data-provider/src/**'
- 'packages/api/src/acl/**'
- 'packages/api/src/shared-links/**'

env:
NODE_ENV: CI
NODE_OPTIONS: '--max-old-space-size=${{ secrets.NODE_MAX_OLD_SPACE_SIZE || 6144 }}'

jobs:
test-config:
name: 'Tests: config migrations'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

- name: Use Node.js 20.19
uses: actions/setup-node@v4
with:
node-version: '20.19'

- name: Restore node_modules cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: |
node_modules
api/node_modules
packages/api/node_modules
packages/data-provider/node_modules
packages/data-schemas/node_modules
key: node-modules-backend-${{ runner.os }}-20.19-${{ hashFiles('package-lock.json') }}

- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci

- name: Restore data-provider build cache
id: cache-data-provider
uses: actions/cache@v4
with:
path: packages/data-provider/dist
key: build-data-provider-${{ runner.os }}-${{ hashFiles('packages/data-provider/src/**', 'packages/data-provider/tsconfig*.json', 'packages/data-provider/rollup.config.js', 'packages/data-provider/package.json') }}

- name: Build data-provider
if: steps.cache-data-provider.outputs.cache-hit != 'true'
run: npm run build:data-provider

- name: Restore data-schemas build cache
id: cache-data-schemas
uses: actions/cache@v4
with:
path: packages/data-schemas/dist
key: build-data-schemas-${{ runner.os }}-${{ hashFiles('packages/data-schemas/src/**', 'packages/data-schemas/tsconfig*.json', 'packages/data-schemas/rollup.config.js', 'packages/data-schemas/package.json', 'packages/data-provider/src/**', 'packages/data-provider/tsconfig*.json', 'packages/data-provider/rollup.config.js', 'packages/data-provider/package.json') }}

- name: Build data-schemas
if: steps.cache-data-schemas.outputs.cache-hit != 'true'
run: npm run build:data-schemas

- name: Restore api build cache
id: cache-api
uses: actions/cache@v4
with:
path: packages/api/dist
key: build-api-${{ runner.os }}-${{ hashFiles('packages/api/src/**', 'packages/api/tsconfig*.json', 'packages/api/server-rollup.config.js', 'packages/api/package.json', 'packages/data-provider/src/**', 'packages/data-provider/tsconfig*.json', 'packages/data-provider/rollup.config.js', 'packages/data-provider/package.json', 'packages/data-schemas/src/**', 'packages/data-schemas/tsconfig*.json', 'packages/data-schemas/rollup.config.js', 'packages/data-schemas/package.json') }}

- name: Build api
if: steps.cache-api.outputs.cache-hit != 'true'
run: npm run build:api

- name: Create empty auth.json file
run: |
mkdir -p api/data
echo '{}' > api/data/auth.json

- name: Prepare .env.test file
run: cp api/test/.env.test.example api/test/.env.test

- name: Run config migration tests
run: npm run test:config
6 changes: 3 additions & 3 deletions api/server/controllers/PermissionsController.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ const updateResourcePermissions = async (req, res) => {
revokedPrincipals.push(...removed);
}

// If public is disabled, add public to revoked list
if (!isPublic) {
// If public is explicitly disabled, add public to revoked list
if (isPublic === false) {
revokedPrincipals.push({
type: PrincipalType.PUBLIC,
id: null,
Expand Down Expand Up @@ -167,7 +167,7 @@ const updateResourcePermissions = async (req, res) => {
message: 'Permissions updated successfully',
results: {
principals: results.granted,
public: isPublic || false,
...(isPublic !== undefined ? { public: isPublic } : {}),
publicAccessRoleId: isPublic ? publicAccessRoleId : undefined,
},
};
Expand Down
3 changes: 2 additions & 1 deletion api/server/controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const {
MCPTokenStorage,
normalizeHttpError,
extractWebSearchEnvVars,
deleteAllSharedLinksWithCleanup,
} = require('@librechat/api');
const {
Tools,
Expand Down Expand Up @@ -359,7 +360,7 @@ const deleteUserController = async (req, res) => {
}
await deleteUserPluginAuth(user.id, null, true);
await db.deleteUserById(user.id);
await db.deleteAllSharedLinks(user.id);
await deleteAllSharedLinksWithCleanup(user.id);
await deleteUserFiles(req);
await db.deleteFiles(null, user.id);
await db.deleteToolCalls(user.id);
Expand Down
3 changes: 3 additions & 0 deletions api/server/controllers/__tests__/deleteUser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const mockDeleteMessages = jest.fn();
const mockDeleteAllUserSessions = jest.fn();
const mockDeleteUserById = jest.fn();
const mockDeleteAllSharedLinks = jest.fn();
const mockDeleteAllSharedLinksWithCleanup = jest.fn();
const mockDeletePresets = jest.fn();
const mockDeleteUserKey = jest.fn();
const mockDeleteConvos = jest.fn();
Expand Down Expand Up @@ -38,6 +39,7 @@ jest.mock('@librechat/api', () => ({
extractWebSearchEnvVars: jest.fn(),
needsRefresh: jest.fn(),
getNewS3URL: jest.fn(),
deleteAllSharedLinksWithCleanup: (...args) => mockDeleteAllSharedLinksWithCleanup(...args),
}));

jest.mock('~/models', () => ({
Expand Down Expand Up @@ -126,6 +128,7 @@ function stubDeletionMocks() {
mockDeleteUserPluginAuth.mockResolvedValue();
mockDeleteUserById.mockResolvedValue();
mockDeleteAllSharedLinks.mockResolvedValue();
mockDeleteAllSharedLinksWithCleanup.mockResolvedValue({ deletedCount: 0 });
mockGetFiles.mockResolvedValue([]);
mockProcessDeleteRequest.mockResolvedValue({ deletedFileIds: [], failedFileIds: [] });
mockDeleteFiles.mockResolvedValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const HANDLED_RESOURCE_TYPES = {
[ResourceType.PROMPTGROUP]: 'deleteUserPrompts',
[ResourceType.MCPSERVER]: 'deleteUserMcpServers',
[ResourceType.SKILL]: 'deleteUserSkills',
[ResourceType.SHARED_LINK]: 'deleteAllSharedLinksWithCleanup',
};

/**
Expand Down
1 change: 1 addition & 0 deletions api/server/controllers/agents/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ class AgentClient extends BaseClient {
{
spec: this.options.spec,
iconURL: this.options.iconURL,
chatProjectId: this.options.chatProjectId,
endpoint: this.options.endpoint,
agent_id: this.options.agent.id,
modelLabel: this.options.modelLabel,
Expand Down
1 change: 1 addition & 0 deletions api/server/experimental.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ if (cluster.isMaster) {
app.use('/api/messages', routes.messages);
app.use('/api/convos', routes.convos);
app.use('/api/presets', routes.presets);
app.use('/api/projects', routes.projects);
app.use('/api/prompts', routes.prompts);
app.use('/api/skills', routes.skills);
app.use('/api/categories', routes.categories);
Expand Down
1 change: 1 addition & 0 deletions api/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ const startServer = async () => {
app.use('/api/messages', routes.messages);
app.use('/api/convos', routes.convos);
app.use('/api/presets', routes.presets);
app.use('/api/projects', routes.projects);
app.use('/api/prompts', routes.prompts);
app.use('/api/skills', routes.skills);
app.use('/api/categories', routes.categories);
Expand Down
Loading
Loading