Skip to content

[permission] Override query builders db-executing methods #11714

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Apr 24, 2025

Conversation

ijreilly
Copy link
Collaborator

@ijreilly ijreilly commented Apr 24, 2025

ijreilly added 30 commits April 7, 2025 11:02

import { WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder';

export class WorkspaceQueryBuilder<
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we actually don't need this: we use a SelectQueryBuilder in the initial createQueryBuilder method in workspace.repository

@ijreilly ijreilly marked this pull request as ready for review April 24, 2025 11:57
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

This PR implements a comprehensive permission system overhaul for database operations in the Twenty server, replacing the single WorkspaceQueryBuilder with specialized query builders for different operations.

  • Added new specialized query builders (WorkspaceInsertQueryBuilder, WorkspaceDeleteQueryBuilder, WorkspaceSoftDeleteQueryBuilder) with proper permission validation
  • Implemented permission checks in execute() methods across all query builders using validateQueryIsPermittedOrThrow
  • Added support for permissions V2 feature flag with backward compatibility
  • Added extensive integration tests covering permission scenarios for guest roles, admin roles, and API keys
  • Note: PR description appears to be incorrect as it references mobile display improvements but changes are about permission handling

17 file(s) reviewed, 14 comment(s)
Edit PR Review Bot Settings | Greptile

Comment on lines +88 to +96
afterAll(async () => {
const disablePermissionsQuery = updateFeatureFlagFactory(
SEED_APPLE_WORKSPACE_ID,
'IsPermissionsV2Enabled',
false,
);

expect(response.body.data).toStrictEqual({ deletePerson: null });
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toBe(
PermissionsExceptionMessage.PERMISSION_DENIED,
);
expect(response.body.errors[0].extensions.code).toBe(ErrorCode.FORBIDDEN);
});
await makeGraphqlAPIRequest(disablePermissionsQuery);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: ensure feature flag is disabled even if test fails by using try/finally

});

it('should throw a permission error when user does not have permission (guest role)', async () => {
const personId = randomUUID();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: personId is redefined here but never used in the test - the recordId in the operation could use the outer personId

Comment on lines +44 to +46
id: {
in: [randomUUID(), randomUUID()],
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Using random UUIDs in the filter when testing permission denial could mask actual permission issues. Consider using the same personId1/personId2 that were created to ensure the test is checking permissions and not just failing because records don't exist.

Suggested change
id: {
in: [randomUUID(), randomUUID()],
},
id: {
in: [personId1, personId2],
},

Comment on lines +90 to +108
beforeAll(async () => {
const enablePermissionsQuery = updateFeatureFlagFactory(
SEED_APPLE_WORKSPACE_ID,
'IsPermissionsV2Enabled',
true,
);

await makeGraphqlAPIRequest(enablePermissionsQuery);
});

afterAll(async () => {
const disablePermissionsQuery = updateFeatureFlagFactory(
SEED_APPLE_WORKSPACE_ID,
'IsPermissionsV2Enabled',
false,
);

await makeGraphqlAPIRequest(disablePermissionsQuery);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Feature flag state changes in beforeAll/afterAll could affect other test suites running in parallel. Consider using a unique workspace ID for these tests.

Comment on lines +143 to +151
afterAll(async () => {
const disablePermissionsQuery = updateFeatureFlagFactory(
SEED_APPLE_WORKSPACE_ID,
'IsPermissionsV2Enabled',
false,
);

expect(response.body.data).toStrictEqual({ restorePeople: null });
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toBe(
PermissionsExceptionMessage.PERMISSION_DENIED,
);
expect(response.body.errors[0].extensions.code).toBe(ErrorCode.FORBIDDEN);
});
await makeGraphqlAPIRequest(disablePermissionsQuery);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Ensure feature flag is properly reset even if tests fail by using try/finally

Suggested change
afterAll(async () => {
const disablePermissionsQuery = updateFeatureFlagFactory(
SEED_APPLE_WORKSPACE_ID,
'IsPermissionsV2Enabled',
false,
);
expect(response.body.data).toStrictEqual({ restorePeople: null });
expect(response.body.errors).toBeDefined();
expect(response.body.errors[0].message).toBe(
PermissionsExceptionMessage.PERMISSION_DENIED,
);
expect(response.body.errors[0].extensions.code).toBe(ErrorCode.FORBIDDEN);
});
await makeGraphqlAPIRequest(disablePermissionsQuery);
});
afterAll(async () => {
try {
const disablePermissionsQuery = updateFeatureFlagFactory(
SEED_APPLE_WORKSPACE_ID,
'IsPermissionsV2Enabled',
false,
);
await makeGraphqlAPIRequest(disablePermissionsQuery);
} catch (error) {
console.error('Failed to reset permissions feature flag:', error);
throw error;
}
});

Copy link
Member

@Weiko Weiko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👏

@ijreilly ijreilly merged commit e750ef2 into main Apr 24, 2025
36 checks passed
@ijreilly ijreilly deleted the perm--query-builders branch April 24, 2025 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Override all db-calling methods on query builders
2 participants