Skip to content

Commit

Permalink
chore: show authorized git services based on existed OAuth token secr…
Browse files Browse the repository at this point in the history
…ets (#986)

* chore: show authorized git services based on existed OAuth token secrets

Signed-off-by: Anatolii Bazko <[email protected]>

* Add test

Signed-off-by: Anatolii Bazko <[email protected]>

* fix formatting

Signed-off-by: Anatolii Bazko <[email protected]>

---------

Signed-off-by: Anatolii Bazko <[email protected]>
  • Loading branch information
tolusha authored Nov 14, 2023
1 parent 5174f24 commit 1abef30
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2018-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import { MockStoreEnhanced } from 'redux-mock-store';
import { ThunkDispatch } from 'redux-thunk';

import { AppState } from '@/store';
import { FakeStoreBuilder } from '@/store/__mocks__/storeBuilder';
import { IGitOauth } from '@/store/GitOauthConfig/types';

import * as TestStore from '..';

const gitOauth = [
{
name: 'github',
endpointUrl: 'https://github.com',
},
{
name: 'gitlab',
endpointUrl: 'https://gitlab.com',
},
{
name: 'azure-devops',
endpointUrl: 'https://dev.azure.com',
},
] as IGitOauth[];

const mockGetOAuthProviders = jest.fn().mockResolvedValue(gitOauth);
const mockGetDevWorkspacePreferences = jest.fn().mockResolvedValue({});
const mockGetOAuthToken = jest.fn().mockImplementation(provider => {
if (provider === 'github') {
return new Promise(resolve => resolve('github-token'));
}
return new Promise((_resolve, reject) => reject(new Error('Token not found')));
});
const mockFetchTokens = jest.fn().mockResolvedValue([
{
tokenName: 'github-personal-access-token',
gitProvider: 'oauth2-token',
gitProviderEndpoint: 'https://dev.azure.com/',
},
] as any[]);

jest.mock('../../../services/backend-client/oAuthApi', () => {
return {
getOAuthProviders: (...args: unknown[]) => mockGetOAuthProviders(...args),
getOAuthToken: (...args: unknown[]) => mockGetOAuthToken(...args),
getDevWorkspacePreferences: (...args: unknown[]) => mockGetDevWorkspacePreferences(...args),
};
});
jest.mock('../../../services/backend-client/personalAccessTokenApi', () => {
return {
fetchTokens: (...args: unknown[]) => mockFetchTokens(...args),
};
});

// mute the outputs
console.error = jest.fn();

describe('GitOauthConfig store, actions', () => {
let store: MockStoreEnhanced<AppState, ThunkDispatch<AppState, undefined, TestStore.KnownAction>>;

beforeEach(() => {
store = new FakeStoreBuilder()
.withInfrastructureNamespace([{ name: 'user-che', attributes: { phase: 'Active' } }])
.build();
});

afterEach(() => {
jest.clearAllMocks();
});

it('should request GitOauthConfig', async () => {
await store.dispatch(TestStore.actionCreators.requestGitOauthConfig());

const actions = store.getActions();

const expectedAction: TestStore.KnownAction = {
supportedGitOauth: gitOauth,
providersWithToken: ['github', 'azure-devops'],
type: TestStore.Type.RECEIVE_GIT_OAUTH_PROVIDERS,
};

expect(actions).toContainEqual(expectedAction);
});
});
37 changes: 33 additions & 4 deletions packages/dashboard-frontend/src/store/GitOauthConfig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
getOAuthProviders,
getOAuthToken,
} from '@/services/backend-client/oAuthApi';
import { fetchTokens } from '@/services/backend-client/personalAccessTokenApi';
import { IGitOauth } from '@/store/GitOauthConfig/types';
import { createObject } from '@/store/helpers';
import { selectDefaultNamespace } from '@/store/InfrastructureNamespaces/selectors';
Expand Down Expand Up @@ -141,12 +142,40 @@ export const actionCreators: ActionCreators = {
const providersWithToken: api.GitOauthProvider[] = [];
try {
const supportedGitOauth = await getOAuthProviders();

const defaultKubernetesNamespace = selectDefaultNamespace(getState());
const tokens = await fetchTokens(defaultKubernetesNamespace.name);

const promises: Promise<void>[] = [];
for (const { name } of supportedGitOauth) {
for (const gitOauth of supportedGitOauth) {
promises.push(
getOAuthToken(name).then(() => {
providersWithToken.push(name);
}),
getOAuthToken(gitOauth.name)
.then(() => {
providersWithToken.push(gitOauth.name);
})

// if `api/oauth/token` doesn't return a user's token,
// then check if there is the user's token in a Kubernetes Secret
.catch(() => {
const normalizedGitOauthEndpoint = gitOauth.endpointUrl.endsWith('/')
? gitOauth.endpointUrl.slice(0, -1)
: gitOauth.endpointUrl;

for (const token of tokens) {
const normalizedTokenGitProviderEndpoint = token.gitProviderEndpoint.endsWith('/')
? token.gitProviderEndpoint.slice(0, -1)
: token.gitProviderEndpoint;

// compare Git OAuth Endpoint url ONLY with OAuth tokens
if (
token.gitProvider.startsWith('oauth2') &&
normalizedGitOauthEndpoint === normalizedTokenGitProviderEndpoint
) {
providersWithToken.push(gitOauth.name);
break;
}
}
}),
);
}
promises.push(dispatch(actionCreators.requestSkipAuthorizationProviders()));
Expand Down

0 comments on commit 1abef30

Please sign in to comment.