Skip to content

Commit

Permalink
Remove dependency on /user and /profile API (#657)
Browse files Browse the repository at this point in the history
  • Loading branch information
akurinnoy authored Nov 2, 2022
1 parent 7b4827b commit bc9f117
Show file tree
Hide file tree
Showing 38 changed files with 630 additions and 633 deletions.
5 changes: 5 additions & 0 deletions packages/common/src/dto/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ export interface IServerConfig {
};
cheNamespace: string;
}

export interface IUserProfile {
email: string;
username: string;
}
13 changes: 8 additions & 5 deletions packages/dashboard-backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { registerDockerConfigRoutes } from './routes/api/dockerConfig';
import { registerKubeConfigRoute } from './routes/api/kubeConfig';
import { registerNamespacesRoute } from './routes/api/namespaces';
import { registerServerConfigRoute } from './routes/api/serverConfig';
import { registerUserProfileRoute } from './routes/api/userProfile';
import { registerYamlResolverRoute } from './routes/api/yamlResolver';
import { registerFactoryAcceptanceRedirect } from './routes/factoryAcceptanceRedirect';
import { registerWorkspaceRedirect } from './routes/workspaceRedirect';
Expand Down Expand Up @@ -79,19 +80,21 @@ export default async function buildApp(server: FastifyInstance): Promise<void> {
registerNamespacesRoute(server);
}

registerDevworkspacesRoutes(server);
registerClusterConfigRoute(server);

registerClusterInfoRoute(server);

registerDevWorkspaceTemplates(server);

registerDockerConfigRoutes(server);
registerDevworkspacesRoutes(server);

registerServerConfigRoute(server);
registerDockerConfigRoutes(server);

registerKubeConfigRoute(server);

registerClusterInfoRoute(server);
registerServerConfigRoute(server);

registerClusterConfigRoute(server);
registerUserProfileRoute(server);

registerYamlResolverRoute(server);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import {
IDevWorkspaceApi,
IDevWorkspaceTemplateApi,
IDockerConfigApi,
IServerConfigApi,
IKubeConfigApi,
INamespaceApi,
IServerConfigApi,
IUserProfileApi,
} from '../types';

