feat: initial public release (MAESTRO)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { buildVisibilityWhere, canUserSeeTask } from './visibility.js';
|
||||
|
||||
function makeUser(overrides: Partial<Express.User> = {}): Express.User {
|
||||
return {
|
||||
id: 'user-1', email: '[email protected]', name: 'u', avatarUrl: null,
|
||||
role: 'user', status: 'active',
|
||||
orgIds: [], defaultVisibility: 'private', defaultVisibilityOrgId: null,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('buildVisibilityWhere', () => {
|
||||
it('admin sees everything (1=1)', () => {
|
||||
const w = buildVisibilityWhere(makeUser({ role: 'admin' }), 'lt');
|
||||
expect(w.clause).toBe('1=1');
|
||||
expect(w.params).toEqual([]);
|
||||
});
|
||||
|
||||
it('user with no orgs: owner or public only', () => {
|
||||
const w = buildVisibilityWhere(makeUser(), 'lt');
|
||||
expect(w.clause).toContain('lt.owner_id = ?');
|
||||
expect(w.clause).toContain("lt.visibility = 'public'");
|
||||
expect(w.clause).toContain('IN (NULL)'); // empty orgs → never matches
|
||||
expect(w.params).toEqual(['user-1']);
|
||||
});
|
||||
|
||||
it('user with orgs: owner or public or same-org', () => {
|
||||
const w = buildVisibilityWhere(makeUser({ orgIds: ['10', '20'] }), 'lt');
|
||||
expect(w.clause).toMatch(/lt\.visibility_scope_org_id IN \(\?,\?\)/);
|
||||
expect(w.params).toEqual(['user-1', '10', '20']);
|
||||
});
|
||||
|
||||
it('respects custom table alias', () => {
|
||||
const w = buildVisibilityWhere(makeUser(), 'j');
|
||||
expect(w.clause).toContain('j.owner_id');
|
||||
expect(w.clause).not.toContain('lt.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('canUserSeeTask', () => {
|
||||
const adminUser = makeUser({ role: 'admin' });
|
||||
const aliceNoOrg = makeUser({ id: 'alice' });
|
||||
const bobOrg10 = makeUser({ id: 'bob', orgIds: ['10'] });
|
||||
|
||||
it('admin sees private tasks of others', () => {
|
||||
const t = { ownerId: 'someone-else', visibility: 'private' as const, visibilityScopeOrgId: null };
|
||||
expect(canUserSeeTask(adminUser, t)).toBe(true);
|
||||
});
|
||||
|
||||
it('owner sees own private task', () => {
|
||||
const t = { ownerId: 'alice', visibility: 'private' as const, visibilityScopeOrgId: null };
|
||||
expect(canUserSeeTask(aliceNoOrg, t)).toBe(true);
|
||||
});
|
||||
|
||||
it('non-owner cannot see another user\'s private task', () => {
|
||||
const t = { ownerId: 'someone-else', visibility: 'private' as const, visibilityScopeOrgId: null };
|
||||
expect(canUserSeeTask(aliceNoOrg, t)).toBe(false);
|
||||
});
|
||||
|
||||
it('public task is visible to anyone', () => {
|
||||
const t = { ownerId: 'someone-else', visibility: 'public' as const, visibilityScopeOrgId: null };
|
||||
expect(canUserSeeTask(aliceNoOrg, t)).toBe(true);
|
||||
});
|
||||
|
||||
it('org task: same org member can see', () => {
|
||||
const t = { ownerId: 'someone-else', visibility: 'org' as const, visibilityScopeOrgId: '10' };
|
||||
expect(canUserSeeTask(bobOrg10, t)).toBe(true);
|
||||
});
|
||||
|
||||
it('org task: different org member cannot see', () => {
|
||||
const t = { ownerId: 'someone-else', visibility: 'org' as const, visibilityScopeOrgId: '99' };
|
||||
expect(canUserSeeTask(bobOrg10, t)).toBe(false);
|
||||
});
|
||||
|
||||
it('org task with null scope: only owner can see', () => {
|
||||
const t = { ownerId: 'alice', visibility: 'org' as const, visibilityScopeOrgId: null };
|
||||
expect(canUserSeeTask(aliceNoOrg, t)).toBe(true);
|
||||
expect(canUserSeeTask(bobOrg10, t)).toBe(false);
|
||||
});
|
||||
|
||||
it('owner with null ownerId: not matched (null !== null check skipped)', () => {
|
||||
const t = { ownerId: null, visibility: 'private' as const, visibilityScopeOrgId: null };
|
||||
expect(canUserSeeTask(aliceNoOrg, t)).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user