-
Notifications
You must be signed in to change notification settings - Fork 5
/
idir.ts
123 lines (110 loc) · 4.44 KB
/
idir.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { createIdirUser } from '../keycloak/users';
import { ConfidentialClientApplication, IConfidentialClientApplication } from '@azure/msal-node';
import { CYPRESS_MOCKED_IDIR_LOOKUP, MS_GRAPH_URL } from '@lambda-app/utils/constants';
import { MsGraphUserResponse, MsGraphUserValue } from '@lambda-shared/interfaces';
import axios from 'axios';
import createHttpError from 'http-errors';
let msalInstance: IConfidentialClientApplication;
const msalConfig = {
auth: {
authority: process.env.MS_GRAPH_API_AUTHORITY || '',
clientId: process.env.MS_GRAPH_API_CLIENT_ID || '',
clientSecret: process.env.MS_GRAPH_API_CLIENT_SECRET || '',
},
};
export async function getAzureAccessToken() {
const request = {
scopes: [`${MS_GRAPH_URL}/.default`],
};
try {
if (!msalInstance) {
msalInstance = new ConfidentialClientApplication(msalConfig);
}
const response = await msalInstance.acquireTokenByClientCredential(request);
return response?.accessToken;
} catch (error) {
console.error(error);
throw new createHttpError.Unauthorized('could not fetch access token');
}
}
/**
* Search idir users by email via the azure graph api
*/
export async function callAzureGraphApi(endpoint: string) {
const accessToken = await getAzureAccessToken();
const options = {
headers: {
Authorization: `Bearer ${accessToken}`,
ConsistencyLevel: 'eventual',
},
};
const response = await axios.get(endpoint, options);
return response.data;
}
/** Search for an idir email address. Lookup uses the "startswith" function so expects the beggining of the address. */
export const searchIdirEmail = async (email: string) => {
if (process.env.CYPRESS_RUNNER) {
return CYPRESS_MOCKED_IDIR_LOOKUP;
}
const url = `${MS_GRAPH_URL}/v1.0/users?$filter=startswith(mail,'${email}')&$orderby=userPrincipalName&$count=true&$top=25`;
return callAzureGraphApi(url).then((res) => res.value?.map((value) => ({ mail: value.mail, id: value.id })));
};
/** Validate the provided email is linked to an existing IDIR account. */
export const validateIdirEmail = async (email: string) => {
const url = `${MS_GRAPH_URL}/v1.0/users/${email}`;
try {
const response = await callAzureGraphApi(url);
return { given_name: response.givenName, family_name: response.surname };
} catch (error) {
return false;
}
};
const formatUser = (data: MsGraphUserValue) => {
const userId = data.mailNickname;
const guid = data.onPremisesExtensionAttributes.extensionAttribute12;
const email = data.mail;
const firstName = data.givenName;
const lastName = data.surname;
const displayName = data.displayName;
const company = data.companyName;
const phone = data.mobilePhone;
const department = data.department;
const jobTitle = data.jobTitle;
return { guid, userId, email, firstName, lastName, displayName, company, phone, department, jobTitle };
};
/** Search for an IDIR user by any field and value. Search expects the actual value to start with the provided value. */
export const searchIdirUsers = async ({ field, search }: { field: string; search: string }) => {
const url = `${MS_GRAPH_URL}/v1.0/users?$filter=startswith(${field},'${search}')&$top=25&$select=onPremisesExtensionAttributes,mailNickname,displayName,mail,givenName,surname,companyName,department,jobTitle,mobilePhone`;
try {
const response = (await callAzureGraphApi(url)) as MsGraphUserResponse;
const formattedUsers = response.value.map(formatUser);
return formattedUsers;
} catch (err) {
console.log(err?.response?.data || err);
return false;
}
};
/** Import a user into the keycloak instances for all envs. */
export const importIdirUser = async ({ guid, userId }: { guid: string; userId: string }) => {
const url = `${MS_GRAPH_URL}/v1.0/users?$filter=mailNickname eq '${userId}'&$select=onPremisesExtensionAttributes,displayName,mail,givenName,surname`;
const response = (await callAzureGraphApi(url)) as MsGraphUserResponse;
if (!response?.value?.length) {
return false;
}
const result = response.value.find((user) => user.onPremisesExtensionAttributes.extensionAttribute12 === guid);
if (!result) return false;
await Promise.all(
['dev', 'test', 'prod'].map((env) =>
createIdirUser({
environment: env,
guid,
userId,
email: result.mail,
firstName: result.givenName,
lastName: result.surname,
displayName: result.displayName,
}).catch(() => null),
),
);
return true;
};