JitDbAccess.utils.test.ts152 lines · main
| 1 | import dayjs from 'dayjs' |
| 2 | import { describe, expect, it } from 'vitest' |
| 3 | |
| 4 | import type { JitUserRuleDraft } from './JitDbAccess.types' |
| 5 | import { |
| 6 | computeStatusFromGrants, |
| 7 | createEmptyGrant, |
| 8 | getInvalidIpRangeRows, |
| 9 | getJitMemberOptions, |
| 10 | getRelativeDatetimeByMode, |
| 11 | serializeDraftRolesForGrantMutation, |
| 12 | } from './JitDbAccess.utils' |
| 13 | import type { OrganizationMembersData } from '@/data/organizations/organization-members-query' |
| 14 | |
| 15 | describe('jitDbAccess.utils', () => { |
| 16 | it('returns empty expiry string for never/custom-only fallback modes', () => { |
| 17 | expect(getRelativeDatetimeByMode('never')).toBe('') |
| 18 | expect(getRelativeDatetimeByMode('custom')).toBe('') |
| 19 | }) |
| 20 | |
| 21 | it('creates future datetimes for preset expiry modes', () => { |
| 22 | const inOneHour = dayjs(getRelativeDatetimeByMode('1h')) |
| 23 | expect(inOneHour.isValid()).toBe(true) |
| 24 | expect(inOneHour.isAfter(dayjs())).toBe(true) |
| 25 | }) |
| 26 | |
| 27 | it('computes active and expired status counts including IP counts', () => { |
| 28 | const activeGrant = { |
| 29 | ...createEmptyGrant('role_active'), |
| 30 | enabled: true, |
| 31 | hasExpiry: true, |
| 32 | expiry: dayjs().add(1, 'day').toISOString(), |
| 33 | ipRanges: [{ value: '192.0.2.0/24' }], |
| 34 | } |
| 35 | |
| 36 | const expiredGrant = { |
| 37 | ...createEmptyGrant('role_expired'), |
| 38 | enabled: true, |
| 39 | hasExpiry: true, |
| 40 | expiry: dayjs().subtract(1, 'day').toISOString(), |
| 41 | ipRanges: [{ value: '203.0.113.0/24' }], |
| 42 | } |
| 43 | |
| 44 | const perpetualGrant = { |
| 45 | ...createEmptyGrant('role_never'), |
| 46 | enabled: true, |
| 47 | hasExpiry: false, |
| 48 | expiryMode: 'never' as const, |
| 49 | expiry: '', |
| 50 | } |
| 51 | |
| 52 | expect(computeStatusFromGrants([activeGrant, expiredGrant, perpetualGrant])).toEqual({ |
| 53 | active: 2, |
| 54 | expired: 1, |
| 55 | activeIp: 1, |
| 56 | expiredIp: 1, |
| 57 | }) |
| 58 | }) |
| 59 | |
| 60 | it('returns invalid CIDRs from repeated input rows', () => { |
| 61 | expect( |
| 62 | getInvalidIpRangeRows([ |
| 63 | { value: '192.0.2.0/24' }, |
| 64 | { value: 'not-a-cidr' }, |
| 65 | { value: '10.0.0.1/33' }, |
| 66 | { value: '2001:db8::/64' }, |
| 67 | { value: '2001:db8::/129' }, |
| 68 | ]) |
| 69 | ).toEqual(['not-a-cidr', '10.0.0.1/33', '2001:db8::/129']) |
| 70 | }) |
| 71 | }) |
| 72 | |
| 73 | describe('serializeDraftRolesForGrantMutation', () => { |
| 74 | it('serializes role expiry and IP restrictions for grant mutation payload', () => { |
| 75 | const expiry = '2026-06-01T12:00:00.000Z' |
| 76 | const draft: JitUserRuleDraft = { |
| 77 | memberId: 'user-1', |
| 78 | grants: [ |
| 79 | { |
| 80 | ...createEmptyGrant('postgres'), |
| 81 | enabled: true, |
| 82 | branchesOnly: true, |
| 83 | hasExpiry: true, |
| 84 | expiryMode: 'custom', |
| 85 | expiry, |
| 86 | ipRanges: [{ value: '192.0.2.0/24' }, { value: ' ' }, { value: '2001:db8::/64' }], |
| 87 | }, |
| 88 | { |
| 89 | ...createEmptyGrant('briven_read_only_user'), |
| 90 | enabled: true, |
| 91 | hasExpiry: false, |
| 92 | expiryMode: 'never', |
| 93 | expiry: '', |
| 94 | }, |
| 95 | { |
| 96 | ...createEmptyGrant('ignored_disabled'), |
| 97 | enabled: false, |
| 98 | }, |
| 99 | ], |
| 100 | } |
| 101 | |
| 102 | expect(serializeDraftRolesForGrantMutation(draft)).toEqual([ |
| 103 | { |
| 104 | role: 'postgres', |
| 105 | branches_only: true, |
| 106 | expires_at: dayjs(expiry).unix(), |
| 107 | allowed_networks: { |
| 108 | allowed_cidrs: [{ cidr: '192.0.2.0/24' }], |
| 109 | allowed_cidrs_v6: [{ cidr: '2001:db8::/64' }], |
| 110 | }, |
| 111 | }, |
| 112 | { |
| 113 | role: 'briven_read_only_user', |
| 114 | }, |
| 115 | ]) |
| 116 | }) |
| 117 | }) |
| 118 | |
| 119 | describe('getJitMemberOptions', () => { |
| 120 | it('excludes invited org members without gotrue IDs from selectable options', () => { |
| 121 | const organizationMembers: OrganizationMembersData = [ |
| 122 | { |
| 123 | gotrue_id: 'de305d54-75b4-431b-adb2-eb6b9e546014', |
| 124 | primary_email: 'active@example.com', |
| 125 | username: 'Active User', |
| 126 | is_sso_user: false, |
| 127 | mfa_enabled: false, |
| 128 | metadata: {}, |
| 129 | role_ids: [], |
| 130 | }, |
| 131 | { |
| 132 | gotrue_id: '', |
| 133 | invited_id: 123, |
| 134 | invited_at: '2026-03-01T00:00:00.000Z', |
| 135 | primary_email: 'expired-invite@example.com', |
| 136 | username: 'e', |
| 137 | is_sso_user: false, |
| 138 | mfa_enabled: false, |
| 139 | metadata: {}, |
| 140 | role_ids: [], |
| 141 | }, |
| 142 | ] |
| 143 | |
| 144 | expect(getJitMemberOptions(organizationMembers, [])).toEqual([ |
| 145 | { |
| 146 | id: 'de305d54-75b4-431b-adb2-eb6b9e546014', |
| 147 | email: 'active@example.com', |
| 148 | name: 'Active User', |
| 149 | }, |
| 150 | ]) |
| 151 | }) |
| 152 | }) |