Skip to content

Commit 9b07b40

Browse files
feat(identity): create an identity layer ahead of multi-org and login changes (#4816)
1 parent 32ceeec commit 9b07b40

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed

src/identity/apis/auth.ts

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
// Functions calling API
2+
import {
3+
getAccount,
4+
getIdentity,
5+
getMe as getMeQuartz,
6+
getOrg,
7+
Account,
8+
Identity,
9+
IdentityAccount,
10+
IdentityUser,
11+
Me as MeQuartz,
12+
Organization,
13+
} from 'src/client/unityRoutes'
14+
15+
import {
16+
getMe as getMeIdpe,
17+
Error as IdpeError,
18+
UserResponse as UserResponseIdpe,
19+
} from 'src/client'
20+
21+
// Feature Flag Check
22+
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
23+
24+
// Constants
25+
import {CLOUD} from 'src/shared/constants'
26+
27+
// Types
28+
import {RemoteDataState} from 'src/types'
29+
30+
// These are optional properties of the current account which are not retrieved from identity.
31+
export interface CurrentAccount extends IdentityAccount {
32+
billingProvider?: 'zuora' | 'aws' | 'gcm' | 'azure'
33+
}
34+
35+
// Optional properties of the current org, which are not retrieved from identity.
36+
export interface CurrentOrg {
37+
id: string
38+
clusterHost: string
39+
name?: string
40+
creationDate?: string
41+
description?: string
42+
isRegionBeta?: boolean
43+
provider?: string
44+
regionCode?: string
45+
regionName?: string
46+
}
47+
48+
export interface CurrentIdentity {
49+
user: IdentityUser
50+
account: CurrentAccount
51+
org: CurrentOrg
52+
status?: RemoteDataState
53+
}
54+
55+
// 401 error
56+
export class UnauthorizedError extends Error {
57+
constructor(message) {
58+
super(message)
59+
this.name = 'UnauthorizedError'
60+
}
61+
}
62+
63+
// 404 error
64+
export class NotFoundError extends Error {
65+
constructor(message) {
66+
super(message)
67+
this.name = 'NotFoundError'
68+
}
69+
}
70+
71+
// 500 error
72+
export class ServerError extends Error {
73+
constructor(message) {
74+
super(message)
75+
this.name = 'ServerError'
76+
}
77+
}
78+
79+
export class GenericError extends Error {
80+
constructor(message) {
81+
super(message)
82+
this.name = 'GenericError'
83+
}
84+
}
85+
86+
export const fetchIdentity = async () => {
87+
// if we aren't in cloud, or we are in cloud and the unification flag is off
88+
if (!CLOUD || !isFlagEnabled('uiUnificationFlag')) {
89+
return fetchLegacyIdentity()
90+
}
91+
// if we make it to this line we are in cloud and ui unification flag is on
92+
93+
if (isFlagEnabled('quartzIdentity')) {
94+
return fetchQuartzIdentity()
95+
}
96+
97+
return fetchQuartzMe()
98+
}
99+
100+
// fetch user identity from /quartz/identity.
101+
export const fetchQuartzIdentity = async (): Promise<Identity> => {
102+
const response = await getIdentity({})
103+
104+
if (response.status === 401) {
105+
throw new UnauthorizedError(response.data.message)
106+
}
107+
108+
if (response.status === 500) {
109+
throw new ServerError(response.data.message)
110+
}
111+
112+
const user = response.data
113+
return user
114+
}
115+
116+
// fetch user identity from /quartz/me.
117+
export const fetchQuartzMe = async (): Promise<MeQuartz> => {
118+
const response = await getMeQuartz({})
119+
120+
if (response.status === 401) {
121+
throw new UnauthorizedError(response.data.message)
122+
}
123+
124+
if (response.status === 404) {
125+
throw new NotFoundError(response.data.message)
126+
}
127+
128+
if (response.status === 500) {
129+
throw new ServerError(response.data.message)
130+
}
131+
132+
const user = response.data
133+
return user
134+
}
135+
136+
// fetch user identity from /me (used in OSS and environments without Quartz)
137+
const fetchLegacyIdentity = async (): Promise<UserResponseIdpe> => {
138+
const response = await getMeIdpe({})
139+
140+
if (response.status === 500) {
141+
const error: IdpeError = response.data
142+
throw new ServerError(error.message)
143+
}
144+
145+
const user = response.data
146+
return user
147+
}
148+
149+
// fetch details about user's current account
150+
export const fetchAccountDetails = async (
151+
accountId: string | number
152+
): Promise<Account> => {
153+
const accountIdString = accountId.toString()
154+
155+
const response = await getAccount({
156+
accountId: accountIdString,
157+
})
158+
159+
if (response.status === 401) {
160+
throw new UnauthorizedError(response.data.message)
161+
}
162+
163+
if (response.status === 500) {
164+
throw new ServerError(response.data.message)
165+
}
166+
167+
const accountDetails = response.data
168+
return accountDetails
169+
}
170+
171+
// fetch details about user's current organization
172+
export const fetchOrgDetails = async (orgId: string): Promise<Organization> => {
173+
const response = await getOrg({orgId})
174+
175+
if (response.status === 401) {
176+
throw new UnauthorizedError(response.data.message)
177+
}
178+
179+
if (response.status === 500) {
180+
throw new ServerError(response.data.message)
181+
}
182+
183+
const orgDetails = response.data
184+
return orgDetails
185+
}
186+
187+
// Transform a response from `/identity` into a response that Me machinery can use
188+
export const convertIdentityToMe = (
189+
quartzIdentity: CurrentIdentity
190+
): MeQuartz => {
191+
const {account, org, user} = quartzIdentity
192+
193+
return {
194+
// User Data
195+
email: user.email,
196+
id: user.id,
197+
// Careful about this line.
198+
isOperator: user.operatorRole ? true : false,
199+
operatorRole: user.operatorRole,
200+
201+
// Account Data
202+
accountCreatedAt: account.accountCreatedAt,
203+
accountType: account.type,
204+
paygCreditStartDate: account.paygCreditStartDate,
205+
billingProvider: account.billingProvider ? account.billingProvider : null,
206+
207+
// Organization Data
208+
clusterHost: org.clusterHost,
209+
regionCode: org.regionCode ? org.regionCode : null,
210+
isRegionBeta: org.isRegionBeta ? org.isRegionBeta : null,
211+
regionName: org.regionName ? org.regionName : null,
212+
}
213+
}

0 commit comments

Comments
 (0)