additional types fixes

This commit is contained in:
Nate Kelley 2025-07-10 10:14:16 -06:00
parent a7aea69277
commit b28f6e1e35
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
10 changed files with 70 additions and 41 deletions

View File

@ -95,7 +95,7 @@ describe('getApprovedDomainsHandler (integration)', () => {
let userWithoutOrg;
try {
userWithoutOrg = await createUserWithoutOrganization();
await expect(getApprovedDomainsHandler(userWithoutOrg)).rejects.toThrow(HTTPException);
await expect(getApprovedDomainsHandler(userWithoutOrg)).rejects.toMatchObject({
status: 403,

View File

@ -111,12 +111,12 @@ describe('getWorkspaceSettingsHandler (integration)', () => {
describe('Error Cases', () => {
it('should return 403 for user without organization', async () => {
const userWithoutOrg = await createUserWithoutOrganization();
await expect(getWorkspaceSettingsHandler(userWithoutOrg)).rejects.toMatchObject({
status: 403,
message: 'User is not associated with an organization',
});
await cleanupTestUser(userWithoutOrg.id);
});

View File

@ -137,7 +137,9 @@ describe('removeApprovedDomainsHandler (integration)', () => {
const userWithoutOrg = await createUserWithoutOrganization();
const request = { domains: ['remove1.com'] };
await expect(removeApprovedDomainsHandler(request, userWithoutOrg)).rejects.toThrow(HTTPException);
await expect(removeApprovedDomainsHandler(request, userWithoutOrg)).rejects.toThrow(
HTTPException
);
await expect(removeApprovedDomainsHandler(request, userWithoutOrg)).rejects.toMatchObject({
status: 403,
message: 'User is not associated with an organization',

View File

@ -123,19 +123,15 @@ describe('security-utils', () => {
it('should reject other roles', () => {
const roles = ['member', 'viewer', 'user', 'guest'];
roles.forEach((role) => {
for (const role of roles) {
expect(() => checkAdminPermissions(role)).toThrow(HTTPException);
expect(() => checkAdminPermissions(role)).toThrow(
'Insufficient admin permissions'
);
});
expect(() => checkAdminPermissions(role)).toThrow('Insufficient admin permissions');
}
});
it('should reject null role', () => {
expect(() => checkAdminPermissions(null)).toThrow(HTTPException);
expect(() => checkAdminPermissions(null)).toThrow(
'Insufficient admin permissions'
);
expect(() => checkAdminPermissions(null)).toThrow('Insufficient admin permissions');
});
it('should reject undefined role', () => {
@ -158,12 +154,12 @@ describe('security-utils', () => {
it('should reject other roles', () => {
const roles = ['admin', 'member', 'viewer', 'user'];
roles.forEach((role) => {
for (const role of roles) {
expect(() => checkWorkspaceAdminPermission(role)).toThrow(HTTPException);
expect(() => checkWorkspaceAdminPermission(role)).toThrow(
'Only workspace admins can update workspace settings'
);
});
}
});
it('should reject null role', () => {
@ -552,7 +548,7 @@ describe('security-utils', () => {
// Should soft-delete all existing first, then batch upsert
expect(mockTx.update).toHaveBeenCalledTimes(1); // 1 for soft-delete all
expect(mockTx.insert).toHaveBeenCalledTimes(1); // 1 batch upsert for both datasets
// Verify the insert was called with values
expect(mockTx.insert).toHaveBeenCalled();
const insertMock = vi.mocked(mockTx.insert);

View File

@ -29,11 +29,13 @@ export async function createTestUserInDb(userData: Partial<User> = {}): Promise<
// Try to clean up any partial user data
await db.delete(usersToOrganizations).where(eq(usersToOrganizations.userId, id));
// Re-throw to let the test handle it
throw new Error(`Failed to create test user: Database trigger tried to add user to non-existent organization. ${error.message}`);
throw new Error(
`Failed to create test user: Database trigger tried to add user to non-existent organization. ${error.message}`
);
}
throw error;
}
return user as User;
}
@ -68,13 +70,8 @@ export async function createTestOrgMemberInDb(
const existing = await db
.select()
.from(usersToOrganizations)
.where(
and(
eq(usersToOrganizations.userId, userId),
isNull(usersToOrganizations.deletedAt)
)
);
.where(and(eq(usersToOrganizations.userId, userId), isNull(usersToOrganizations.deletedAt)));
if (existing.length > 0) {
// Delete existing memberships silently
await db.delete(usersToOrganizations).where(eq(usersToOrganizations.userId, userId));
@ -92,7 +89,7 @@ export async function createTestOrgMemberInDb(
};
await db.insert(usersToOrganizations).values(member);
// Verify the membership was created
const verification = await db
.select()
@ -105,11 +102,11 @@ export async function createTestOrgMemberInDb(
)
)
.limit(1);
if (!verification.length) {
throw new Error('Failed to create test organization membership');
}
if (verification[0].role !== role) {
throw new Error(`Role mismatch: expected ${role}, got ${verification[0].role}`);
}
@ -126,7 +123,7 @@ export async function cleanupTestUser(userId: string): Promise<void> {
export async function cleanupTestOrganization(orgId: string): Promise<void> {
// Import the necessary tables for cleanup
const { permissionGroups, datasetsToPermissionGroups } = await import('@buster/database');
// Delete dataset associations for default permission group
const defaultPermissionGroupName = `default:${orgId}`;
const pgResult = await db
@ -134,15 +131,16 @@ export async function cleanupTestOrganization(orgId: string): Promise<void> {
.from(permissionGroups)
.where(eq(permissionGroups.name, defaultPermissionGroupName))
.limit(1);
if (pgResult[0]) {
await db.delete(datasetsToPermissionGroups)
await db
.delete(datasetsToPermissionGroups)
.where(eq(datasetsToPermissionGroups.permissionGroupId, pgResult[0].id));
}
// Delete permission groups
await db.delete(permissionGroups).where(eq(permissionGroups.organizationId, orgId));
// Delete organization memberships
await db.delete(usersToOrganizations).where(eq(usersToOrganizations.organizationId, orgId));
@ -161,7 +159,10 @@ export async function getOrganizationFromDb(orgId: string): Promise<Organization
}
// Helper to verify user organization membership
export async function verifyUserOrgMembership(userId: string, organizationId: string): Promise<{
export async function verifyUserOrgMembership(
userId: string,
organizationId: string
): Promise<{
organizationId: string;
role: string;
} | null> {
@ -186,9 +187,9 @@ export async function verifyUserOrgMembership(userId: string, organizationId: st
// Helper to create a user without any organization
export async function createUserWithoutOrganization(): Promise<User> {
const user = await createTestUserInDb();
// Remove any auto-created organization memberships
await db.delete(usersToOrganizations).where(eq(usersToOrganizations.userId, user.id));
return user;
}

View File

@ -37,7 +37,7 @@ describe('updateWorkspaceSettingsHandler (integration)', () => {
describe('Happy Path', () => {
it('should update all settings fields', async () => {
await createTestOrgMemberInDb(testUser.id, testOrg.id, 'workspace_admin');
// Verify membership was created properly
const membership = await verifyUserOrgMembership(testUser.id, testOrg.id);
expect(membership).toBeTruthy();
@ -130,7 +130,7 @@ describe('updateWorkspaceSettingsHandler (integration)', () => {
restrictNewUserInvitations: false,
defaultRole: 'querier',
});
const roleUser = await createTestUserInDb();
await createTestOrgMemberInDb(roleUser.id, roleTestOrg.id, role);
@ -171,7 +171,7 @@ describe('updateWorkspaceSettingsHandler (integration)', () => {
it('should return 403 for user without organization', async () => {
const isolatedUser = await createUserWithoutOrganization();
const request = { restrict_new_user_invitations: true };
await expect(updateWorkspaceSettingsHandler(request, isolatedUser)).rejects.toThrow(
@ -181,7 +181,7 @@ describe('updateWorkspaceSettingsHandler (integration)', () => {
status: 403,
message: 'User is not associated with an organization',
});
// Clean up
await cleanupTestUser(isolatedUser.id);
});

View File

@ -47,7 +47,14 @@ describe('WorkspaceSettingsService', () => {
});
it('should handle all string values correctly', () => {
const roles = ['workspace_admin', 'data_admin', 'querier', 'restricted_querier', 'viewer', 'none'];
const roles = [
'workspace_admin',
'data_admin',
'querier',
'restricted_querier',
'viewer',
'none',
];
roles.forEach((role) => {
const settings = {

View File

@ -0,0 +1,16 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"extends": ["../../biome.json"],
"overrides": [
{
"include": ["**/*.ts"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off"
}
}
}
}
]
}

View File

@ -2,5 +2,8 @@
"name": "@buster/supabase",
"version": "0.0.1",
"private": false,
"scripts": {}
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check . --write"
}
}

View File

@ -0,0 +1,4 @@
{
"extends": "../typescript-config/base.json",
"include": ["volumes/**/*"]
}