export class DevWorkspaceClient implements IDevWorkspaceClient {
Expand All @@ -39,4 +40,7 @@ export class DevWorkspaceClient implements IDevWorkspaceClient {
get namespaceApi(): INamespaceApi {
throw new Error('Method not implemented.');
}
get userProfileApi(): IUserProfileApi {
throw new Error('Method not implemented.');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { DockerConfigApiService } from '../services/dockerConfigApi';
import { KubeConfigApiService } from '../services/kubeConfigApi';
import { NamespaceApiService } from '../services/namespaceApi';
import { ServerConfigApiService } from '../services/serverConfigApi';
import { UserProfileApiService } from '../services/userProfileApi';

jest.mock('../services/devWorkspaceApi.ts');

Expand All @@ -43,5 +44,6 @@ describe('DevWorkspace client', () => {
expect(client.namespaceApi).toBeInstanceOf(NamespaceApiService);
expect(client.serverConfigApi).toBeInstanceOf(ServerConfigApiService);
expect(client.devWorkspaceTemplateApi).toBeInstanceOf(DevWorkspaceTemplateApiService);
expect(client.userProfileApi).toBeInstanceOf(UserProfileApiService);
});
});
50 changes: 21 additions & 29 deletions packages/dashboard-backend/src/devworkspaceClient/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,66 +11,58 @@
*/

import * as k8s from '@kubernetes/client-node';
import { DevWorkspaceApiService } from './services/devWorkspaceApi';
import { DevWorkspaceTemplateApiService } from './services/devWorkspaceTemplateApi';
import { DockerConfigApiService } from './services/dockerConfigApi';
import { KubeConfigApiService } from './services/kubeConfigApi';
import { NamespaceApiService } from './services/namespaceApi';
import { ServerConfigApiService } from './services/serverConfigApi';
import { UserProfileApiService } from './services/userProfileApi';
import {
IServerConfigApi,
IDevWorkspaceApi,
IDevWorkspaceClient,
IDevWorkspaceTemplateApi,
IDockerConfigApi,
IKubeConfigApi,
INamespaceApi,
IServerConfigApi,
IUserProfileApi,
} from './types';
import { DevWorkspaceTemplateApiService } from './services/devWorkspaceTemplateApi';
import { DevWorkspaceApiService } from './services/devWorkspaceApi';
import { DockerConfigApiService } from './services/dockerConfigApi';
import { ServerConfigApiService } from './services/serverConfigApi';
import { KubeConfigApiService } from './services/kubeConfigApi';
import { NamespaceApiService } from './services/namespaceApi';

export * from './types';

export class DevWorkspaceClient implements IDevWorkspaceClient {
private apiEnabled: boolean | undefined;

private readonly _apisApi: k8s.ApisApi;
private readonly _devWorkspaceTemplateApi: IDevWorkspaceTemplateApi;
private readonly _devworkspaceApi: IDevWorkspaceApi;
private readonly _dockerConfigApi: IDockerConfigApi;
private readonly _serverConfigApi: IServerConfigApi;
private readonly _kubeConfigApi: IKubeConfigApi;
private readonly _namespaceApi: INamespaceApi;
private readonly kubeConfig: k8s.KubeConfig;

constructor(kc: k8s.KubeConfig) {
this._devWorkspaceTemplateApi = new DevWorkspaceTemplateApiService(kc);
this._devworkspaceApi = new DevWorkspaceApiService(kc);
this._dockerConfigApi = new DockerConfigApiService(kc);
this._serverConfigApi = new ServerConfigApiService(kc);
this._kubeConfigApi = new KubeConfigApiService(kc);
this._namespaceApi = new NamespaceApiService(kc);
this._apisApi = kc.makeApiClient(k8s.ApisApi);
this.kubeConfig = kc;
}

get devWorkspaceTemplateApi(): IDevWorkspaceTemplateApi {
return this._devWorkspaceTemplateApi;
return new DevWorkspaceTemplateApiService(this.kubeConfig);
}

get devworkspaceApi(): IDevWorkspaceApi {
return this._devworkspaceApi;
return new DevWorkspaceApiService(this.kubeConfig);
}

get dockerConfigApi(): IDockerConfigApi {
return this._dockerConfigApi;
return new DockerConfigApiService(this.kubeConfig);
}

get serverConfigApi(): IServerConfigApi {
return this._serverConfigApi;
return new ServerConfigApiService(this.kubeConfig);
}

get kubeConfigApi(): IKubeConfigApi {
return this._kubeConfigApi;
return new KubeConfigApiService(this.kubeConfig);
}

get namespaceApi(): INamespaceApi {
return this._namespaceApi;
return new NamespaceApiService(this.kubeConfig);
}

get userProfileApi(): IUserProfileApi {
return new UserProfileApiService(this.kubeConfig);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2018-2021 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
*/

/* eslint-disable @typescript-eslint/no-unused-vars */

import * as mockClient from '@kubernetes/client-node';
import { CoreV1Api, V1Secret } from '@kubernetes/client-node';
import { UserProfileApiService } from '../userProfileApi';

jest.mock('../../../helpers/getUserName.ts');

const userNamespace = 'user1-che';

describe('UserProfile API Service', () => {
let userProfileService: UserProfileApiService;

beforeEach(() => {
const { KubeConfig } = mockClient;
const kubeConfig = new KubeConfig();

kubeConfig.makeApiClient = jest.fn().mockImplementation(_api => {
return {
readNamespacedSecret: (_name, _namespace) => {
return Promise.resolve(buildSecret());
},
} as CoreV1Api;
});

userProfileService = new UserProfileApiService(kubeConfig);
});

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

test('user profile object', async () => {
const res = await userProfileService.getUserProfile(userNamespace);
expect(res).toEqual({ email: 'user1@che', username: 'user1' });
});
});

function buildSecret(): { body: V1Secret } {
return {
body: {
apiVersion: 'v1',
data: {
email: 'dXNlcjFAY2hl',
id: 'Q2dFeEVnVnNiMk5oYkE=',
name: 'dXNlcjE=',
},
kind: 'Secret',
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2021 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 { api } from '@eclipse-che/common';
import * as k8s from '@kubernetes/client-node';
import { IUserProfileApi } from '../types';
import { createError } from './helpers/createError';

const ERROR_LABEL = 'CORE_V1_API_ERROR';
const USER_PROFILE_SECRET_NAME = 'user-profile';

export class UserProfileApiService implements IUserProfileApi {
private readonly coreV1API: k8s.CoreV1Api;

constructor(kc: k8s.KubeConfig) {
this.coreV1API = kc.makeApiClient(k8s.CoreV1Api);
}

async getUserProfile(namespace: string): Promise<api.IUserProfile | undefined> {
try {
const result = await this.coreV1API.readNamespacedSecret(USER_PROFILE_SECRET_NAME, namespace);
const data = result.body.data;
if (data === undefined) {
throw new Error('Data is empty');
}
return {
username: Buffer.from(data.name, 'base64').toString(),
email: Buffer.from(data.email, 'base64').toString(),
};
} catch (e) {
console.error('Unable to get user profile data:', e);
throw createError(e, ERROR_LABEL, 'Unable to get user profile data');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ export interface IKubeConfigApi {
injectKubeConfig(namespace: string, devworkspaceId: string): Promise<void>;
}

export interface IUserProfileApi {
/**
* Returns user profile object that contains username and email.
*/
getUserProfile(namespace: string): Promise<api.IUserProfile | undefined>;
}

export type IDevWorkspaceCallbacks = {
onModified: (workspace: V1alpha2DevWorkspace) => void;
onDeleted: (workspaceId: string) => void;
Expand All @@ -215,6 +222,7 @@ export interface IDevWorkspaceClient {
serverConfigApi: IServerConfigApi;
kubeConfigApi: IKubeConfigApi;
namespaceApi: INamespaceApi;
userProfileApi: IUserProfileApi;
}

export interface IDevWorkspaceList {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2018-2021 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 { FastifyInstance } from 'fastify';
import { baseApiPath } from '../../../constants/config';
import { setup, teardown } from '../../../helpers/tests/appBuilder';
import { stubUserProfile } from '../helpers/__mocks__/getDevWorkspaceClient';

jest.mock('../helpers/getDevWorkspaceClient.ts');
jest.mock('../helpers/getToken.ts');
jest.mock('../helpers/getServiceAccountToken.ts');

describe('UserProfile Route', () => {
let app: FastifyInstance;
const namespace = 'user-che';

beforeEach(async () => {
app = await setup();
});

afterEach(() => {
teardown(app);
});

test('GET ${baseApiPath}/namespaces', async () => {
const res = await app.inject().get(`${baseApiPath}/userprofile/${namespace}`);

expect(res.statusCode).toEqual(200);
expect(res.json()).toEqual(stubUserProfile);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ export const stubDockerConfig = {};

export const stubNamespaces = ['user-che'];

export const stubUserProfile: api.IUserProfile = {
email: 'user1@che',
username: 'user1',
};

export function getDevWorkspaceClient(_args: Parameters<typeof helper>): ReturnType<typeof helper> {
return {
serverConfigApi: {
Expand Down Expand Up @@ -108,5 +113,8 @@ export function getDevWorkspaceClient(_args: Parameters<typeof helper>): ReturnT
listInNamespace: _namespace => Promise.resolve(stubDevWorkspaceTemplatesList),
patch: (_namespace, _name, _patches) => Promise.resolve(stubDevWorkspaceTemplate),
} as IDevWorkspaceTemplateApi,
userProfileApi: {
getUserProfile: _namespace => Promise.resolve(stubUserProfile),
},
} as DevWorkspaceClient;
}
34 changes: 34 additions & 0 deletions packages/dashboard-backend/src/routes/api/userProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2021 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 { FastifyInstance, FastifyRequest } from 'fastify';
import { baseApiPath } from '../../constants/config';
import { namespacedSchema } from '../../constants/schemas';
import { getSchema } from '../../services/helpers';
import { restParams } from '../../typings/models';
import { getDevWorkspaceClient } from './helpers/getDevWorkspaceClient';
import { getToken } from './helpers/getToken';

const tags = ['UserProfile'];

export function registerUserProfileRoute(server: FastifyInstance) {
server.get(
`${baseApiPath}/userprofile/:namespace`,
getSchema({ tags, params: namespacedSchema }),
async function (request: FastifyRequest) {
const { namespace } = request.params as restParams.INamespacedParam;
const token = getToken(request);
const { userProfileApi } = getDevWorkspaceClient(token);
return userProfileApi.getUserProfile(namespace);
},
);
}
Loading

0 comments on commit bc9f117

Please sign in to comment.