@@ -9,40 +9,100 @@ import {
99 IsNotEmpty ,
1010 IsArray ,
1111 ValidateIf ,
12- IsEmpty
12+ IsEmpty ,
13+ ArrayNotEmpty
1314} from 'class-validator' ;
1415import { ApiExtraModels , ApiProperty , ApiPropertyOptional , getSchemaPath , PartialType } from '@nestjs/swagger' ;
1516import { Type } from 'class-transformer' ;
16- import { DisplayDto } from './oid4vc-issuer.dto' ;
1717import { SignerOption } from '@prisma/client' ;
18+ import { CredentialFormat } from '@credebl/enum/enum' ;
19+
20+ class CredentialAttributeDisplayDto {
21+ @ApiPropertyOptional ( { example : 'First Name' } )
22+ @IsString ( )
23+ @IsNotEmpty ( )
24+ name : string ;
25+
26+ @ApiPropertyOptional ( { example : 'en' } )
27+ @IsString ( )
28+ @IsOptional ( )
29+ locale ?: string ;
30+ }
31+
32+ // export class CredentialAttributeDto {
33+ // @ApiProperty ({ required: false, description: 'Whether the attribute is mandatory' })
34+ // @IsOptional ()
35+ // @IsBoolean ()
36+ // mandatory?: boolean;
37+
38+ // // TODO: Check how do we handle claims with only path rpoperty like email, etc.
39+ // @ApiProperty ({ description: 'Type of the attribute value (string, number, date, etc.)' })
40+ // @IsString ()
41+ // value_type: string;
42+
43+ // @ApiProperty ({
44+ // type: [String],
45+ // description:
46+ // 'Claims path pointer as per the draft 15 - https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-ID2.html#name-claims-path-pointer'
47+ // })
48+ // @IsArray ()
49+ // @IsString ({ each: true })
50+ // path: string[];
51+
52+ // @ApiProperty ({ type: [CredentialAttributeDisplayDto], required: false, description: 'Localized display values' })
53+ // @IsOptional ()
54+ // @ValidateNested ({ each: true })
55+ // @Type (() => CredentialAttributeDisplayDto)
56+ // display?: CredentialAttributeDisplayDto[];
57+ // }
58+
59+ export enum AttributeType {
60+ STRING = 'string' ,
61+ NUMBER = 'number' ,
62+ BOOLEAN = 'boolean' ,
63+ DATE = 'date' ,
64+ OBJECT = 'object' ,
65+ ARRAY = 'array' ,
66+ IMAGE = 'image'
67+ }
1868
1969export class CredentialAttributeDto {
70+ @ApiProperty ( { description : 'Unique key for this attribute (e.g., full_name, org.iso.23220.photoID.1.birth_date)' } )
71+ @IsString ( )
72+ key : string ;
73+
2074 @ApiProperty ( { required : false , description : 'Whether the attribute is mandatory' } )
2175 @IsOptional ( )
2276 @IsBoolean ( )
2377 mandatory ?: boolean ;
2478
2579 // TODO: Check how do we handle claims with only path rpoperty like email, etc.
26- @ApiProperty ( { description : 'Type of the attribute value (string, number, date, etc.)' } )
27- @IsString ( )
80+ @ApiProperty ( { enum : AttributeType , description : 'Type of the attribute value (string, number, date, etc.)' } )
81+ @IsEnum ( AttributeType )
2882 value_type : string ;
2983
84+ @ApiProperty ( { description : 'Whether this attribute should be disclosed (for SD-JWT)' } )
85+ @IsOptional ( )
86+ @IsBoolean ( )
87+ disclose ?: boolean ;
88+
89+ @ApiProperty ( { type : [ CredentialAttributeDisplayDto ] , required : false , description : 'Localized display values' } )
90+ @IsOptional ( )
91+ @ValidateNested ( { each : true } )
92+ @Type ( ( ) => CredentialAttributeDisplayDto )
93+ display ?: CredentialAttributeDisplayDto [ ] ;
94+
3095 @ApiProperty ( {
31- type : [ String ] ,
32- description :
33- 'Claims path pointer as per the draft 15 - https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0-ID2.html#name-claims-path-pointer'
96+ description : 'Nested attributes if type is object or array' ,
97+ required : false ,
98+ type : ( ) => [ CredentialAttributeDto ]
3499 } )
35- @IsArray ( )
36- @IsString ( { each : true } )
37- path : string [ ] ;
38-
39- @ApiProperty ( { type : [ DisplayDto ] , required : false , description : 'Localized display values' } )
40100 @IsOptional ( )
101+ @IsArray ( )
41102 @ValidateNested ( { each : true } )
42- @Type ( ( ) => DisplayDto )
43- display ?: DisplayDto [ ] ;
103+ @Type ( ( ) => CredentialAttributeDto )
104+ children ?: CredentialAttributeDto [ ] ;
44105}
45-
46106class LogoDto {
47107 @ApiPropertyOptional ( {
48108 example : 'https://upload.wikimedia.org/wikipedia/commons/2/2f/ABC-2021-LOGO.svg'
@@ -84,6 +144,23 @@ class CredentialDisplayDto {
84144 @ValidateNested ( )
85145 @Type ( ( ) => LogoDto )
86146 logo ?: LogoDto ;
147+
148+ @ApiPropertyOptional ( { example : '#12107c' } )
149+ @IsString ( )
150+ @IsOptional ( )
151+ background_color ?: string ;
152+
153+ @ApiPropertyOptional ( { example : '#FFFFFF' } )
154+ @IsString ( )
155+ @IsOptional ( )
156+ text_color ?: string ;
157+
158+ @ApiPropertyOptional ( { example : { uri : 'https://upload.wikimedia.org/wikipedia/commons/2/2f/ABC-2021-LOGO.svg' } } )
159+ @IsObject ( )
160+ @IsOptional ( )
161+ background_image ?: {
162+ uri : string ;
163+ } ;
87164}
88165
89166export class AppearanceDto {
@@ -115,7 +192,55 @@ export class AppearanceDto {
115192 display : CredentialDisplayDto [ ] ;
116193}
117194
118- @ApiExtraModels ( CredentialAttributeDto )
195+ export class MdocNamespaceDto {
196+ @ApiProperty ( { description : 'Namespace key (e.g., org.iso.23220.photoID.1)' } )
197+ @IsString ( )
198+ namespace : string ;
199+
200+ @ApiProperty ( { type : ( ) => [ CredentialAttributeDto ] } )
201+ @IsArray ( )
202+ @ArrayNotEmpty ( )
203+ @ValidateNested ( { each : true } )
204+ @Type ( ( ) => CredentialAttributeDto )
205+ attributes : CredentialAttributeDto [ ] ;
206+ }
207+ export class MdocTemplateDto {
208+ @ApiProperty ( {
209+ description : 'Document type (required when format is "mso_mdoc"; must NOT be provided when format is "vc+sd-jwt")' ,
210+ example : 'org.iso.23220.photoID.1'
211+ } )
212+ //@ValidateIf ((o: CreateCredentialTemplateDto) => 'mso_mdoc' === o.format)
213+ @IsString ( )
214+ doctype : string ;
215+
216+ @ApiProperty ( { type : ( ) => [ MdocNamespaceDto ] } )
217+ @IsArray ( )
218+ @ArrayNotEmpty ( )
219+ @ValidateNested ( { each : true } )
220+ @Type ( ( ) => MdocNamespaceDto )
221+ namespaces : MdocNamespaceDto [ ] ;
222+ }
223+
224+ export class SdJwtTemplateDto {
225+ @ApiProperty ( {
226+ description :
227+ 'Verifiable Credential Type (required when format is "vc+sd-jwt"; must NOT be provided when format is "mso_mdoc")' ,
228+ example : 'BirthCertificateCredential-sdjwt'
229+ } )
230+ // @ValidateIf ((o: CreateCredentialTemplateDto) => 'vc+sd-jwt' === o.format)
231+ @IsString ( )
232+ vct : string ;
233+
234+ @ApiProperty ( {
235+ type : 'array' ,
236+ items : { $ref : getSchemaPath ( CredentialAttributeDto ) } ,
237+ description : 'Attributes included in the credential template'
238+ } )
239+ @IsArray ( )
240+ attributes : CredentialAttributeDto [ ] ;
241+ }
242+
243+ @ApiExtraModels ( CredentialAttributeDto , SdJwtTemplateDto , MdocTemplateDto )
119244export class CreateCredentialTemplateDto {
120245 @ApiProperty ( { description : 'Template name' } )
121246 @IsString ( )
@@ -134,47 +259,37 @@ export class CreateCredentialTemplateDto {
134259 @IsEnum ( SignerOption )
135260 signerOption ! : SignerOption ;
136261
137- @ApiProperty ( { enum : [ 'mso_mdoc' , 'vc+sd-jwt' ] , description : 'Credential format type' } )
138- @IsEnum ( [ 'mso_mdoc' , 'vc+sd-jwt' ] )
139- format : 'mso_mdoc' | 'vc+sd-jwt' ;
140-
141- @ApiPropertyOptional ( {
142- description : 'Document type (required when format is "mso_mdoc"; must NOT be provided when format is "vc+sd-jwt")' ,
143- example : 'org.iso.23220.photoID.1'
144- } )
145- @ValidateIf ( ( o : CreateCredentialTemplateDto ) => 'mso_mdoc' === o . format )
146- @IsString ( )
147- doctype ?: string ;
262+ @ApiProperty ( { enum : CredentialFormat , description : 'Credential format type' } )
263+ @IsEnum ( CredentialFormat )
264+ format : CredentialFormat ;
148265
149- @ValidateIf ( ( o : CreateCredentialTemplateDto ) => 'vc+sd-jwt' === o . format )
266+ @ValidateIf ( ( o : CreateCredentialTemplateDto ) => CredentialFormat . SdJwtVc === o . format )
150267 @IsEmpty ( { message : 'doctype must not be provided when format is "vc+sd-jwt"' } )
151268 readonly _doctypeAbsentGuard ?: unknown ;
152269
153- @ApiPropertyOptional ( {
154- description :
155- 'Verifiable Credential Type (required when format is "vc+sd-jwt"; must NOT be provided when format is "mso_mdoc")' ,
156- example : 'BirthCertificateCredential-sdjwt'
157- } )
158- @ValidateIf ( ( o : CreateCredentialTemplateDto ) => 'vc+sd-jwt' === o . format )
159- @IsString ( )
160- vct ?: string ;
161-
162- @ValidateIf ( ( o : CreateCredentialTemplateDto ) => 'mso_mdoc' === o . format )
270+ @ValidateIf ( ( o : CreateCredentialTemplateDto ) => CredentialFormat . Mdoc === o . format )
163271 @IsEmpty ( { message : 'vct must not be provided when format is "mso_mdoc"' } )
164272 readonly _vctAbsentGuard ?: unknown ;
165273
274+ @ApiProperty ( {
275+ type : Object ,
276+ oneOf : [ { $ref : getSchemaPath ( SdJwtTemplateDto ) } , { $ref : getSchemaPath ( MdocTemplateDto ) } ] ,
277+ description : 'Credential template definition (depends on credentialFormat)'
278+ } )
279+ @ValidateNested ( )
280+ @Type ( ( { object } ) => {
281+ if ( object . format === CredentialFormat . Mdoc ) {
282+ return MdocTemplateDto ;
283+ } else if ( object . format === CredentialFormat . SdJwtVc ) {
284+ return SdJwtTemplateDto ;
285+ }
286+ } )
287+ template : SdJwtTemplateDto | MdocTemplateDto ;
288+
166289 @ApiProperty ( { default : false , description : 'Indicates whether credentials can be revoked' } )
167290 @IsBoolean ( )
168291 canBeRevoked = false ;
169292
170- @ApiProperty ( {
171- type : 'array' ,
172- items : { $ref : getSchemaPath ( CredentialAttributeDto ) } ,
173- description : 'Attributes included in the credential template'
174- } )
175- @IsArray ( )
176- attributes : CredentialAttributeDto [ ] ;
177-
178293 @ApiProperty ( {
179294 type : Object ,
180295 required : false ,
0 commit comments