-
Notifications
You must be signed in to change notification settings - Fork 302
Add GitHub App auth provider #15500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
eva-vashkevich
merged 14 commits into
rancher:master
from
rak-phillip:task/14796-github-app-auth-provider
Oct 15, 2025
Merged
Add GitHub App auth provider #15500
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
6482ec6
Add github app to list of auth providers
rak-phillip 237f575
Add github app auth form
rak-phillip abdb68f
Multiline input
rak-phillip 2accc31
Add instructions for registering github app
rak-phillip 0fd4fb7
Add additional warning for github app
rak-phillip 4ac1367
Move private key input to end of form
rak-phillip 2d292e2
Add required fields for github app auth
rak-phillip a244f0c
Add tests for github app auth
rak-phillip 2da81e7
Rename `NAME` prop to `name`
rak-phillip 98a29f9
Add secondary rolw to file upload button
rak-phillip 11411bd
Update the name of the form if github app is selected
rak-phillip 5844d31
Fix clientId display
rak-phillip db50fcb
Fix Github App ID label
rak-phillip 40b5058
Update instructions
rak-phillip File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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,82 @@ | ||
| import PagePo from '@/cypress/e2e/po/pages/page.po'; | ||
| import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po'; | ||
| import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po'; | ||
| import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po'; | ||
| import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po'; | ||
|
|
||
| export default class GithubAppPo extends PagePo { | ||
| private static createPath(clusterId: string, id?: string ) { | ||
| return `/c/${ clusterId }/auth/config/githubapp?mode=edit`; | ||
| } | ||
|
|
||
| static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> { | ||
| return super.goTo(GithubAppPo.createPath(clusterId)); | ||
| } | ||
|
|
||
| constructor(clusterId: string) { | ||
| super(GithubAppPo.createPath(clusterId)); | ||
| } | ||
|
|
||
| static navTo() { | ||
| const sideNav = new ProductNavPo(); | ||
|
|
||
| BurgerMenuPo.burgerMenuNavToMenubyLabel('Users & Authentication'); | ||
| sideNav.navToSideMenuEntryByLabel('Auth Provider'); | ||
| } | ||
|
|
||
| clientIdInputField() { | ||
| return this.self().get('[data-testid="client-id"').invoke('val'); | ||
| } | ||
|
|
||
| enterClientId(id: string) { | ||
| return new LabeledInputPo('[data-testid="client-id"]').set(id); | ||
| } | ||
|
|
||
| clientSecretInputField() { | ||
| return this.self().get('[data-testid="client-secret"').invoke('val'); | ||
| } | ||
|
|
||
| enterClientSecret(val: string) { | ||
| return new LabeledInputPo('[data-testid="client-secret"]').set(val); | ||
| } | ||
|
|
||
| gitHubAppIdInputField() { | ||
| return this.self().get('[data-testid="app-id"').invoke('val'); | ||
| } | ||
|
|
||
| enterGitHubAppId(val: string) { | ||
| return new LabeledInputPo('[data-testid="app-id"]').set(val); | ||
| } | ||
|
|
||
| installationIdInputField() { | ||
| return this.self().get('[data-testid="installation-id"').invoke('val'); | ||
| } | ||
|
|
||
| enterInstallationId(val: string) { | ||
| return new LabeledInputPo('[data-testid="installation-id"]').set(val); | ||
| } | ||
|
|
||
| privateKeyInputField() { | ||
| return this.self().get('[data-testid="private-key"').invoke('val'); | ||
| } | ||
|
|
||
| enterPrivateKey(val: string) { | ||
| return new LabeledInputPo('[data-testid="private-key"]').set(val); | ||
| } | ||
|
|
||
| saveButton(): AsyncButtonPo { | ||
| return new AsyncButtonPo('[data-testid="form-save"]', this.self()); | ||
| } | ||
|
|
||
| save() { | ||
| return new AsyncButtonPo('[data-testid="form-save"]').click(); | ||
| } | ||
|
|
||
| gitHubAppBanner() { | ||
| return this.self().get('[data-testid="github-app-banner"]'); | ||
| } | ||
|
|
||
| permissionsWarningBanner() { | ||
| return this.self().get('[data-testid="auth-provider-admin-permissions-warning-banner"]'); | ||
| } | ||
| } |
This file contains hidden or 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
This file contains hidden or 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,60 @@ | ||
| import HomePagePo from '@/cypress/e2e/po/pages/home.po'; | ||
| import GithubAppPo from '@/cypress/e2e/po/edit/auth/githubapp.po'; | ||
| import { AuthProvider, AuthProviderPo } from '@/cypress/e2e/po/pages/users-and-auth/authProvider.po'; | ||
|
|
||
| const authProviderPo = new AuthProviderPo('local'); | ||
| const githubAppPo = new GithubAppPo('local'); | ||
|
|
||
| const clientId = 'test-client-id'; | ||
| const clientSecret = 'test-client-secret'; | ||
| const appId = 'test-app-id'; | ||
| const privateKey = 'test-private-key'; | ||
|
|
||
| const mockStatusCode = 200; | ||
| const mockBody = {}; | ||
|
|
||
| describe('GitHub App', { tags: ['@adminUser', '@usersAndAuths'] }, () => { | ||
| beforeEach(() => { | ||
| cy.login(); | ||
| HomePagePo.goToAndWaitForGet(); | ||
| AuthProviderPo.navTo(); | ||
| authProviderPo.waitForPage(); | ||
| authProviderPo.selectProvider(AuthProvider.GITHUB_APP); | ||
| githubAppPo.waitForPage(); | ||
| }); | ||
|
|
||
| it('can navigate to Auth Provider and Select GitHub App', () => { | ||
| githubAppPo.mastheadTitle().should('include', `GitHub App`); | ||
|
|
||
| githubAppPo.gitHubAppBanner().should('be.visible'); | ||
| githubAppPo.permissionsWarningBanner().should('be.visible'); | ||
| }); | ||
|
|
||
| it('sends correct request to create GitHub App auth provider', () => { | ||
| cy.intercept('POST', 'v3/githubAppConfigs/githubapp?action=configureTest', (req) => { | ||
| expect(req.body.enabled).to.equal(false); | ||
| expect(req.body.id).to.equal('githubapp'); | ||
| expect(req.body.type).to.equal('githubAppConfig'); | ||
| expect(req.body.clientId).to.equal(clientId); | ||
| expect(req.body.clientSecret).to.equal(clientSecret); | ||
| expect(req.body.appId).to.equal(appId); | ||
| expect(req.body.privateKey).to.equal(privateKey); | ||
|
|
||
| req.reply(mockStatusCode, mockBody); | ||
|
|
||
| return true; | ||
| }).as('configureTest'); | ||
|
|
||
| // save should be disabled before values are filled | ||
| githubAppPo.saveButton().expectToBeDisabled(); | ||
| githubAppPo.enterClientId(clientId); | ||
| githubAppPo.enterClientSecret(clientSecret); | ||
| githubAppPo.enterGitHubAppId(appId); | ||
| githubAppPo.enterPrivateKey(privateKey); | ||
|
|
||
| // save should be enabled after values are filled | ||
| githubAppPo.saveButton().expectToBeEnabled(); | ||
| githubAppPo.save(); | ||
| cy.wait('@configureTest'); | ||
| }); | ||
| }); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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,97 @@ | ||
| <script setup lang="ts"> | ||
| import InfoBox from '@shell/components/InfoBox'; | ||
| import CopyToClipboard from '@shell/components/CopyToClipboard'; | ||
|
|
||
| type TArgs = { | ||
| baseUrl: string; | ||
| serverUrl: string; | ||
| provider: string; | ||
| username: string; | ||
| } | ||
|
|
||
| defineProps<{ | ||
| name: string; | ||
| tArgs: TArgs; | ||
| }>(); | ||
|
|
||
| </script> | ||
|
|
||
| <template> | ||
| <InfoBox | ||
| :step="1" | ||
| class="step-box" | ||
| > | ||
| <ul class="step-list"> | ||
| <li v-clean-html="t(`authConfig.${name}.form.prefix.1`, tArgs, true)" /> | ||
| <li v-clean-html="t(`authConfig.${name}.form.prefix.2`, tArgs, true)" /> | ||
| <li v-clean-html="t(`authConfig.${name}.form.prefix.3`, tArgs, true)" /> | ||
| <li v-clean-html="t(`authConfig.${name}.form.prefix.4`, tArgs, true)" /> | ||
| </ul> | ||
| </InfoBox> | ||
| <InfoBox | ||
| :step="2" | ||
| class="step-box" | ||
| > | ||
| <ul class="step-list"> | ||
| <li> | ||
| {{ t(`authConfig.${name}.form.instruction`, tArgs, true) }} | ||
| <ul class="mt-10"> | ||
| <li> | ||
| <b> | ||
| {{ t(`authConfig.${name}.form.app.label`) }} | ||
| </b>: | ||
| <span v-clean-html="t(`authConfig.${name}.form.app.value`, tArgs, true)" /> | ||
| </li> | ||
| <li> | ||
| <b> | ||
| {{ t(`authConfig.${name}.form.homepage.label`) }} | ||
| </b>: {{ tArgs.serverUrl }} | ||
| <CopyToClipboard | ||
| label-as="tooltip" | ||
| :text="tArgs.serverUrl" | ||
| class="icon-btn" | ||
| action-color="bg-transparent" | ||
| /> | ||
| </li> | ||
| <li> | ||
| <b> | ||
| {{ t(`authConfig.${name}.form.description.label`) }} | ||
| </b>: | ||
| <span v-clean-html="t(`authConfig.${name}.form.description.value`, tArgs, true)" /> | ||
| </li> | ||
| <li> | ||
| <b> | ||
| {{ t(`authConfig.${name}.form.callback.label`) }} | ||
| </b>: | ||
| {{ t(`authConfig.${name}.form.callback.value`, tArgs, true) }} | ||
| <CopyToClipboard | ||
| :text="tArgs.serverUrl" | ||
| label-as="tooltip" | ||
| class="icon-btn" | ||
| action-color="bg-transparent" | ||
| /> | ||
| </li> | ||
| </ul> | ||
| </li> | ||
| <li> | ||
| {{ t(`authConfig.${name}.form.create`, tArgs, true) }} | ||
| </li> | ||
| </ul> | ||
| </InfoBox> | ||
| <InfoBox | ||
| :step="3" | ||
| class="mb-20" | ||
| > | ||
| <ul class="step-list"> | ||
| <li v-clean-html="t(`authConfig.${name}.form.suffix.1`, tArgs, true)" /> | ||
| <li v-clean-html="t(`authConfig.${name}.form.suffix.2`, tArgs, true)" /> | ||
| <li v-clean-html="t(`authConfig.${name}.form.suffix.3`, tArgs, true)" /> | ||
| </ul> | ||
| </InfoBox> | ||
| </template> | ||
|
|
||
| <style lang="scss" scoped> | ||
| .step-list li:not(:last-child) { | ||
| margin-bottom: 8px; | ||
| } | ||
| </style> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be in quotes too? And the next two lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for clarity, what are these that you are referencing? I think that the convention I was going for was that targets of actions would be contained within quotation marks - for example, Click "Some label". With this in mind, I think that the targets of Copy & Paste can be contained in quotation marks.
With the current iteration, there's only one line below 521.. I think I've addressed the changes, but let me know if anything is missing.