Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'
import { ConfigurationService } from '../infrastructure/configuration/configuration.service'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'
import { ConfigurationService } from '../../cpin-module/infrastructure/configuration/configuration.service'
import { NexusClientService } from './nexus-client.service'
import { NexusHttpClientService } from './nexus-http-client.service'

const nexusUrl = 'https://nexus.internal'

const server = setupServer()
const nexusAdminPassword = faker.internet.password()
const basicAuth = `Basic ${Buffer.from(`admin:${nexusAdminPassword}`, 'utf8').toString('base64')}`

const server = setupServer()

function createNexusServiceTestingModule() {
return Test.createTestingModule({
providers: [
Expand All @@ -35,6 +40,9 @@ function createNexusServiceTestingModule() {
describe('nexusClientService', () => {
let service: NexusClientService

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
const basicAuth = `Basic ${Buffer.from('admin:password', 'utf8').toString('base64')}`

beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))

beforeEach(async () => {
Expand Down Expand Up @@ -75,4 +83,31 @@ describe('nexusClientService', () => {

await service.updateSecurityUsersChangePassword('u1', 'pw123')
})

it('should return null on 404 (getRepositoriesMavenHosted)', async () => {
server.use(
http.get(`${nexusUrl}/service/rest/v1/repositories/maven/hosted/:name`, ({ request }) => {
expect(request.headers.get('authorization')).toBe(basicAuth)
return HttpResponse.json({}, { status: 404 })
}),
)

await expect(service.getRepositoriesMavenHosted('missing')).resolves.toBeNull()
})

it('should send basic auth and plain text body on change-password', async () => {
server.use(
http.put(`${nexusUrl}/service/rest/v1/security/users/:userId/change-password`, async ({ request, params }) => {
expect(request.method).toBe('PUT')
expect(request.url).toBe(`${nexusUrl}/service/rest/v1/security/users/u1/change-password`)
expect(params.userId).toBe('u1')
expect(request.headers.get('authorization')).toBe(basicAuth)
expect(request.headers.get('content-type')).toContain('text/plain')
expect(await request.text()).toBe('pw123')
return new HttpResponse(null, { status: 204 })
}),
)

await service.updateSecurityUsersChangePassword('u1', 'pw123')
})
})
22 changes: 16 additions & 6 deletions apps/server-nestjs/src/modules/nexus/nexus.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
DEFAULT_MAVEN_SNAPSHOT_WRITE_POLICY,
DEFAULT_NPM_WRITE_POLICY,
DEFAULT_PLATFORM_READ_GROUP_PATHS,
DEFAULT_PLATFORM_READONLY_GROUP_PATH,
DEFAULT_PLATFORM_SECURITY_GROUP_PATH,
DEFAULT_PLATFORM_WRITE_GROUP_PATHS,
DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES,
DEFAULT_PROJECT_WRITE_GROUP_PATH_SUFFIXES,
Expand All @@ -28,7 +30,10 @@ import {
NEXUS_CONFIG_KEY_MAVEN_SNAPSHOT_WRITE_POLICY,
NEXUS_CONFIG_KEY_NPM_WRITE_POLICY,
NEXUS_PLUGIN_NAME,
PLATFORM_ADMIN_GROUP_PATH_PLUGIN_KEY,
PLATFORM_READ_GROUP_PATHS_PLUGIN_KEY,
PLATFORM_READONLY_GROUP_PATH_PLUGIN_KEY,
PLATFORM_SECURITY_GROUP_PATH_PLUGIN_KEY,
PLATFORM_WRITE_GROUP_PATHS_PLUGIN_KEY,
PROJECT_READ_GROUP_PATH_SUFFIXES_PLUGIN_KEY,
PROJECT_WRITE_GROUP_PATH_SUFFIXES_PLUGIN_KEY,
Expand Down Expand Up @@ -489,8 +494,8 @@ export class NexusService {
const rawReadSuffixes = await this.getOptionalConfigValue(project, PROJECT_READ_GROUP_PATH_SUFFIXES_PLUGIN_KEY)
?? DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES

const writeGroupPaths = generateProjectRoleGroupPath(project, rawWriteSuffixes || DEFAULT_PROJECT_WRITE_GROUP_PATH_SUFFIXES)
const readGroupPaths = generateProjectRoleGroupPath(project, rawReadSuffixes || DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES)
const writeGroupPaths = generateProjectRoleGroupPath(project.slug, rawWriteSuffixes || DEFAULT_PROJECT_WRITE_GROUP_PATH_SUFFIXES)
const readGroupPaths = generateProjectRoleGroupPath(project.slug, rawReadSuffixes || DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES)

const byId = generateRolePrivilegesMapping({
readGroupPaths,
Expand All @@ -504,9 +509,14 @@ export class NexusService {

private async ensurePlatformRoles(projects: ProjectWithDetails[]) {
const rawWriteGroupPaths = await this.nexusDatastore.getAdminPluginConfig(NEXUS_PLUGIN_NAME, PLATFORM_WRITE_GROUP_PATHS_PLUGIN_KEY)
?? await this.nexusDatastore.getAdminPluginConfig(NEXUS_PLUGIN_NAME, PLATFORM_ADMIN_GROUP_PATH_PLUGIN_KEY)
?? DEFAULT_PLATFORM_WRITE_GROUP_PATHS

const rawReadGroupPaths = await this.nexusDatastore.getAdminPluginConfig(NEXUS_PLUGIN_NAME, PLATFORM_READ_GROUP_PATHS_PLUGIN_KEY)
?? [
await this.nexusDatastore.getAdminPluginConfig(NEXUS_PLUGIN_NAME, PLATFORM_READONLY_GROUP_PATH_PLUGIN_KEY) ?? DEFAULT_PLATFORM_READONLY_GROUP_PATH,
await this.nexusDatastore.getAdminPluginConfig(NEXUS_PLUGIN_NAME, PLATFORM_SECURITY_GROUP_PATH_PLUGIN_KEY) ?? DEFAULT_PLATFORM_SECURITY_GROUP_PATH,
].join(',')
?? DEFAULT_PLATFORM_READ_GROUP_PATHS

const readonlyPrivileges = new Set<string>()
Expand Down Expand Up @@ -535,8 +545,8 @@ export class NexusService {
?? DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES

const groupPaths = [
...generateProjectRoleGroupPath(project, rawWriteSuffixes || DEFAULT_PROJECT_WRITE_GROUP_PATH_SUFFIXES),
...generateProjectRoleGroupPath(project, rawReadSuffixes || DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES),
...generateProjectRoleGroupPath(project.slug, rawWriteSuffixes || DEFAULT_PROJECT_WRITE_GROUP_PATH_SUFFIXES),
...generateProjectRoleGroupPath(project.slug, rawReadSuffixes || DEFAULT_PROJECT_READ_GROUP_PATH_SUFFIXES),
]

const ids = [...new Set(groupPaths.map(generateRoleId))]
Expand Down Expand Up @@ -608,12 +618,12 @@ function generateNpmGroupPrivilegeNameReadonly(project: ProjectWithDetails) {
return `${generateNpmGroupPrivilegeName(project)}-ro`
}

function generateProjectRoleGroupPath(project: ProjectWithDetails, rawGroupPathSuffixes: string) {
function generateProjectRoleGroupPath(projectSlug: string, rawGroupPathSuffixes: string) {
return rawGroupPathSuffixes
.split(',')
.map(path => path.trim())
.filter(Boolean)
.map(path => `/${project.slug}${path}`)
.map(path => `/${projectSlug}${path}`)
}

function parseOidcGroupPaths(rawGroupPaths: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Test } from '@nestjs/testing'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'
import { ConfigurationService } from '../infrastructure/configuration/configuration.service'
import { ConfigurationService } from '../../cpin-module/infrastructure/configuration/configuration.service'
import { VaultClientService } from '../vault/vault-client.service'
import { RegistryClientService } from './registry-client.service'
import { RegistryHttpClientService } from './registry-http-client.service'
Expand Down
Loading
Loading