chore(core): Add timestamp fields to Role, and support counting role usages (#19171)

This commit is contained in:
Andreas Fitzek
2025-09-17 09:21:40 +02:00
committed by GitHub
parent 763d17bb1f
commit 69c81a6437
19 changed files with 1575 additions and 15 deletions

View File

@@ -80,6 +80,8 @@ export {
export { UpdateRoleDto } from './roles/update-role.dto';
export { CreateRoleDto } from './roles/create-role.dto';
export { RoleListQueryDto } from './roles/role-list-query.dto';
export { RoleGetQueryDto } from './roles/role-get-query.dto';
export { OidcConfigDto } from './oidc/config.dto';

View File

@@ -0,0 +1,68 @@
import { RoleGetQueryDto } from '../role-get-query.dto';
describe('RoleGetQueryDto', () => {
describe('Valid requests', () => {
test.each([
{
name: 'with "true"',
request: {
withUsageCount: 'true',
},
},
{
name: 'with "false"',
request: {
withUsageCount: 'false',
},
},
{
name: 'without withUsageCount (uses default)',
request: {},
},
])('should pass validation for withUsageCount $name', ({ request }) => {
const result = RoleGetQueryDto.safeParse(request);
expect(result.success).toBe(true);
});
});
describe('Invalid requests', () => {
test.each([
{
name: 'with number',
request: {
withUsageCount: 1,
},
expectedErrorPath: ['withUsageCount'],
},
{
name: 'with boolean (true)',
request: {
withUsageCount: true,
},
expectedErrorPath: ['withUsageCount'],
},
{
name: 'with boolean (false)',
request: {
withUsageCount: false,
},
expectedErrorPath: ['withUsageCount'],
},
{
name: 'with invalid string',
request: {
withUsageCount: 'invalid',
},
expectedErrorPath: ['withUsageCount'],
},
])('should fail validation for withUsageCount $name', ({ request, expectedErrorPath }) => {
const result = RoleGetQueryDto.safeParse(request);
expect(result.success).toBe(false);
if (expectedErrorPath) {
expect(result.error?.issues[0].path).toEqual(expectedErrorPath);
}
});
});
});

View File

@@ -0,0 +1,68 @@
import { RoleListQueryDto } from '../role-list-query.dto';
describe('RoleListQueryDto', () => {
describe('Valid requests', () => {
test.each([
{
name: 'with "true"',
request: {
withUsageCount: 'true',
},
},
{
name: 'with "false"',
request: {
withUsageCount: 'false',
},
},
{
name: 'without withUsageCount (uses default)',
request: {},
},
])('should pass validation for withUsageCount $name', ({ request }) => {
const result = RoleListQueryDto.safeParse(request);
expect(result.success).toBe(true);
});
});
describe('Invalid requests', () => {
test.each([
{
name: 'with number',
request: {
withUsageCount: 1,
},
expectedErrorPath: ['withUsageCount'],
},
{
name: 'with boolean (true)',
request: {
withUsageCount: true,
},
expectedErrorPath: ['withUsageCount'],
},
{
name: 'with boolean (false)',
request: {
withUsageCount: false,
},
expectedErrorPath: ['withUsageCount'],
},
{
name: 'with invalid string',
request: {
withUsageCount: 'invalid',
},
expectedErrorPath: ['withUsageCount'],
},
])('should fail validation for withUsageCount $name', ({ request, expectedErrorPath }) => {
const result = RoleListQueryDto.safeParse(request);
expect(result.success).toBe(false);
if (expectedErrorPath) {
expect(result.error?.issues[0].path).toEqual(expectedErrorPath);
}
});
});
});

View File

@@ -0,0 +1,10 @@
import { Z } from 'zod-class';
import { booleanFromString } from '../../schemas/boolean-from-string';
/**
* Query DTO for retrieving a single role with optional usage count
*/
export class RoleGetQueryDto extends Z.class({
withUsageCount: booleanFromString.optional().default('false'),
}) {}

View File

@@ -0,0 +1,10 @@
import { Z } from 'zod-class';
import { booleanFromString } from '../../schemas/boolean-from-string';
/**
* Query DTO for listing roles with optional usage count
*/
export class RoleListQueryDto extends Z.class({
withUsageCount: booleanFromString.optional().default('false'),
}) {}