119119 < h3 > File</ h3 >
120120 </ p >
121121 < p class ="comment ">
122- < code > src/management/lifecycle /_dto/config.dto.ts</ code >
122+ < code > src/management/identities/validations /_dto/config.dto.ts</ code >
123123 </ p >
124124
125125
@@ -142,11 +142,14 @@ <h6><b>Properties</b></h6>
142142 < li >
143143 < span class ="modifier "> </ span >
144144 < span class ="modifier "> </ span >
145- < span class ="modifier "> </ span >
145+ < span class ="modifier "> Public</ span >
146+ < a href ="#attributes " > attributes</ a >
147+ </ li >
148+ < li >
146149 < span class ="modifier "> </ span >
147150 < span class ="modifier "> </ span >
148151 < span class ="modifier "> Public</ span >
149- < a href ="#identities " > identities </ a >
152+ < a href ="#objectClasses " > objectClasses </ a >
150153 </ li >
151154 </ ul >
152155 </ td >
@@ -171,22 +174,57 @@ <h3 id="inputs">
171174 < tbody >
172175 < tr >
173176 < td class ="col-md-4 ">
174- < a name ="identities "> </ a >
177+ < a name ="attributes "> </ a >
175178 < span class ="name ">
176179 < span class ="modifier "> </ span >
177180 < span class ="modifier "> </ span >
178- < span class ="modifier "> </ span >
181+ < span class ="modifier "> Public</ span >
182+ < span > < b > attributes</ b > </ span >
183+ < a href ="#attributes "> < span class ="icon ion-ios-link "> </ span > </ a >
184+ </ span >
185+ </ td >
186+ </ tr >
187+ < tr >
188+ < td class ="col-md-4 ">
189+ < i > Type : </ i > < code > < a href ="../classes/ConfigObjectAttributeDTO.html " target ="_self " > ConfigObjectAttributeDTO[]</ a > </ code >
190+
191+ </ td >
192+ </ tr >
193+ < tr >
194+ < td class ="col-md-4 ">
195+ < b > Decorators : </ b >
196+ < br />
197+ < code >
198+ @ValidateNested({each: true})< br /> @Type(undefined)< br />
199+ </ code >
200+ </ td >
201+ </ tr >
202+ < tr >
203+ < td class ="col-md-4 ">
204+ < div class ="io-line "> Defined in < a href ="" data-line ="42 " class ="link-to-prism "> src/management/identities/validations/_dto/config.dto.ts:42</ a > </ div >
205+ </ td >
206+ </ tr >
207+
208+
209+ </ tbody >
210+ </ table >
211+ < table class ="table table-sm table-bordered ">
212+ < tbody >
213+ < tr >
214+ < td class ="col-md-4 ">
215+ < a name ="objectClasses "> </ a >
216+ < span class ="name ">
179217 < span class ="modifier "> </ span >
180218 < span class ="modifier "> </ span >
181219 < span class ="modifier "> Public</ span >
182- < span > < b > identities </ b > </ span >
183- < a href ="#identities "> < span class ="icon ion-ios-link "> </ span > </ a >
220+ < span > < b > objectClasses </ b > </ span >
221+ < a href ="#objectClasses "> < span class ="icon ion-ios-link "> </ span > </ a >
184222 </ span >
185223 </ td >
186224 </ tr >
187225 < tr >
188226 < td class ="col-md-4 ">
189- < i > Type : </ i > < code > ConfigObjectIdentitiesDTO[] </ code >
227+ < i > Type : </ i > < code > < a href =" ../classes/ConfigObjectObjectClassDTO.html " target =" _self " > ConfigObjectObjectClassDTO[] </ a > </ code >
190228
191229 </ td >
192230 </ tr >
@@ -195,13 +233,13 @@ <h3 id="inputs">
195233 < b > Decorators : </ b >
196234 < br />
197235 < code >
198- @IsOptional() < br /> @IsArray() < br /> @ApiProperty({type: ConfigObjectIdentitiesDTO, required: false}) < br /> @ ValidateNested({each: true})< br /> @Type(undefined)< br />
236+ @ValidateNested({each: true})< br /> @Type(undefined)< br />
199237 </ code >
200238 </ td >
201239 </ tr >
202240 < tr >
203241 < td class ="col-md-4 ">
204- < div class ="io-line "> Defined in < a href ="" data-line ="183 " class ="link-to-prism "> src/management/lifecycle/ _dto/config.dto.ts:183 </ a > </ div >
242+ < div class ="io-line "> Defined in < a href ="" data-line ="38 " class ="link-to-prism "> src/management/identities/validations/ _dto/config.dto.ts:38 </ a > </ div >
205243 </ td >
206244 </ tr >
207245
@@ -220,189 +258,48 @@ <h3 id="inputs">
220258
221259
222260 < div class ="tab-pane fade tab-source-code " id ="source ">
223- < pre class ="line-numbers compodoc-sourcecode "> < code class ="language-typescript "> import { ApiProperty } from '@nestjs/swagger';
224- import { Type, Transform } from 'class-transformer';
225- import { IsArray, IsEnum, IsNegative, IsNotEmpty, IsNumber, IsObject, IsOptional, ValidateNested, registerDecorator, ValidationOptions, ValidationArguments, isString, isNumber, IsString } from 'class-validator';
226- import { IdentityLifecycle } from '~/management/identities/_enums/lifecycle.enum';
227-
228- /**
229- * Transform trigger values to seconds.
230- * - Numbers are interpreted as days and converted to seconds
231- * - Strings with 'd' suffix are interpreted as days and converted to seconds
232- * - Strings with 'm' suffix are interpreted as minutes and converted to seconds
233- * - Strings with 's' suffix are already in seconds
234- *
235- * @param value The trigger value to transform
236- * @returns The value converted to seconds
237- */
238- function transformTriggerToSeconds(value: number | string): number | undefined {
239- let isValid = false;
240-
241- if (value === undefined || value === null) {
242- return undefined;
243- }
244-
245- /**
246- * Check if the value is a number.
247- * If it's a number, we check if it's upper than 0.
248- * If it's a string, we check if it matches the regex for time strings.
249- */
250- if (isNumber(value)) {
251- isValid = value < 0;
252- } else if (isString(value)) {
253- const timeRegex = /^\d+[dms]$/;
254- if (timeRegex.test(value)) {
255- // Extract the number part and check if it's
256- const numberPart = value.replace(/[dms]$/, '');
257- const num = parseInt(numberPart, 10);
258- isValid = num > 0;
259- }
260- }
261-
262- if (!isValid) {
263- throw new Error('Trigger must be a number (days) or a time string with units (e.g., "90d", "10m", "45s")');
264- }
265-
266- /**
267- * If the value is a number, we assume it's in days and convert it to seconds.
268- * We multiply by 24 (hours) * 60 (minutes) * 60 (seconds) to get the total seconds.
269- * This conversion preserves the sign of the number,
270- * so if the input is negative, the output will also be negative.
271- */
272- if (isNumber(value)) {
273- return value * 24 * 60 * 60; // Convert days to seconds, preserving sign
274- }
275-
276- /**
277- * If the value is a string, we check if it matches the regex for negative time strings.
278- * If it does, we extract the number and unit, then convert it to seconds.
279- * - 'd' is converted to seconds by multiplying by 24 * 60 * 60
280- * - 'm' is converted to seconds by multiplying by 60
281- * - 's' is already in seconds
282- * This conversion preserves the sign of the number,
283- * so if the input is negative, the output will also be negative.
284- */
285- if (isString(value)) {
286- const match = value.match(/^(\d+)([dms])$/);
287- if (match) {
288- const numValue = parseInt(match[1], 10);
289- const unit = match[2];
290-
291- switch (unit) {
292- case 'd': // days
293- return numValue * 24 * 60 * 60;
294-
295- case 'm': // minutes
296- return numValue * 60;
297-
298- case 's': // seconds
299- return numValue;
300-
301- default:
302- throw new Error(`Unsupported time unit: ${unit}`);
303- }
304- }
305- }
306-
307- // If we can't parse it, try to convert to number
308- return Number(value) || undefined;
309- }
261+ < pre class ="line-numbers compodoc-sourcecode "> < code class ="language-typescript "> import {IsString, ArrayNotEmpty, ValidateNested, IsEnum, IsBoolean, IsOptional} from 'class-validator';
262+ import { Type } from 'class-transformer';
263+ import { ConfigObjectType } from '../_enums/config.object';
310264
311- /**
312- * Custom decorator to validate that at least one of the properties 'rules' or 'trigger' is defined and not empty.
313- * This decorator can be applied to a class to enforce this validation rule.
314- *
315- * @param validationOptions
316- * @returns
317- */
318- function ValidateRulesOrTrigger(validationOptions?: ValidationOptions) {
319- return function (constructor: Function) {
320- registerDecorator({
321- name: 'validateRulesOrTrigger',
322- target: constructor,
323- propertyName: undefined,
324- options: validationOptions,
325- validator: {
326- validate(_: any, args: ValidationArguments) {
327- const obj = args.object as ConfigObjectIdentitiesDTO;
328-
329- /**
330- * Check if either 'rules' or 'trigger' is defined and not empty.
331- * 'rules' should be an object with at least one key-value pair,
332- * and 'trigger' should be a number that is not null.
333- */
334- const hasRules = obj.rules !== undefined && obj.rules !== null && (typeof obj.rules === 'object' && Object.keys(obj.rules).length > 0);
335- const hasTrigger = obj.trigger !== undefined && obj.trigger !== null;
336- return hasRules || hasTrigger;
337- },
338- defaultMessage(_: ValidationArguments) {
339- return 'Either rules or trigger must be provided';
340- }
341- }
342- });
343- };
344- }
265+ export class ConfigObjectAttributeDTO {
266+ @IsString()
267+ public name: string;
345268
346- @ValidateRulesOrTrigger({ message: 'Either rules or trigger must be provided' })
347- export class ConfigObjectIdentitiesDTO {
348- @IsEnum(IdentityLifecycle, { each: true })
349- @ApiProperty({
350- type: String,
351- enum: IdentityLifecycle,
352- description: 'Lifecycle state of the identity',
353- example: IdentityLifecycle.OFFICIAL,
354- required: true,
355- })
356- public sources: IdentityLifecycle[];
269+ @IsString()
270+ public desc: string;
357271
358- @IsOptional()
359272 @IsString()
360- public dateKey: string = 'lastSync';
273+ @IsEnum(ConfigObjectType)
274+ public type: ConfigObjectType;
361275
362- @IsOptional()
363- @IsObject()
364- public rules: object;
276+ @IsBoolean()
277+ public required: boolean;
365278
279+ @IsString()
366280 @IsOptional()
367- @IsObject()
368- public mutation: object;
281+ public format: string;
282+ }
369283
370- @IsOptional()
371- @Transform(({ value }) => transformTriggerToSeconds(value))
372- @IsNumber()
373- @ApiProperty({
374- oneOf: [
375- { type: 'number', description: 'Number representing days' },
376- { type: 'string', description: 'Time string with units (d=days, m=minutes, s=seconds)' }
377- ],
378- required: false,
379- description: 'Trigger time as number (days) or time string with units',
380- examples: [90, '90d', '10m', '45s']
381- })
382- public trigger: number;
383-
384- @IsNotEmpty()
385- @IsEnum(IdentityLifecycle)
386- @ApiProperty({
387- type: String,
388- enum: IdentityLifecycle,
389- description: 'Target lifecycle state for the identity',
390- example: IdentityLifecycle.MANUAL,
391- required: true,
392- })
393- public target: IdentityLifecycle;
284+ export class ConfigObjectObjectClassDTO {
285+ @IsString()
286+ public name: string;
287+
288+ @IsString()
289+ public desc: string;
290+
291+ @ArrayNotEmpty()
292+ public attributes: string[];
394293}
395294
396295export class ConfigObjectSchemaDTO {
397- @IsOptional()
398- @IsArray()
399- @ApiProperty({
400- type: ConfigObjectIdentitiesDTO,
401- required: false,
402- })
403296 @ValidateNested({ each: true })
404- @Type(() => ConfigObjectIdentitiesDTO)
405- public identities: ConfigObjectIdentitiesDTO[]
297+ @Type(() => ConfigObjectObjectClassDTO)
298+ public objectClasses: ConfigObjectObjectClassDTO[];
299+
300+ @ValidateNested({ each: true })
301+ @Type(() => ConfigObjectAttributeDTO)
302+ public attributes: ConfigObjectAttributeDTO[];
406303}
407304</ code > </ pre >
408305 </ div >
0 commit comments