From f7e0929ab06d6a4fceb0f6a72a0bf6685ce84aa2 Mon Sep 17 00:00:00 2001 From: "j.dev" Date: Thu, 7 Nov 2024 15:03:23 -0800 Subject: [PATCH] chore(4123): filter invalid IDIR users from search --- app/components/users/UserAutocomplete.tsx | 34 +++++++++++-------- app/helpers/mock-users.ts | 31 ++++++++++------- app/prisma/schema.prisma | 10 +++--- app/services/db/user.ts | 27 +++++++++------ app/services/msgraph/index.ts | 14 +++++--- ...20241107213923-add_field_membersChanged.js | 9 ----- 6 files changed, 68 insertions(+), 57 deletions(-) delete mode 100644 data-migrations/migrations/20241107213923-add_field_membersChanged.js diff --git a/app/components/users/UserAutocomplete.tsx b/app/components/users/UserAutocomplete.tsx index 6ce6e1851..794b7d0a9 100644 --- a/app/components/users/UserAutocomplete.tsx +++ b/app/components/users/UserAutocomplete.tsx @@ -56,18 +56,22 @@ export default function UserAutocomplete({ onSelect }: { onSelect: (user?: User) const [data, setData] = useState([]); const [value, setValue] = useState(); const [searching, setSearching] = useState(false); - const throttled = useRef(_throttle((query: string) => searchUsers(query), 500, { trailing: true })); - - const fetchOptions = (query: string) => { - setLoading(true); - - throttled - .current(query) - ?.then((result) => { + const throttled = useRef( + _throttle( + async (query: string) => { + setLoading(true); + const result = await searchUsers(query); setData(result.data); setLoading(false); - }) - .catch(() => {}); + return result.data; + }, + 500, + { trailing: true }, + ), + ); + + const fetchOptions = (query: string) => { + throttled.current(query); }; const options = (data || []).map((item) => ( @@ -121,16 +125,16 @@ export default function UserAutocomplete({ onSelect }: { onSelect: (user?: User) - {data?.length ? ( - - {options} - - ) : ( + {loading || data?.length === 0 ? ( No results found + ) : ( + + {options} + )} ); diff --git a/app/helpers/mock-users.ts b/app/helpers/mock-users.ts index e8adea4af..9fb0136aa 100644 --- a/app/helpers/mock-users.ts +++ b/app/helpers/mock-users.ts @@ -12,19 +12,24 @@ export const proxyUsers: MsUser[] = mockFile.mocks.find( (mock: MockResponse) => mock.request.url === 'https://graph.microsoft.com/v1.0/users?$filter*', )?.response.body.value; -export const mockUsers = proxyUsers.map((usr) => { - const { firstName, lastName, email, ministry, idir, upn } = processMsUser(usr); - return { - firstName, - lastName, - displayName: formatFullName({ firstName, lastName }), - email, - ministry, - idir, - upn, - roles: _compact([usr.jobTitle]), - } as AppUserWithRoles; -}); +export const mockUsers = proxyUsers + .map((usr) => { + const appUser = processMsUser(usr); + if (!appUser) return null; + + const { firstName, lastName, email, ministry, idir, upn } = appUser; + return { + firstName, + lastName, + displayName: formatFullName({ firstName, lastName }), + email, + ministry, + idir, + upn, + roles: _compact([usr.jobTitle]), + } as AppUserWithRoles; + }) + .filter((v) => v!) as AppUserWithRoles[]; export const mockRoleUsers = mockUsers.filter((usr) => usr.roles.length > 0); export const mockNoRoleUsers = mockUsers.filter((usr) => usr.roles.length === 0); diff --git a/app/prisma/schema.prisma b/app/prisma/schema.prisma index 0ccea8a9a..695dc9f92 100644 --- a/app/prisma/schema.prisma +++ b/app/prisma/schema.prisma @@ -247,11 +247,11 @@ model Billing { } type PublicCloudDataChanges { - profileChanged Boolean - contactsChanged Boolean - membersChanged Boolean - budgetChanged Boolean - billingChanged Boolean + profileChanged Boolean? + contactsChanged Boolean? + membersChanged Boolean? + budgetChanged Boolean? + billingChanged Boolean? parentPaths String[] } diff --git a/app/services/db/user.ts b/app/services/db/user.ts index 75cd1f73f..9b2fd3dae 100644 --- a/app/services/db/user.ts +++ b/app/services/db/user.ts @@ -1,4 +1,4 @@ -import { Prisma } from '@prisma/client'; +import { Prisma, User } from '@prisma/client'; import _castArray from 'lodash-es/castArray'; import _compact from 'lodash-es/compact'; import _forEach from 'lodash-es/forEach'; @@ -77,16 +77,21 @@ export async function getMatchingUserIds(search: string) { export async function createProxyUsers() { const dbUsers = await Promise.all( - proxyUsers.map((puser: MsUser) => { - const { displayName, ...clearnUserData } = processMsUser(puser); - - clearnUserData.email = clearnUserData.email.toLowerCase(); - return prisma.user.upsert({ - where: { email: clearnUserData.email }, - update: clearnUserData, - create: clearnUserData, - }); - }), + proxyUsers + .map((puser: MsUser) => { + const appUser = processMsUser(puser); + if (!appUser) return null; + + const { displayName, ...clearnUserData } = appUser; + + clearnUserData.email = clearnUserData.email.toLowerCase(); + return prisma.user.upsert({ + where: { email: clearnUserData.email }, + update: clearnUserData, + create: clearnUserData, + }); + }) + .filter((v) => v!), ); return dbUsers; diff --git a/app/services/msgraph/index.ts b/app/services/msgraph/index.ts index ecaceb6c2..ad888997f 100644 --- a/app/services/msgraph/index.ts +++ b/app/services/msgraph/index.ts @@ -2,12 +2,18 @@ import { M365_URL } from '@/config'; import { parseMinistryFromDisplayName } from '@/helpers/user'; import { MsUser, AppUser } from '@/types/user'; import { callMsGraph, getAccessToken } from './core'; -export function processMsUser(user: MsUser): AppUser { + +export function processMsUser(user: MsUser): AppUser | null { + const idir = user.onPremisesSamAccountName; + const upn = user.userPrincipalName; + + if (!idir || !upn) return null; + return { providerUserId: user.id, - upn: user.userPrincipalName, + upn, email: user.mail.toLowerCase(), - idir: user.onPremisesSamAccountName, + idir, idirGuid: user.extension_85cc52e9286540fcb1f97ed86114a0e5_bcgovGUID, displayName: user.displayName, firstName: user.givenName, @@ -75,7 +81,7 @@ export async function listUsersByEmail(email: string) { } const data = await res.json(); - return (data as { value: MsUser[] }).value.map(processMsUser).filter((user) => !!user.upn); + return (data as { value: MsUser[] }).value.map(processMsUser).filter((user) => !!user); } export async function getUserByEmail(email: string) { diff --git a/data-migrations/migrations/20241107213923-add_field_membersChanged.js b/data-migrations/migrations/20241107213923-add_field_membersChanged.js deleted file mode 100644 index 8787629ea..000000000 --- a/data-migrations/migrations/20241107213923-add_field_membersChanged.js +++ /dev/null @@ -1,9 +0,0 @@ -export const up = async (db, client) => { - const result = await db - .collection('PublicCloudRequest') - .updateMany({ 'changes.membersChanged': { $exists: false } }, [{ $set: { 'changes.membersChanged': false } }]); - - console.log('add_field_membersChanged:', result); -}; - -export const down = async (db, client) => {};