Skip to content

Commit fdb5493

Browse files
tech-story - [UIE-9306]: Improve user seeding (follow up) (#12978)
* distinctive seeding * handle dupe records * Update packages/manager/src/mocks/presets/crud/seeds/utils.ts Co-authored-by: Copilot <[email protected]> * lint --------- Co-authored-by: Copilot <[email protected]>
1 parent daa0ebd commit fdb5493

File tree

4 files changed

+140
-24
lines changed

4 files changed

+140
-24
lines changed

packages/manager/src/mocks/presets/crud/seeds/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ipAddressSeeder } from './networking';
77
import { nodeBalancerSeeder } from './nodebalancers';
88
import { placementGroupSeeder } from './placementGroups';
99
import { supportTicketsSeeder } from './supportTickets';
10-
import { usersSeeder } from './users';
10+
import { defaultUsersSeeder, parentUsersSeeder } from './users';
1111
import { volumesSeeder } from './volumes';
1212
import { vpcSeeder } from './vpcs';
1313

@@ -21,7 +21,8 @@ export const dbSeeders = [
2121
nodeBalancerSeeder,
2222
placementGroupSeeder,
2323
supportTicketsSeeder,
24-
usersSeeder,
24+
defaultUsersSeeder,
25+
parentUsersSeeder,
2526
volumesSeeder,
2627
vpcSeeder,
2728
];

packages/manager/src/mocks/presets/crud/seeds/users.ts

Lines changed: 133 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { getProfile } from '@linode/api-v4';
21
import { childAccountFactory } from '@linode/utilities';
32

43
import { getSeedsCountMap } from 'src/dev-tools/utils';
@@ -17,26 +16,108 @@ import type {
1716
UserRolesEntry,
1817
} from 'src/mocks/types';
1918

