-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scaffolder hooks to call auth and execute a fetch with a token
- Loading branch information
Showing
7 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# scaffolder-frontend-auth | ||
|
||
_This package was created through the Backstage CLI_. | ||
|
||
## Installation | ||
|
||
Install the package via Yarn: | ||
|
||
```sh | ||
cd <package-dir> # if within a monorepo | ||
yarn add scaffolder-frontend-auth | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "scaffolder-frontend-auth", | ||
"version": "0.1.0", | ||
"main": "src/index.ts", | ||
"types": "src/index.ts", | ||
"license": "Apache-2.0", | ||
"private": true, | ||
"publishConfig": { | ||
"access": "public", | ||
"main": "dist/index.esm.js", | ||
"types": "dist/index.d.ts" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"backstage": { | ||
"role": "web-library" | ||
}, | ||
"scripts": { | ||
"start": "backstage-cli package start", | ||
"build": "backstage-cli package build", | ||
"lint": "backstage-cli package lint", | ||
"test": "backstage-cli package test", | ||
"clean": "backstage-cli package clean", | ||
"prepack": "backstage-cli package prepack", | ||
"postpack": "backstage-cli package postpack" | ||
}, | ||
"dependencies": { | ||
"@backstage/core-plugin-api": "^1.3.0", | ||
"@backstage/integration-react": "^1.1.9", | ||
"@backstage/plugin-scaffolder-react": "^1.0.1", | ||
"react-use": "^17.4.0" | ||
}, | ||
"peerDependencies": { | ||
"react": "^16.13.1 || ^17.0.0" | ||
}, | ||
"devDependencies": { | ||
"@backstage/cli": "^0.22.1", | ||
"@testing-library/jest-dom": "^5.10.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { useState } from 'react'; | ||
import { useApi } from '@backstage/core-plugin-api'; | ||
import { scmAuthApiRef } from '@backstage/integration-react'; | ||
import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react'; | ||
import useDebounce from 'react-use/lib/useDebounce'; | ||
|
||
export type RequestUserCredentials = { | ||
additionalScopes: Record<string, string[]>; | ||
secretsKey: string; | ||
}; | ||
|
||
export const useAuth = ({ | ||
requestUserCredentials, | ||
url, | ||
}: { | ||
requestUserCredentials?: RequestUserCredentials; | ||
url?: string; | ||
} = {}) => { | ||
const schAuthApi = useApi(scmAuthApiRef); | ||
const { setSecrets } = useTemplateSecrets(); | ||
const [localToken, setToken] = useState<string | undefined>(); | ||
|
||
useDebounce( | ||
async () => { | ||
if (!requestUserCredentials || !url) return; | ||
|
||
const { token } = await schAuthApi.getCredentials({ | ||
url, | ||
additionalScope: { | ||
repoWrite: true, | ||
...(requestUserCredentials?.additionalScopes | ||
? { customScopes: requestUserCredentials.additionalScopes } | ||
: {}), | ||
}, | ||
}); | ||
|
||
if (requestUserCredentials?.secretsKey) | ||
setSecrets({ [requestUserCredentials.secretsKey]: token }); | ||
setToken(token); | ||
}, | ||
500, | ||
[localToken], | ||
); | ||
|
||
return localToken ? localToken : undefined; | ||
}; |
70 changes: 70 additions & 0 deletions
70
plugins/scaffolder-frontend-auth/src/hooks/useFetchWithAuth.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import useAsync from 'react-use/lib/useAsync'; | ||
import { useAuth } from './useAuth'; | ||
|
||
export type RequestUserCredentials = { | ||
additionalScopes: Record<string, string[]>; | ||
secretsKey: string; | ||
}; | ||
|
||
export const useFetchWithAuth = ({ | ||
requestUserCredentials, | ||
url, | ||
fetchOpts, | ||
}: { | ||
requestUserCredentials?: RequestUserCredentials; | ||
url: string; | ||
fetchOpts: { | ||
url: string; | ||
options?: Record<string, unknown>; | ||
headersRequiringToken?: string[]; | ||
}; | ||
}) => { | ||
const token = useAuth({ url, requestUserCredentials }); | ||
|
||
const { value, loading, error } = useAsync(async (): Promise<any> => { | ||
if (token) { | ||
const headersRequiringToken = fetchOpts?.headersRequiringToken ?? []; | ||
const options = fetchOpts.options ?? {}; | ||
if (headersRequiringToken) { | ||
if (!options.headers) options.headers = {} as Record<string, string>; | ||
// add token to any existing headers | ||
options.headers = Object.entries( | ||
options.headers as Record<string, string>, | ||
).reduce((headers, [header, headerValue]) => { | ||
if (headersRequiringToken.includes(header)) { | ||
headers[header] = `${headerValue}${token}`; | ||
} else { | ||
headers[header] = headerValue; | ||
} | ||
return headers; | ||
}, {} as Record<string, string>); | ||
|
||
headersRequiringToken.forEach(header => { | ||
if ( | ||
!Object.keys(options.headers as Record<string, string>).includes( | ||
header, | ||
) | ||
) { | ||
(options.headers as Record<string, string>)[header] = token; | ||
} | ||
}); | ||
} | ||
const response = await fetch(fetchOpts.url, { | ||
...fetchOpts.options, | ||
...headersRequiringToken.reduce((headers, headerVal) => { | ||
headers[headerVal] = token; | ||
return headers; | ||
}, {} as Record<string, string>), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(`unable to fetch from ${fetchOpts.url}`); | ||
} | ||
|
||
return response.json(); | ||
} | ||
return undefined; | ||
}, [token]); | ||
|
||
return { value, loading, error }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { useAuth, type RequestUserCredentials } from './hooks/useAuth'; | ||
export { useFetchWithAuth } from './hooks/useFetchWithAuth'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import '@testing-library/jest-dom'; |