Skip to content

Commit b1781c7

Browse files
authored
Merge pull request #22 from platform-mesh/feat/add-support-for-local-development
add support for local development
2 parents 00e5d65 + 5d71a6b commit b1781c7

13 files changed

+63
-122
lines changed

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@nestjs/core": ">=10.0.0",
3737
"@nestjs/platform-express": ">=10.0.0",
3838
"@nestjs/serve-static": ">=4.0.0",
39-
"@openmfp/portal-server-lib": ">=0.160.1",
39+
"@openmfp/portal-server-lib": ">=0.160.2",
4040
"axios": ">=1.7.7",
4141
"cookie-parser": ">=1.4.7",
4242
"express": ">=4.21.1",
@@ -48,7 +48,7 @@
4848
"@nestjs/axios": ">=3.0.0",
4949
"@nestjs/common": ">=10.0.0",
5050
"@nestjs/serve-static": ">=4.0.0",
51-
"@openmfp/portal-server-lib": ">=0.160.1",
51+
"@openmfp/portal-server-lib": ">=0.160.2",
5252
"axios": ">=1.7.7",
5353
"express": ">=4.21.1",
5454
"rxjs": ">=7.8.1"

src/portal-options/auth-config-provider.spec.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { PMAuthConfigProvider } from './auth-config-provider.js';
2-
import { getDomainAndOrganization } from './utils/domain.js';
32
import { HttpException } from '@nestjs/common';
43
import {
54
DiscoveryService,
@@ -98,22 +97,4 @@ describe('PMAuthConfigProvider', () => {
9897

9998
await expect(provider.getAuthConfig(req)).rejects.toThrow(HttpException);
10099
});
101-
102-
it('getDomain should return organization and baseDomain', () => {
103-
const req = { hostname: 'foo.example.com' } as Request;
104-
const result = getDomainAndOrganization(req);
105-
expect(result).toEqual({
106-
organization: 'foo',
107-
baseDomain: 'example.com',
108-
});
109-
});
110-
111-
it('getDomain should return clientId if hostname equals baseDomain', () => {
112-
const req = { hostname: 'example.com' } as Request;
113-
const result = getDomainAndOrganization(req);
114-
expect(result).toEqual({
115-
organization: 'client123',
116-
baseDomain: 'example.com',
117-
});
118-
});
119100
});

