@forge/api
Advanced tools
Comparing version 3.2.0 to 3.3.0-next.0
# @forge/api | ||
## 3.3.0-next.0 | ||
### Minor Changes | ||
- 119eb24: Implement external auth API enhancements for Node runtime | ||
## 3.2.0 | ||
@@ -4,0 +10,0 @@ |
@@ -14,2 +14,3 @@ import { RequestInit } from 'node-fetch'; | ||
remote: ExternalAuthRemote; | ||
account: string; | ||
}; | ||
@@ -16,0 +17,0 @@ export declare function fetchProduct(args: FetchArgs): FetchMethod; |
@@ -25,3 +25,3 @@ "use strict"; | ||
init = (0, exports.addMagicAgent)(init, 'EXTERNAL_AUTH_REQUEST'); | ||
init.headers = Object.assign(Object.assign({}, init.headers), { authorization: `Forge user ${args.provider}` }); | ||
init.headers = Object.assign(Object.assign({}, init.headers), { authorization: `Forge user ${args.provider} ${args.account}` }); | ||
const response = await (0, node_fetch_1.default)(url, init); | ||
@@ -66,2 +66,29 @@ handleProxyResponseErrors(response); | ||
} | ||
function lazyThrowNeedsAuthenticationError(serviceKey) { | ||
return async (scopes) => { | ||
throw new errors_1.NeedsAuthenticationError('Authentication Required', serviceKey, scopes && { scopes }); | ||
}; | ||
} | ||
function buildExternalAuthAccountsInfo(provider, remote) { | ||
const { accounts } = findExternalAuthProviderConfigOrThrow(provider); | ||
const buildAccountModel = (account) => { | ||
const { externalAccountId: id } = account, rest = tslib_1.__rest(account, ["externalAccountId"]); | ||
return Object.assign(Object.assign({}, rest), { id }); | ||
}; | ||
const buildExternalAuthAccountMethods = (account, outboundAuthAccountId) => ({ | ||
hasCredentials: async (scopes) => !scopes || scopes.every((scope) => account.scopes.includes(scope)), | ||
requestCredentials: lazyThrowNeedsAuthenticationError(provider), | ||
getAccount: async () => { | ||
return account; | ||
}, | ||
fetch: (0, _1.wrapWithRouteUnwrapper)(fetchRemote({ provider, remote: remote !== null && remote !== void 0 ? remote : getDefaultRemote(provider), account: outboundAuthAccountId })) | ||
}); | ||
return accounts.map((account) => { | ||
const authAccount = buildAccountModel(account); | ||
return { | ||
account: authAccount, | ||
methods: buildExternalAuthAccountMethods(authAccount, account.id) | ||
}; | ||
}); | ||
} | ||
const addMagicAgent = (init, agentOverride) => (Object.assign(Object.assign({}, init), { agent: (agentOverride !== null && agentOverride !== void 0 ? agentOverride : 'FORGE_PRODUCT_REQUEST') })); | ||
@@ -72,17 +99,32 @@ exports.addMagicAgent = addMagicAgent; | ||
}; | ||
const withProvider = (provider, remote) => ({ | ||
hasCredentials: async () => { | ||
const { tokenAvailable } = findExternalAuthProviderConfigOrThrow(provider); | ||
return tokenAvailable; | ||
}, | ||
getAccount: throwNotImplementedError, | ||
requestCredentials: async () => { | ||
findExternalAuthProviderConfigOrThrow(provider); | ||
throw new errors_1.NeedsAuthenticationError('Authentication Required', provider); | ||
}, | ||
listCredentials: throwNotImplementedError, | ||
listAccounts: throwNotImplementedError, | ||
asAccount: throwNotImplementedError, | ||
fetch: (0, _1.wrapWithRouteUnwrapper)(fetchRemote({ provider, remote: remote !== null && remote !== void 0 ? remote : getDefaultRemote(provider) })) | ||
}); | ||
const withProvider = (provider, remote) => { | ||
const accountsInfo = buildExternalAuthAccountsInfo(provider, remote); | ||
const defaultAccountInfo = accountsInfo.length ? accountsInfo[0] : undefined; | ||
const lazyThrowNoValidCredentialsError = () => { | ||
return (url) => { | ||
throw new Error(`Fetch failed for ${remote ? `remote '${remote}', ` : ''}provider '${provider}', path '${url}' no credentials previously requested`); | ||
}; | ||
}; | ||
return { | ||
hasCredentials: async (scopes) => { | ||
return defaultAccountInfo ? await defaultAccountInfo.methods.hasCredentials(scopes) : false; | ||
}, | ||
getAccount: async () => { | ||
return defaultAccountInfo ? defaultAccountInfo.account : undefined; | ||
}, | ||
requestCredentials: lazyThrowNeedsAuthenticationError(provider), | ||
listCredentials: throwNotImplementedError, | ||
listAccounts: async () => { | ||
return accountsInfo.map(({ account }) => account); | ||
}, | ||
asAccount: (externalAccountId) => { | ||
const accountInfo = accountsInfo.find(({ account }) => account.id === externalAccountId); | ||
if (!accountInfo) { | ||
throw new Error(`No account with ID ${externalAccountId} found for provider ${provider}`); | ||
} | ||
return accountInfo.methods; | ||
}, | ||
fetch: defaultAccountInfo ? defaultAccountInfo.methods.fetch : lazyThrowNoValidCredentialsError() | ||
}; | ||
}; | ||
function getNodeRuntimeAPI() { | ||
@@ -89,0 +131,0 @@ return { |
@@ -8,5 +8,11 @@ import type { Metrics, Tags } from '@forge/util/packages/metrics-interface'; | ||
}; | ||
export declare type ExternalAuthMetaDataAccount = { | ||
id: string; | ||
externalAccountId: string; | ||
displayName: string; | ||
scopes: string[]; | ||
avatarUrl?: string; | ||
}; | ||
export declare type ExternalAuthMetaData = { | ||
service: string; | ||
tokenAvailable: boolean; | ||
remotes: { | ||
@@ -16,2 +22,3 @@ baseUrl: string; | ||
}[]; | ||
accounts: ExternalAuthMetaDataAccount[]; | ||
}; | ||
@@ -18,0 +25,0 @@ export declare type ForgeRuntime = { |
@@ -29,3 +29,3 @@ import { RequestInit, Response } from 'node-fetch'; | ||
} | ||
interface ExternalAuthAccountMethods { | ||
export interface ExternalAuthAccountMethods { | ||
hasCredentials: (scopes?: string[]) => Promise<boolean>; | ||
@@ -32,0 +32,0 @@ requestCredentials: (scopes?: string[]) => Promise<boolean>; |
{ | ||
"name": "@forge/api", | ||
"version": "3.2.0", | ||
"version": "3.3.0-next.0", | ||
"description": "Forge API methods", | ||
@@ -15,3 +15,3 @@ "author": "Atlassian", | ||
"devDependencies": { | ||
"@forge/runtime": "5.4.0", | ||
"@forge/runtime": "5.5.0-next.0", | ||
"@types/node": "14.18.63", | ||
@@ -18,0 +18,0 @@ "expect-type": "^0.17.3", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
116506
16282
1259
2
5
0