Skip to content

Commit ec9bac7

Browse files
committed
Store BP token in session
1 parent 344fd10 commit ec9bac7

File tree

9 files changed

+80
-47
lines changed

9 files changed

+80
-47
lines changed

packages/app/src/cli/services/context/partner-account-info.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {outputDebug} from '@shopify/cli-kit/node/output'
55

66
export interface PartnersSession {
77
token: string
8+
businessPlatformToken: string
89
accountInfo: AccountInfo
910
userId: string
1011
}

packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ import {
118118
SchemaDefinitionByApiTypeQueryVariables,
119119
} from '../../api/graphql/functions/generated/schema-definition-by-api-type.js'
120120
import {WebhooksSpecIdentifier} from '../../models/extensions/specifications/app_config_webhook.js'
121-
import {ensureAuthenticatedAppManagement, ensureAuthenticatedBusinessPlatform} from '@shopify/cli-kit/node/session'
121+
import {ensureAuthenticatedAppManagementAndBusinessPlatform} from '@shopify/cli-kit/node/session'
122122
import {isUnitTest} from '@shopify/cli-kit/node/context/local'
123123
import {AbortError, BugError} from '@shopify/cli-kit/node/error'
124124
import {fetch} from '@shopify/cli-kit/node/http'
@@ -156,7 +156,6 @@ export class AppManagementClient implements DeveloperPlatformClient {
156156
public readonly supportsDevSessions = true
157157
public readonly organizationSource = OrganizationSource.BusinessPlatform
158158
private _session: PartnersSession | undefined
159-
private _businessPlatformToken: string | undefined
160159

161160
constructor(session?: PartnersSession) {
162161
this._session = session
@@ -171,20 +170,24 @@ export class AppManagementClient implements DeveloperPlatformClient {
171170
if (isUnitTest()) {
172171
throw new Error('AppManagementClient.session() should not be invoked dynamically in a unit test')
173172
}
174-
const userInfoResult = await businessPlatformRequestDoc(UserInfo, await this.businessPlatformToken())
175-
const {token, userId} = await ensureAuthenticatedAppManagement()
176-
if (userInfoResult.currentUserAccount) {
173+
174+
const {appToken, userId, businessPlatformToken} = await ensureAuthenticatedAppManagementAndBusinessPlatform()
175+
const userAccount = await businessPlatformRequestDoc(UserInfo, businessPlatformToken)
176+
177+
if (userAccount.currentUserAccount) {
177178
this._session = {
178-
token,
179+
token: appToken,
180+
businessPlatformToken,
179181
accountInfo: {
180182
type: 'UserAccount',
181-
email: userInfoResult.currentUserAccount.email,
183+
email: userAccount.currentUserAccount.email,
182184
},
183185
userId,
184186
}
185187
} else {
186188
this._session = {
187-
token,
189+
token: appToken,
190+
businessPlatformToken,
188191
accountInfo: {
189192
type: 'UnknownAccount',
190193
},
@@ -199,23 +202,22 @@ export class AppManagementClient implements DeveloperPlatformClient {
199202
return (await this.session()).token
200203
}
201204

205+
async businessPlatformToken(): Promise<string> {
206+
return (await this.session()).businessPlatformToken
207+
}
208+
202209
async refreshToken(): Promise<string> {
203-
const {token} = await ensureAuthenticatedAppManagement([], process.env, {noPrompt: true})
210+
const {appToken, businessPlatformToken} = await ensureAuthenticatedAppManagementAndBusinessPlatform(
211+
[],
212+
[],
213+
process.env,
214+
{noPrompt: true},
215+
)
204216
const session = await this.session()
205-
if (token) {
206-
session.token = token
207-
}
208-
return session.token
209-
}
217+
session.token = appToken
218+
session.businessPlatformToken = businessPlatformToken
210219

211-
async businessPlatformToken(): Promise<string> {
212-
if (isUnitTest()) {
213-
throw new Error('AppManagementClient.businessPlatformToken() should not be invoked dynamically in a unit test')
214-
}
215-
if (!this._businessPlatformToken) {
216-
this._businessPlatformToken = await ensureAuthenticatedBusinessPlatform()
217-
}
218-
return this._businessPlatformToken
220+
return session.token
219221
}
220222

221223
async accountInfo(): Promise<PartnersSession['accountInfo']> {

packages/app/src/cli/utilities/developer-platform-client/partners-client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,12 @@ export class PartnersClient implements DeveloperPlatformClient {
229229
const {token, userId} = await ensureAuthenticatedPartners()
230230
this._session = {
231231
token,
232+
businessPlatformToken: '',
232233
accountInfo: {type: 'UnknownAccount'},
233234
userId,
234235
}
235236
const accountInfo = await fetchCurrentAccountInformation(this, userId)
236-
this._session = {token, accountInfo, userId}
237+
this._session = {token, businessPlatformToken: '', accountInfo, userId}
237238
}
238239
return this._session
239240
}

packages/cli-kit/src/private/node/api.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {sanitizedHeadersOutput} from './api/headers.js'
22
import {sanitizeURL} from './api/urls.js'
3-
import {startHRTime} from '@shopify/cli-kit/node/hrtime'
43
import {outputDebug} from '@shopify/cli-kit/node/output'
54
import {Headers} from 'form-data'
65
import {ClientError} from 'graphql-request'
@@ -54,9 +53,7 @@ async function makeVerboseRequest<T extends {headers: Headers; status: number}>(
5453
const sanitizedUrl = sanitizeURL(url)
5554
let response: T = {} as T
5655
try {
57-
const start = startHRTime()
5856
response = await request()
59-
// console.log(`${endHRTimeInMs(start)}ms - Network: ${outputContent`${outputToken.magenta(url)}`.value}`)
6057
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6158
response.headers.forEach((value: any, key: any) => {
6259
if (responseHeaderIsInteresting(key)) responseHeaders[key] = value

packages/cli-kit/src/private/node/session/validate.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {sessionConstants} from '../constants.js'
66
import {outputDebug} from '../../../public/node/output.js'
77
import {firstPartyDev} from '../../../public/node/context/local.js'
88
import {OAuthApplications} from '../session.js'
9-
import {endHRTimeInMs, startHRTime} from '@shopify/cli-kit/node/hrtime'
109

1110
type ValidationResult = 'needs_refresh' | 'needs_full_auth' | 'ok'
1211

@@ -36,9 +35,7 @@ export async function validateSession(
3635
): Promise<ValidationResult> {
3736
if (!session) return 'needs_full_auth'
3837
const scopesAreValid = validateScopes(scopes, session.identity)
39-
const start = startHRTime()
4038
const identityIsValid = await validateIdentityToken(session.identity.accessToken)
41-
console.log(`${endHRTimeInMs(start)}ms - Auth: Identity token introspection (${identityIsValid ? 'OK' : 'FAILED'})`)
4239
if (!scopesAreValid) return 'needs_full_auth'
4340
let tokensAreExpired = isTokenExpired(session.identity)
4441

packages/cli-kit/src/public/node/analytics.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export async function reportAnalyticsEvent(options: ReportAnalyticsEventOptions)
4949
withinRateLimit = true
5050
},
5151
})
52-
console.log('All network time:', payload.public.cmd_all_timing_network_ms)
5352
if (!withinRateLimit) {
5453
outputDebug(outputContent`Skipping command analytics due to rate limiting, payload: ${outputToken.json(payload)}`)
5554
return

packages/cli-kit/src/public/node/api/graphql.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import {debugLogRequestInfo, errorHandler} from '../../../private/node/api/graph
33
import {addPublicMetadata, runWithTimer} from '../metadata.js'
44
import {retryAwareRequest} from '../../../private/node/api.js'
55
import {requestIdsCollection} from '../../../private/node/request-ids.js'
6-
import {endHRTimeInMs, startHRTime} from '../hrtime.js'
7-
import {outputContent, outputToken} from '../output.js'
86
import {
97
GraphQLClient,
108
rawRequest,
@@ -77,13 +75,8 @@ async function performGraphQLRequest<TResult>(options: PerformGraphQLRequestOpti
7775
// there is a errorPolicy option which returns rather than throwing on errors, but we _do_ ultimately want to
7876
// throw.
7977
try {
80-
const time = startHRTime()
8178
fullResponse = await client.rawRequest<TResult>(queryAsString, variables)
8279
await logLastRequestIdFromResponse(fullResponse)
83-
const firstLine = queryAsString.split('\n')[0] ?? ''
84-
const secondLine = queryAsString.split('\n')[1] ?? ''
85-
const validLine = firstLine.includes('query') ? firstLine : secondLine
86-
console.log(`${endHRTimeInMs(time)}ms - Network: ${outputContent`${outputToken.yellow(validLine)}`.value}`)
8780
return fullResponse
8881
} catch (error) {
8982
if (error instanceof ClientError) {

packages/cli-kit/src/public/node/session.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
ensureAuthenticatedAdmin,
3+
ensureAuthenticatedAppManagementAndBusinessPlatform,
34
ensureAuthenticatedBusinessPlatform,
45
ensureAuthenticatedPartners,
56
ensureAuthenticatedStorefront,
@@ -210,3 +211,35 @@ describe('ensureAuthenticatedBusinessPlatform', () => {
210211
await expect(got).rejects.toThrow(`No business-platform token`)
211212
})
212213
})
214+
215+
describe('ensureAuthenticatedAppManagementAndBusinessPlatform', () => {
216+
test('returns app management and business platform tokens if success', async () => {
217+
// Given
218+
vi.mocked(ensureAuthenticated).mockResolvedValueOnce({
219+
appManagement: 'app_management_token',
220+
businessPlatform: 'business_platform_token',
221+
userId: '1234-5678',
222+
})
223+
224+
// When
225+
const got = await ensureAuthenticatedAppManagementAndBusinessPlatform()
226+
227+
// Then
228+
expect(got).toEqual({
229+
appToken: 'app_management_token',
230+
businessPlatformToken: 'business_platform_token',
231+
userId: '1234-5678',
232+
})
233+
})
234+
235+
test('throws error if there are no tokens', async () => {
236+
// Given
237+
vi.mocked(ensureAuthenticated).mockResolvedValueOnce({userId: '1234-5678'})
238+
239+
// When
240+
const got = ensureAuthenticatedAppManagementAndBusinessPlatform()
241+
242+
// Then
243+
await expect(got).rejects.toThrow('No App Management or Business Platform token found after ensuring authenticated')
244+
})
245+
})

packages/cli-kit/src/public/node/session.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,35 @@ ${outputToken.json(scopes)}
6262
/**
6363
* Ensure that we have a valid session to access the App Management API.
6464
*
65-
* @param scopes - Optional array of extra scopes to authenticate with.
65+
* @param appManagementScopes - Optional array of extra scopes to authenticate with.
66+
* @param businessPlatformScopes - Optional array of extra scopes to authenticate with.
6667
* @param env - Optional environment variables to use.
6768
* @param options - Optional extra options to use.
6869
* @returns The access token for the App Management API.
6970
*/
70-
export async function ensureAuthenticatedAppManagement(
71-
scopes: AppManagementAPIScope[] = [],
71+
export async function ensureAuthenticatedAppManagementAndBusinessPlatform(
72+
appManagementScopes: AppManagementAPIScope[] = [],
73+
businessPlatformScopes: BusinessPlatformScope[] = [],
7274
env = process.env,
7375
options: EnsureAuthenticatedAdditionalOptions = {},
74-
): Promise<{token: string; userId: string}> {
76+
): Promise<{appToken: string; userId: string; businessPlatformToken: string}> {
7577
outputDebug(outputContent`Ensuring that the user is authenticated with the App Management API with the following scopes:
76-
${outputToken.json(scopes)}
78+
${outputToken.json(appManagementScopes)}
7779
`)
78-
const tokens = await ensureAuthenticated({appManagementApi: {scopes}}, env, options)
79-
if (!tokens) {
80-
throw new BugError('No App Management token found after ensuring authenticated')
80+
const tokens = await ensureAuthenticated(
81+
{appManagementApi: {scopes: appManagementScopes}, businessPlatformApi: {scopes: businessPlatformScopes}},
82+
env,
83+
options,
84+
)
85+
if (!tokens.appManagement || !tokens.businessPlatform) {
86+
throw new BugError('No App Management or Business Platform token found after ensuring authenticated')
87+
}
88+
89+
return {
90+
appToken: tokens.appManagement,
91+
userId: tokens.userId,
92+
businessPlatformToken: tokens.businessPlatform,
8193
}
82-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
83-
return {token: tokens.appManagement!, userId: tokens.userId}
8494
}
8595

8696
/**

0 commit comments

Comments
 (0)