src/portal-options/auth-config-provider.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getOrganization } from './utils/domain.js';
12
import { CoreV1Api, KubeConfig } from '@kubernetes/client-node';
23
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
34
import {
@@ -19,13 +20,7 @@ export class PMAuthConfigProvider implements AuthConfigService {
1920

2021
async getAuthConfig(request: Request): Promise<ServerAuthVariables> {
2122
const baseDomain = process.env['BASE_DOMAINS_DEFAULT'];
22-
23-
const subDomain = request.hostname.split('.')[0];
24-
const isSubdomain = request.hostname !== baseDomain;
25-
26-
const clientId = isSubdomain
27-
? subDomain
28-
: process.env['OIDC_CLIENT_ID_DEFAULT'];
23+
const clientId = getOrganization(request);
2924
const clientSecret = await this.getClientSecret(clientId);
3025

3126
const oidcUrl = process.env[`DISCOVERY_ENDPOINT`]?.replace(

src/portal-options/pm-portal-context.service.spec.ts

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { PMPortalContextService } from './pm-portal-context.service.js';
22
import { KcpKubernetesService } from './services/kcp-k8s.service.js';
3-
import { getDomainAndOrganization } from './utils/domain.js';
3+
import { getOrganization } from './utils/domain.js';
44
import { Test, TestingModule } from '@nestjs/testing';
55
import { Request } from 'express';
66
import { mock } from 'jest-mock-extended';
7+
import process from 'node:process';
78

89
jest.mock('@kubernetes/client-node', () => {
910
class KubeConfig {
@@ -23,22 +24,19 @@ jest.mock('@kubernetes/client-node', () => {
2324
});
2425

2526
jest.mock('./utils/domain.js', () => ({
26-
getDomainAndOrganization: jest.fn(),
27+
getOrganization: jest.fn(),
2728
}));
2829

2930
describe('PMPortalContextService', () => {
3031
let service: PMPortalContextService;
3132
let kcpKubernetesServiceMock: jest.Mocked<KcpKubernetesService>;
32-
const mockedGetDomainAndOrganization = jest.mocked(getDomainAndOrganization);
33+
const mockedGetDomainAndOrganization = jest.mocked(getOrganization);
3334
let mockRequest: any;
3435

3536
beforeEach(async () => {
3637
kcpKubernetesServiceMock = mock();
3738

38-
mockedGetDomainAndOrganization.mockReturnValue({
39-
baseDomain: 'example.com',
40-
organization: 'test-org',
41-
});
39+
mockedGetDomainAndOrganization.mockReturnValue('test-org');
4240

4341
const module: TestingModule = await Test.createTestingModule({
4442
providers: [
@@ -87,10 +85,7 @@ describe('PMPortalContextService', () => {
8785
process.env.OTHER_ENV_VAR = 'should-be-ignored';
8886

8987
try {
90-
mockedGetDomainAndOrganization.mockReturnValue({
91-
baseDomain: 'example.com',
92-
organization: 'test-org',
93-
});
88+
mockedGetDomainAndOrganization.mockReturnValue('test-org');
9489

9590
const result = await service.getContextValues(mockRequest as Request);
9691

@@ -110,10 +105,7 @@ describe('PMPortalContextService', () => {
110105
process.env.OPENMFP_PORTAL_CONTEXT_MULTIPLE_SNAKE_CASE_KEYS = 'value2';
111106

112107
try {
113-
mockedGetDomainAndOrganization.mockReturnValue({
114-
baseDomain: 'example.com',
115-
organization: 'test-org',
116-
});
108+
mockedGetDomainAndOrganization.mockReturnValue('test-org');
117109

118110
const result = await service.getContextValues(mockRequest as Request);
119111

@@ -132,10 +124,7 @@ describe('PMPortalContextService', () => {
132124
'https://${org-subdomain}api.example.com/${org-name}/graphql';
133125

134126
try {
135-
mockedGetDomainAndOrganization.mockReturnValue({
136-
baseDomain: 'example.com',
137-
organization: 'test-org',
138-
});
127+
mockedGetDomainAndOrganization.mockReturnValue('test-org');
139128

140129
mockRequest.hostname = 'subdomain.example.com';
141130

@@ -154,11 +143,8 @@ describe('PMPortalContextService', () => {
154143
'https://${org-subdomain}api.example.com/${org-name}/graphql';
155144

156145
try {
157-
mockedGetDomainAndOrganization.mockReturnValue({
158-
baseDomain: 'example.com',
159-
organization: 'test-org',
160-
});
161-
146+
mockedGetDomainAndOrganization.mockReturnValue('test-org');
147+
process.env['BASE_DOMAINS_DEFAULT'] = 'example.com';
162148
mockRequest.hostname = 'example.com';
163149

164150
const result = await service.getContextValues(mockRequest as Request);
@@ -177,10 +163,7 @@ describe('PMPortalContextService', () => {
177163
process.env.OPENMFP_PORTAL_CONTEXT_VALID_KEY = 'valid-value';
178164

179165
try {
180-
mockedGetDomainAndOrganization.mockReturnValue({
181-
baseDomain: 'example.com',
182-
organization: 'test-org',
183-
});
166+
mockedGetDomainAndOrganization.mockReturnValue('test-org');
184167

185168
const result = await service.getContextValues(mockRequest as Request);
186169

src/portal-options/pm-portal-context.service.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { KcpKubernetesService } from './services/kcp-k8s.service.js';
2-
import { getDomainAndOrganization } from './utils/domain.js';
2+
import { getOrganization } from './utils/domain.js';
33
import { Injectable } from '@nestjs/common';
44
import { PortalContextProvider } from '@openmfp/portal-server-lib';
55
import type { Request } from 'express';
@@ -31,7 +31,7 @@ export class PMPortalContextService implements PortalContextProvider {
3131
}
3232

3333
private addKcpWorkspaceUrl(request, portalContext) {
34-
const { organization } = getDomainAndOrganization(request);
34+
const organization = getOrganization(request);
3535
const account = request.query?.['core_platform-mesh_io_account'];
3636

3737
portalContext.kcpWorkspaceUrl = this.kcpKubernetesService
@@ -43,12 +43,12 @@ export class PMPortalContextService implements PortalContextProvider {
4343
request: Request,
4444
portalContext: Record<string, any>,
4545
): void {
46-
const org = getDomainAndOrganization(request);
47-
const subDomain =
48-
request.hostname === org.baseDomain ? '' : `${org.organization}.`;
46+
const org = getOrganization(request);
47+
const baseDomain = process.env['BASE_DOMAINS_DEFAULT'];
48+
const subDomain = request.hostname !== baseDomain ? `${org}.` : '';
4949
portalContext.crdGatewayApiUrl = portalContext.crdGatewayApiUrl
5050
?.replace('${org-subdomain}', subDomain)
51-
.replace('${org-name}', org.organization);
51+
.replace('${org-name}', org);
5252
}
5353

5454
private toCamelCase(text: string): string {

src/portal-options/pm-request-context-provider.spec.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PMPortalContextService } from './pm-portal-context.service.js';
22
import { PMRequestContextProvider } from './pm-request-context-provider.js';
3-
import { getDomainAndOrganization } from './utils/domain.js';
3+
import { getOrganization } from './utils/domain.js';
44
import type { Request } from 'express';
55
import { mock } from 'jest-mock-extended';
66

@@ -22,20 +22,17 @@ jest.mock('@kubernetes/client-node', () => {
2222
});
2323

2424
jest.mock('./utils/domain.js', () => ({
25-
getDomainAndOrganization: jest.fn(),
25+
getOrganization: jest.fn(),
2626
}));
2727

2828
describe('PMRequestContextProvider', () => {
2929
let provider: PMRequestContextProvider;
3030
const portalContextService = mock<PMPortalContextService>();
31-
const mockedGetDomainAndOrganization = jest.mocked(getDomainAndOrganization);
31+
const mockedGetOrganization = jest.mocked(getOrganization);
3232

3333
beforeEach(() => {
3434
jest.resetAllMocks();
35-
mockedGetDomainAndOrganization.mockReturnValue({
36-
organization: 'org1',
37-
baseDomain: 'org1.example.com',
38-
});
35+
mockedGetOrganization.mockReturnValue('org1');
3936
(
4037
portalContextService.getContextValues as unknown as jest.Mock
4138
).mockResolvedValue({
@@ -62,7 +59,7 @@ describe('PMRequestContextProvider', () => {
6259
organization: 'org1',
6360
});
6461

65-
expect(mockedGetDomainAndOrganization).toHaveBeenCalledWith(req);
62+
expect(mockedGetOrganization).toHaveBeenCalledWith(req);
6663
expect(portalContextService.getContextValues).toHaveBeenCalledWith(req);
6764
});
6865
});

src/portal-options/pm-request-context-provider.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PMPortalContextService } from './pm-portal-context.service.js';
2-
import { getDomainAndOrganization } from './utils/domain.js';
2+
import { getOrganization } from './utils/domain.js';
33
import { Injectable } from '@nestjs/common';
44
import { RequestContextProvider } from '@openmfp/portal-server-lib';
55
import type { Request } from 'express';
@@ -16,12 +16,13 @@ export class PMRequestContextProvider implements RequestContextProvider {
1616
constructor(private pmPortalContextService: PMPortalContextService) {}
1717

1818
async getContextValues(request: Request): Promise<RequestContext> {
19-
const domainData = getDomainAndOrganization(request);
19+
const organization = getOrganization(request);
20+
const baseDomain = process.env['BASE_DOMAINS_DEFAULT'];
2021
return {
2122
...request.query,
2223
...(await this.pmPortalContextService.getContextValues(request)),
23-
organization: domainData.organization,
24-
isSubDomain: request.hostname !== domainData.baseDomain,
24+
organization,
25+
isSubDomain: request.hostname !== baseDomain,
2526
};
2627
}
2728
}

src/portal-options/service-providers/content-configuration-service-providers.service.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ describe('ContentConfigurationServiceProvidersService', () => {
5656
expect(result).toEqual(welcomeNodeConfig);
5757
});
5858

59+
it('throws if context organization is missing', async () => {
60+
context.isSubDomain = false;
61+
const result = await service.getServiceProviders(
62+
'token',
63+
['entity'],
64+
context,
65+
);
66+
67+
expect(result).toEqual(welcomeNodeConfig);
68+
});
69+
5970
it('returns parsed content configurations', async () => {
6071
mockClient.request.mockResolvedValue({
6172
ui_platform_mesh_io: {

src/portal-options/service-providers/content-configuration-service-providers.service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { RequestContext } from '../pm-request-context-provider.js';
22
import { contentConfigurationsQuery } from './contentconfigurations-query.js';
33
import { ContentConfigurationQueryResponse } from './models/contentconfigurations.js';
44
import { welcomeNodeConfig } from './models/welcome-node-config.js';
5+
import { Injectable } from '@nestjs/common';
56
import {
67
ContentConfiguration,
78
ServiceProviderResponse,
89
ServiceProviderService,
910
} from '@openmfp/portal-server-lib';
1011
import { GraphQLClient } from 'graphql-request';
1112

13+
@Injectable()
1214
export class ContentConfigurationServiceProvidersService
1315
implements ServiceProviderService
1416
{

0 commit comments

Comments
 (0)