20-
export const usersSeeder: MockSeeder = {
19+
export const defaultUsersSeeder: MockSeeder = {
2120
canUpdateCount: true,
2221
desc: 'Users Seeds with Permissions',
2322
group: { id: 'Users' },
24-
id: 'users:crud',
25-
label: 'Users',
23+
id: 'users(default):crud',
24+
label: 'Default Users',
2625

2726
seeder: async (mockState: MockState) => {
2827
const seedsCountMap = getSeedsCountMap();
29-
const count = seedsCountMap[usersSeeder.id] ?? 0;
30-
const profile = await getProfile();
28+
const count = seedsCountMap[defaultUsersSeeder.id] ?? 0;
3129

3230
const userSeeds = seedWithUniqueIds<'users'>({
3331
dbEntities: await mswDB.getAll('users'),
3432
seedEntities: accountUserFactory.buildList(count, {
35-
user_type: profile?.user_type,
36-
restricted: profile?.restricted,
33+
user_type: 'default',
34+
restricted: true,
3735
}),
3836
});
3937

38+
const userRolesEntries: UserRolesEntry[] = [];
39+
const userAccountPermissionsEntries: UserAccountPermissionsEntry[] = [];
40+
const userEntityPermissionsEntries: UserEntityPermissionsEntry[] = [];
41+
42+
userSeeds.forEach((user) => {
43+
const userRoles = userDefaultRolesFactory.build();
44+
userRolesEntries.push({
45+
username: user.username,
46+
roles: userRoles,
47+
});
48+
49+
if (userRoles.account_access) {
50+
userAccountPermissionsEntries.push({
51+
username: user.username,
52+
permissions: userRoles.account_access,
53+
});
54+
}
55+
56+
if (userRoles.entity_access) {
57+
for (const entityAccess of userRoles.entity_access) {
58+
userEntityPermissionsEntries.push({
59+
username: user.username,
60+
entityType: entityAccess.type,
61+
entityId: entityAccess.id,
62+
permissions: entityAccess.roles,
63+
});
64+
}
65+
}
66+
});
67+
68+
const updatedMockState = {
69+
...mockState,
70+
users: (mockState.users ?? []).concat(userSeeds),
71+
userRoles: (mockState.userRoles ?? []).concat(userRolesEntries),
72+
userAccountPermissions: (mockState.userAccountPermissions ?? []).concat(
73+
userAccountPermissionsEntries
74+
),
75+
userEntityPermissions: (mockState.userEntityPermissions ?? []).concat(
76+
userEntityPermissionsEntries
77+
),
78+
};
79+
80+
await mswDB.saveStore(updatedMockState, 'seedState');
81+
82+
return updatedMockState;
83+
},
84+
};
85+
86+
/**
87+
* This way, when you seed 10 parent users, you'll get:
88+
* 10 parent users
89+
* 30 child accounts (3 per parent)
90+
* 60 child users (2 per child account)
91+
* 10 delegate users (1 per parent)
92+
* All the proper relationships and permissions
93+
*/
94+
export const parentUsersSeeder: MockSeeder = {
95+
canUpdateCount: true,
96+
desc: 'Parent Users (with child accounts and delegations)',
97+
group: { id: 'Users' },
98+
id: 'users(parent):crud',
99+
label: 'Parent Users (with child accounts and delegations)',
100+
101+
seeder: async (mockState: MockState) => {
102+
const seedsCountMap = getSeedsCountMap();
103+
const count = seedsCountMap[parentUsersSeeder.id] ?? 0;
104+
105+
const existingUsers = await mswDB.getAll('users');
106+
const existingUsernames = existingUsers?.map((u) => u.username) || [];
107+
108+
// Only create users that don't already exist
109+
const newUsers = accountUserFactory
110+
.buildList(count, {
111+
user_type: 'parent',
112+
restricted: false,
113+
})
114+
.filter((user) => !existingUsernames.includes(user.username));
115+
116+
const userSeeds = seedWithUniqueIds<'users'>({
117+
dbEntities: existingUsers,
118+
seedEntities: newUsers,
119+
});
120+
40121
const userRolesEntries: UserRolesEntry[] = [];
41122
const userAccountPermissionsEntries: UserAccountPermissionsEntry[] = [];
42123
const userEntityPermissionsEntries: UserEntityPermissionsEntry[] = [];
@@ -69,26 +150,56 @@ export const usersSeeder: MockSeeder = {
69150
}
70151

71152
// Create child accounts and delegations for parent users
72-
if (user.user_type === 'parent') {
73-
const delegateUser = accountUserFactory.build({
74-
username: `${user.username}_delegate`,
75-
user_type: 'delegate',
76-
email: `${user.username}[email protected]`,
77-
restricted: false,
153+
const childAccounts = childAccountFactory.buildList(3);
154+
for (const childAccount of childAccounts) {
155+
childAccountsToAdd.push(childAccount);
156+
delegationsToAdd.push({
157+
username: user.username,
158+
childAccountEuuid: childAccount.euuid,
159+
id: Math.floor(Math.random() * 1000000),
78160
});
79-
userSeeds.push(delegateUser);
80161

81-
const childAccounts = childAccountFactory.buildList(3);
162+
// Create child users for each child account
163+
const childUsers = accountUserFactory
164+
.buildList(2, {
165+
user_type: 'child',
166+
restricted: true,
167+
})
168+
.map((user, index) => ({
169+
...user,
170+
username: `child-user-${childAccount.euuid}-${index}`,
171+
email: `child-user-${childAccount.euuid}-${index}@example.com`,
172+
}));
82173

83-
for (const childAccount of childAccounts) {
84-
childAccountsToAdd.push(childAccount);
85-
delegationsToAdd.push({
86-
username: user.username,
87-
childAccountEuuid: childAccount.euuid,
88-
id: Math.floor(Math.random() * 1000000),
174+
for (const childUser of childUsers) {
175+
userSeeds.push(childUser);
176+
177+
// Add roles for child users
178+
const childUserRoles = userDefaultRolesFactory.build();
179+
userRolesEntries.push({
180+
username: childUser.username,
181+
roles: childUserRoles,
89182
});
183+
184+
// Add permissions if needed
185+
if (childUserRoles.account_access) {
186+
userAccountPermissionsEntries.push({
187+
username: childUser.username,
188+
permissions: childUserRoles.account_access,
189+
});
190+
}
90191
}
91192
}
193+
194+
// Create delegate users for each parent user
195+
const delegateUsers = accountUserFactory.build({
196+
user_type: 'delegate',
197+
username: `delegateuser-${user.username}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 1000000)}`,
198+
email: `${user.username}[email protected]`,
199+
restricted: false,
200+
});
201+
202+
userSeeds.push(delegateUsers);
92203
});
93204

94205
const updatedMockState = {

packages/manager/src/mocks/presets/crud/seeds/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export const removeSeeds = async (seederId: MockSeeder['id']) => {
4242
case 'support-tickets:crud':
4343
await mswDB.deleteAll('supportTickets', mockState, 'seedState');
4444
break;
45+
case 'users(default):crud':
46+
case 'users(parent):crud':
4547
case 'users:crud':
4648
await mswDB.deleteAll('users', mockState, 'seedState');
4749
await mswDB.deleteAll('userRoles', mockState, 'seedState');

packages/manager/src/mocks/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ export type MockPresetCrudId =
162162
| 'placement-groups:crud'
163163
| 'quotas:crud'
164164
| 'support-tickets:crud'
165+
| 'users(default):crud'
166+
| 'users(parent):crud'
165167
| 'users:crud'
166168
| 'volumes:crud'
167169
| 'vpcs:crud';

0 commit comments

Comments
 (0)