Skip to content

Commit 30770c9

Browse files
ShadeWyrmcraigzour
andauthored
* fix: Pull user Features from DB/Cache call instead of Cache only on User Feature Management (#5741)
* * fix user feature management to not read from cache only - instead pull from DB if cached value doesn't exist. * * remove unused code. * * fix update flags from set to createMany. * * Add auth checks, remove unused solo add function. * Update lib/cache/userFeatureFlagsCache.ts Co-authored-by: Clément JANIN <clement.janin@cds-snc.ca> * * Remove priv check on cache - it fails on putting users perms into cache when loading. * * swap set to delete for remove flag. --------- Co-authored-by: Clément JANIN <clement.janin@cds-snc.ca>
1 parent 3a3ba5d commit 30770c9

File tree

3 files changed

+17
-69
lines changed

3 files changed

+17
-69
lines changed

app/(gcforms)/[locale]/(app administration)/admin/(with nav)/accounts/[id]/manage-user-features/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getUser } from "@lib/users";
55
import { UserFeaturesList } from "./components/server/UserFeaturesList";
66
import { AddUserFeatureModal } from "./components/client/AddUserFeatureModal";
77
import { checkAll } from "@lib/cache/flags";
8-
import { featureFlagsCheck } from "@lib/cache/userFeatureFlagsCache";
8+
import { getUserFeatureFlags } from "@lib/userFeatureFlags";
99

1010
export default AuthenticatedPage<{ id: string }>(
1111
[authorization.canViewAllUsers, authorization.canAccessFlags],
@@ -17,7 +17,7 @@ export default AuthenticatedPage<{ id: string }>(
1717
const formUser = await getUser(id);
1818

1919
const flags = await checkAll();
20-
const userFlags = await featureFlagsCheck(formUser.id);
20+
const userFlags = await getUserFeatureFlags(formUser.id);
2121

2222
return (
2323
<div>

lib/cache/userFeatureFlagsCache.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { logMessage } from "@lib/logger";
22
import { getRedisInstance } from "../integration/redisConnector";
3-
import { removeUserFeatureFlag, addUserFeatureFlag } from "@lib/userFeatureFlags";
43

54
// If NODE_ENV is in test mode (Jest Tests) do not use the cache
65
const cacheAvailable: boolean = process.env.APP_ENV !== "test" && Boolean(process.env.REDIS_URL);
@@ -68,29 +67,3 @@ export const featureFlagsGetAll = async (): Promise<{ userID: string; flag: stri
6867
throw new Error("Could not connect to cache");
6968
}
7069
};
71-
72-
// Remove a feature flag for a user (hit the DB and then update the cache)
73-
export const featureFlagsRemove = async (userID: string, flag: string): Promise<void> => {
74-
if (!cacheAvailable) return;
75-
76-
try {
77-
await removeUserFeatureFlag(userID, flag);
78-
await featureFlagsPut(userID, (await featureFlagsCheck(userID)) || []);
79-
} catch (e) {
80-
logMessage.error(e as Error);
81-
throw new Error("Could not update feature flags in cache");
82-
}
83-
};
84-
85-
// Add a feature flag for a user (hit the DB and then update the cache)
86-
export const featureFlagsAdd = async (userID: string, flag: string): Promise<void> => {
87-
if (!cacheAvailable) return;
88-
89-
try {
90-
await addUserFeatureFlag(userID, flag);
91-
await featureFlagsPut(userID, (await featureFlagsCheck(userID)) || []);
92-
} catch (e) {
93-
logMessage.error(e as Error);
94-
throw new Error("Could not update feature flags in cache");
95-
}
96-
};

lib/userFeatureFlags.ts

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { authorization } from "@lib/privileges";
12
import { prisma } from "@lib/integration/prismaConnector";
23
import { featureFlagsCheck, featureFlagsPut } from "@lib/cache/userFeatureFlagsCache";
34

@@ -33,6 +34,9 @@ export const getUserFeatureFlags = async (userId: string): Promise<string[]> =>
3334

3435
// Remove a specific feature flag for a user
3536
export const removeUserFeatureFlag = async (userId: string, flag: string): Promise<void> => {
37+
await authorization.canManageFlags();
38+
await authorization.canManageUser(userId);
39+
3640
try {
3741
// Get current flags
3842
const currentFlags = await getUserFeatureFlags(userId);
@@ -42,11 +46,11 @@ export const removeUserFeatureFlag = async (userId: string, flag: string): Promi
4246

4347
if (updatedFlags.length > 0) {
4448
// Update the database with the remaining features
45-
await prisma.user.update({
46-
where: { id: userId },
47-
data: {
48-
features: {
49-
set: updatedFlags.map((feature) => ({ userId_feature: { userId, feature } })),
49+
await prisma.userFeature.delete({
50+
where: {
51+
userId_feature: {
52+
userId,
53+
feature: flag,
5054
},
5155
},
5256
});
@@ -64,36 +68,11 @@ export const removeUserFeatureFlag = async (userId: string, flag: string): Promi
6468
}
6569
};
6670

67-
// Add a specific feature flag for a user
68-
export const addUserFeatureFlag = async (userId: string, flag: string): Promise<void> => {
69-
try {
70-
// Get current flags
71-
const currentFlags = await getUserFeatureFlags(userId);
72-
73-
// Add the new flag if it doesn't already exist
74-
if (!currentFlags.includes(flag)) {
75-
const updatedFlags = [...currentFlags, flag];
76-
77-
// Update the database
78-
await prisma.user.update({
79-
where: { id: userId },
80-
data: {
81-
features: {
82-
set: updatedFlags.map((feature) => ({ userId_feature: { userId, feature } })),
83-
},
84-
},
85-
});
86-
87-
// Update the cache
88-
await featureFlagsPut(userId, updatedFlags);
89-
}
90-
} catch (error) {
91-
throw new Error(`Failed to add feature flag: ${error}`);
92-
}
93-
};
94-
9571
// Add multiple feature flags for a user
9672
export const addUserFeatureFlags = async (userId: string, flags: string[]): Promise<void> => {
73+
await authorization.canManageFlags();
74+
await authorization.canManageUser(userId);
75+
9776
try {
9877
// Get current flags
9978
const currentFlags = await getUserFeatureFlags(userId);
@@ -105,13 +84,9 @@ export const addUserFeatureFlags = async (userId: string, flags: string[]): Prom
10584
const updatedFlags = [...currentFlags, ...newFlags];
10685

10786
// Update the database
108-
await prisma.user.update({
109-
where: { id: userId },
110-
data: {
111-
features: {
112-
set: updatedFlags.map((feature) => ({ userId_feature: { userId, feature } })),
113-
},
114-
},
87+
await prisma.userFeature.createMany({
88+
data: newFlags.map((feature) => ({ userId, feature })),
89+
skipDuplicates: true, // avoids error if the (userId, feature) already exists
11590
});
11691

11792
// Update the cache

0 commit comments

Comments
 (0)