@sphereon/ssi-sdk.data-store 0.36.1-feature.SSISDK.82.and.SSISDK.70.37 → 0.36.1-feature.fides.fixes.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +450 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +465 -117
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/__tests__/issuanceBranding.entities.test.ts +1 -1
- package/src/__tests__/issuanceBranding.store.test.ts +310 -0
- package/src/contact/ContactStore.ts +10 -1
- package/src/digitalCredential/DigitalCredentialStore.ts +1 -1
- package/src/entities/digitalCredential/DigitalCredentialEntity.ts +2 -2
- package/src/entities/issuanceBranding/CredentialBrandingEntity.ts +42 -1
- package/src/entities/issuanceBranding/CredentialLocaleBrandingEntity.ts +64 -1
- package/src/entities/issuanceBranding/IssuerLocaleBrandingEntity.ts +63 -1
- package/src/issuanceBranding/IssuanceBrandingStore.ts +16 -5
- package/src/migrations/generic/15-AddBrandingState.ts +64 -0
- package/src/migrations/generic/index.ts +6 -1
- package/src/migrations/postgres/1766000000000-AddBrandingState.ts +15 -0
- package/src/migrations/sqlite/1766000000000-AddBrandingState.ts +74 -0
- package/src/utils/issuanceBranding/HashUtils.ts +30 -0
- package/src/utils/issuanceBranding/MappingUtils.ts +21 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/ssi-sdk.data-store",
|
|
3
|
-
"version": "0.36.1-feature.
|
|
3
|
+
"version": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@sphereon/kmp-mdoc-core": "0.2.0-SNAPSHOT.26",
|
|
30
30
|
"@sphereon/pex": "5.0.0-unstable.28",
|
|
31
|
-
"@sphereon/ssi-sdk-ext.did-utils": "0.36.1-feature.
|
|
32
|
-
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.36.1-feature.
|
|
33
|
-
"@sphereon/ssi-sdk.agent-config": "0.36.1-feature.
|
|
34
|
-
"@sphereon/ssi-sdk.core": "0.36.1-feature.
|
|
35
|
-
"@sphereon/ssi-sdk.data-store-types": "0.36.1-feature.
|
|
36
|
-
"@sphereon/ssi-types": "0.36.1-feature.
|
|
31
|
+
"@sphereon/ssi-sdk-ext.did-utils": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
32
|
+
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
33
|
+
"@sphereon/ssi-sdk.agent-config": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
34
|
+
"@sphereon/ssi-sdk.core": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
35
|
+
"@sphereon/ssi-sdk.data-store-types": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
36
|
+
"@sphereon/ssi-types": "0.36.1-feature.fides.fixes.111+275075fd",
|
|
37
37
|
"@veramo/core": "4.2.0",
|
|
38
38
|
"@veramo/utils": "4.2.0",
|
|
39
39
|
"blakejs": "^1.2.1",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"PostgreSQL",
|
|
67
67
|
"Contact Store"
|
|
68
68
|
],
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "275075fdc7753426df398e771e7ecdf28b7d1e3b"
|
|
70
70
|
}
|
|
@@ -823,7 +823,7 @@ describe('Database entities tests', (): void => {
|
|
|
823
823
|
}
|
|
824
824
|
|
|
825
825
|
const issuerLocaleBrandingEntity: IssuerLocaleBrandingEntity = issuerLocaleBrandingEntityFrom(localeBranding)
|
|
826
|
-
const fromDb: IssuerLocaleBrandingEntity = await dbConnection.getRepository(
|
|
826
|
+
const fromDb: IssuerLocaleBrandingEntity = await dbConnection.getRepository(IssuerLocaleBrandingEntity).save(issuerLocaleBrandingEntity)
|
|
827
827
|
|
|
828
828
|
expect(fromDb).toBeDefined()
|
|
829
829
|
expect(fromDb?.alias).toEqual(localeBranding.alias)
|
|
@@ -1884,4 +1884,314 @@ describe('Issuance branding store tests', (): void => {
|
|
|
1884
1884
|
expect(result?.localeBranding[0].background!.image!.alt).toBeUndefined()
|
|
1885
1885
|
expect(result?.localeBranding[0].text!.color).toBeUndefined()
|
|
1886
1886
|
})
|
|
1887
|
+
|
|
1888
|
+
// State-related tests
|
|
1889
|
+
|
|
1890
|
+
it('should populate state field when adding credential branding', async (): Promise<void> => {
|
|
1891
|
+
const credentialBranding: IBasicCredentialBranding = {
|
|
1892
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
1893
|
+
vcHash: 'vcHash',
|
|
1894
|
+
localeBranding: [
|
|
1895
|
+
{
|
|
1896
|
+
alias: 'credentialTypeAlias',
|
|
1897
|
+
locale: 'en-US',
|
|
1898
|
+
},
|
|
1899
|
+
],
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
const result: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding)
|
|
1903
|
+
|
|
1904
|
+
expect(result).toBeDefined()
|
|
1905
|
+
expect(result.state).toBeDefined()
|
|
1906
|
+
expect(typeof result.state).toBe('string')
|
|
1907
|
+
expect(result.state.length).toBeGreaterThan(0)
|
|
1908
|
+
expect(result.localeBranding[0].state).toBeDefined()
|
|
1909
|
+
expect(typeof result.localeBranding[0].state).toBe('string')
|
|
1910
|
+
expect(result.localeBranding[0].state.length).toBeGreaterThan(0)
|
|
1911
|
+
})
|
|
1912
|
+
|
|
1913
|
+
it('should generate different states for different credential brandings', async (): Promise<void> => {
|
|
1914
|
+
const credentialBranding1: IBasicCredentialBranding = {
|
|
1915
|
+
issuerCorrelationId: 'issuerCorrelationId1',
|
|
1916
|
+
vcHash: 'vcHash1',
|
|
1917
|
+
localeBranding: [
|
|
1918
|
+
{
|
|
1919
|
+
alias: 'credentialTypeAlias1',
|
|
1920
|
+
locale: 'en-US',
|
|
1921
|
+
},
|
|
1922
|
+
],
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
const credentialBranding2: IBasicCredentialBranding = {
|
|
1926
|
+
issuerCorrelationId: 'issuerCorrelationId2',
|
|
1927
|
+
vcHash: 'vcHash2',
|
|
1928
|
+
localeBranding: [
|
|
1929
|
+
{
|
|
1930
|
+
alias: 'credentialTypeAlias2',
|
|
1931
|
+
locale: 'en-US',
|
|
1932
|
+
},
|
|
1933
|
+
],
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
const result1: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding1)
|
|
1937
|
+
const result2: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding2)
|
|
1938
|
+
|
|
1939
|
+
expect(result1.state).toBeDefined()
|
|
1940
|
+
expect(result2.state).toBeDefined()
|
|
1941
|
+
expect(result1.state).not.toEqual(result2.state)
|
|
1942
|
+
expect(result1.localeBranding[0].state).not.toEqual(result2.localeBranding[0].state)
|
|
1943
|
+
})
|
|
1944
|
+
|
|
1945
|
+
it('should keep same state when credential branding content does not change', async (): Promise<void> => {
|
|
1946
|
+
const credentialBranding: IBasicCredentialBranding = {
|
|
1947
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
1948
|
+
vcHash: 'vcHash',
|
|
1949
|
+
localeBranding: [
|
|
1950
|
+
{
|
|
1951
|
+
alias: 'credentialTypeAlias',
|
|
1952
|
+
locale: 'en-US',
|
|
1953
|
+
description: 'Description',
|
|
1954
|
+
},
|
|
1955
|
+
],
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
const original: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding)
|
|
1959
|
+
const originalState: string = original.state
|
|
1960
|
+
const originalLocaleState: string = original.localeBranding[0].state
|
|
1961
|
+
|
|
1962
|
+
const retrieved: Array<ICredentialBranding> = await issuanceBrandingStore.getCredentialBranding({ filter: [{ id: original.id }] })
|
|
1963
|
+
|
|
1964
|
+
expect(retrieved).toBeDefined()
|
|
1965
|
+
expect(retrieved.length).toEqual(1)
|
|
1966
|
+
expect(retrieved[0].state).toEqual(originalState)
|
|
1967
|
+
expect(retrieved[0].localeBranding[0].state).toEqual(originalLocaleState)
|
|
1968
|
+
})
|
|
1969
|
+
|
|
1970
|
+
it('should filter credential branding by knownStates when all states match', async (): Promise<void> => {
|
|
1971
|
+
const credentialBranding: IBasicCredentialBranding = {
|
|
1972
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
1973
|
+
vcHash: 'vcHash',
|
|
1974
|
+
localeBranding: [
|
|
1975
|
+
{
|
|
1976
|
+
alias: 'credentialTypeAlias',
|
|
1977
|
+
locale: 'en-US',
|
|
1978
|
+
},
|
|
1979
|
+
],
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
const saved: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding)
|
|
1983
|
+
const knownStates: Record<string, string> = {
|
|
1984
|
+
[saved.id]: saved.state,
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
const result: Array<ICredentialBranding> = await issuanceBrandingStore.getCredentialBranding({ knownStates })
|
|
1988
|
+
|
|
1989
|
+
expect(result.length).toEqual(0)
|
|
1990
|
+
})
|
|
1991
|
+
|
|
1992
|
+
it('should return credential branding when knownStates differs', async (): Promise<void> => {
|
|
1993
|
+
const credentialBranding: IBasicCredentialBranding = {
|
|
1994
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
1995
|
+
vcHash: 'vcHash',
|
|
1996
|
+
localeBranding: [
|
|
1997
|
+
{
|
|
1998
|
+
alias: 'credentialTypeAlias',
|
|
1999
|
+
locale: 'en-US',
|
|
2000
|
+
},
|
|
2001
|
+
],
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
const saved: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding)
|
|
2005
|
+
const knownStates: Record<string, string> = {
|
|
2006
|
+
[saved.id]: 'differentState',
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
const result: Array<ICredentialBranding> = await issuanceBrandingStore.getCredentialBranding({ knownStates })
|
|
2010
|
+
|
|
2011
|
+
expect(result.length).toEqual(1)
|
|
2012
|
+
expect(result[0].id).toEqual(saved.id)
|
|
2013
|
+
})
|
|
2014
|
+
|
|
2015
|
+
it('should return credential branding when not in knownStates map', async (): Promise<void> => {
|
|
2016
|
+
const credentialBranding: IBasicCredentialBranding = {
|
|
2017
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
2018
|
+
vcHash: 'vcHash',
|
|
2019
|
+
localeBranding: [
|
|
2020
|
+
{
|
|
2021
|
+
alias: 'credentialTypeAlias',
|
|
2022
|
+
locale: 'en-US',
|
|
2023
|
+
},
|
|
2024
|
+
],
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
const saved: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding)
|
|
2028
|
+
const knownStates: Record<string, string> = {}
|
|
2029
|
+
|
|
2030
|
+
const result: Array<ICredentialBranding> = await issuanceBrandingStore.getCredentialBranding({ knownStates })
|
|
2031
|
+
|
|
2032
|
+
expect(result.length).toEqual(1)
|
|
2033
|
+
expect(result[0].id).toEqual(saved.id)
|
|
2034
|
+
})
|
|
2035
|
+
|
|
2036
|
+
it('should filter multiple credential brandings correctly with knownStates', async (): Promise<void> => {
|
|
2037
|
+
const credentialBranding1: IBasicCredentialBranding = {
|
|
2038
|
+
issuerCorrelationId: 'issuerCorrelationId1',
|
|
2039
|
+
vcHash: 'vcHash1',
|
|
2040
|
+
localeBranding: [
|
|
2041
|
+
{
|
|
2042
|
+
alias: 'credentialTypeAlias1',
|
|
2043
|
+
locale: 'en-US',
|
|
2044
|
+
},
|
|
2045
|
+
],
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
const credentialBranding2: IBasicCredentialBranding = {
|
|
2049
|
+
issuerCorrelationId: 'issuerCorrelationId2',
|
|
2050
|
+
vcHash: 'vcHash2',
|
|
2051
|
+
localeBranding: [
|
|
2052
|
+
{
|
|
2053
|
+
alias: 'credentialTypeAlias2',
|
|
2054
|
+
locale: 'en-US',
|
|
2055
|
+
},
|
|
2056
|
+
],
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
const credentialBranding3: IBasicCredentialBranding = {
|
|
2060
|
+
issuerCorrelationId: 'issuerCorrelationId3',
|
|
2061
|
+
vcHash: 'vcHash3',
|
|
2062
|
+
localeBranding: [
|
|
2063
|
+
{
|
|
2064
|
+
alias: 'credentialTypeAlias3',
|
|
2065
|
+
locale: 'en-US',
|
|
2066
|
+
},
|
|
2067
|
+
],
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
const saved1: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding1)
|
|
2071
|
+
const saved2: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding2)
|
|
2072
|
+
const saved3: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding3)
|
|
2073
|
+
|
|
2074
|
+
const knownStates: Record<string, string> = {
|
|
2075
|
+
[saved1.id]: saved1.state,
|
|
2076
|
+
[saved2.id]: 'differentState',
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
const result: Array<ICredentialBranding> = await issuanceBrandingStore.getCredentialBranding({ knownStates })
|
|
2080
|
+
|
|
2081
|
+
expect(result.length).toEqual(2)
|
|
2082
|
+
const resultIds: Array<string> = result.map((r: ICredentialBranding) => r.id)
|
|
2083
|
+
expect(resultIds).toContain(saved2.id)
|
|
2084
|
+
expect(resultIds).toContain(saved3.id)
|
|
2085
|
+
expect(resultIds).not.toContain(saved1.id)
|
|
2086
|
+
})
|
|
2087
|
+
|
|
2088
|
+
it('should add new locale branding with state field populated', async (): Promise<void> => {
|
|
2089
|
+
const credentialBranding: IBasicCredentialBranding = {
|
|
2090
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
2091
|
+
vcHash: 'vcHash',
|
|
2092
|
+
localeBranding: [
|
|
2093
|
+
{
|
|
2094
|
+
alias: 'credentialTypeAlias',
|
|
2095
|
+
locale: 'en-US',
|
|
2096
|
+
},
|
|
2097
|
+
],
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
const saved: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding)
|
|
2101
|
+
|
|
2102
|
+
const addLocaleBrandingArgs: IAddCredentialLocaleBrandingArgs = {
|
|
2103
|
+
credentialBrandingId: saved.id,
|
|
2104
|
+
localeBranding: [
|
|
2105
|
+
{
|
|
2106
|
+
alias: 'credentialTypeAlias',
|
|
2107
|
+
locale: 'en-GB',
|
|
2108
|
+
},
|
|
2109
|
+
],
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
const result: ICredentialBranding = await issuanceBrandingStore.addCredentialLocaleBranding(addLocaleBrandingArgs)
|
|
2113
|
+
|
|
2114
|
+
expect(result.localeBranding.length).toEqual(2)
|
|
2115
|
+
expect(result.localeBranding[0].state).toBeDefined()
|
|
2116
|
+
expect(result.localeBranding[1].state).toBeDefined()
|
|
2117
|
+
expect(result.localeBranding[0].state).not.toEqual(result.localeBranding[1].state)
|
|
2118
|
+
})
|
|
2119
|
+
|
|
2120
|
+
it('should compute state based on locale branding claims', async (): Promise<void> => {
|
|
2121
|
+
const credentialBranding1: IBasicCredentialBranding = {
|
|
2122
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
2123
|
+
vcHash: 'vcHash1',
|
|
2124
|
+
localeBranding: [
|
|
2125
|
+
{
|
|
2126
|
+
alias: 'credentialTypeAlias',
|
|
2127
|
+
locale: 'en-US',
|
|
2128
|
+
claims: [
|
|
2129
|
+
{
|
|
2130
|
+
key: 'name',
|
|
2131
|
+
name: 'Full Name',
|
|
2132
|
+
},
|
|
2133
|
+
],
|
|
2134
|
+
},
|
|
2135
|
+
],
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
const credentialBranding2: IBasicCredentialBranding = {
|
|
2139
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
2140
|
+
vcHash: 'vcHash2',
|
|
2141
|
+
localeBranding: [
|
|
2142
|
+
{
|
|
2143
|
+
alias: 'credentialTypeAlias',
|
|
2144
|
+
locale: 'en-US',
|
|
2145
|
+
claims: [
|
|
2146
|
+
{
|
|
2147
|
+
key: 'email',
|
|
2148
|
+
name: 'Email Address',
|
|
2149
|
+
},
|
|
2150
|
+
],
|
|
2151
|
+
},
|
|
2152
|
+
],
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
const saved1: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding1)
|
|
2156
|
+
const saved2: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding2)
|
|
2157
|
+
|
|
2158
|
+
expect(saved1.localeBranding[0].state).toBeDefined()
|
|
2159
|
+
expect(saved2.localeBranding[0].state).toBeDefined()
|
|
2160
|
+
expect(saved1.localeBranding[0].state).not.toEqual(saved2.localeBranding[0].state)
|
|
2161
|
+
})
|
|
2162
|
+
|
|
2163
|
+
it('should compute deterministic state for same content', async (): Promise<void> => {
|
|
2164
|
+
const credentialBranding1: IBasicCredentialBranding = {
|
|
2165
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
2166
|
+
vcHash: 'vcHash',
|
|
2167
|
+
localeBranding: [
|
|
2168
|
+
{
|
|
2169
|
+
alias: 'credentialTypeAlias',
|
|
2170
|
+
locale: 'en-US',
|
|
2171
|
+
description: 'Test description',
|
|
2172
|
+
},
|
|
2173
|
+
],
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
const saved1: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding1)
|
|
2177
|
+
|
|
2178
|
+
await issuanceBrandingStore.removeCredentialBranding({ filter: [{ id: saved1.id }] })
|
|
2179
|
+
|
|
2180
|
+
const credentialBranding2: IBasicCredentialBranding = {
|
|
2181
|
+
issuerCorrelationId: 'issuerCorrelationId',
|
|
2182
|
+
vcHash: 'vcHash',
|
|
2183
|
+
localeBranding: [
|
|
2184
|
+
{
|
|
2185
|
+
alias: 'credentialTypeAlias',
|
|
2186
|
+
locale: 'en-US',
|
|
2187
|
+
description: 'Test description',
|
|
2188
|
+
},
|
|
2189
|
+
],
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
const saved2: ICredentialBranding = await issuanceBrandingStore.addCredentialBranding(credentialBranding2)
|
|
2193
|
+
|
|
2194
|
+
expect(saved1.state).toEqual(saved2.state)
|
|
2195
|
+
expect(saved1.localeBranding[0].state).toEqual(saved2.localeBranding[0].state)
|
|
2196
|
+
})
|
|
1887
2197
|
})
|
|
@@ -111,7 +111,16 @@ export class ContactStore extends AbstractContactStore {
|
|
|
111
111
|
// Fetch the complete entities based on the initial result IDs
|
|
112
112
|
const result = await partyRepository.find({ where: { id: In(initialResult.map((party) => party.id)) } })
|
|
113
113
|
debug(`getParties() resulted in ${result.length} parties`)
|
|
114
|
-
return result
|
|
114
|
+
return result
|
|
115
|
+
.filter((party) => {
|
|
116
|
+
// Do not crash fetching the entire contacts list over one missing contact relation
|
|
117
|
+
if (!party.contact) {
|
|
118
|
+
console.warn(`party ${party.id} does not have an associated contact`)
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
return true
|
|
122
|
+
})
|
|
123
|
+
.map(partyFrom)
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
addParty = async (args: AddPartyArgs): Promise<Party> => {
|
|
@@ -44,7 +44,7 @@ export class DigitalCredentialStore extends AbstractDigitalCredentialStore {
|
|
|
44
44
|
return Promise.reject(validationError)
|
|
45
45
|
}
|
|
46
46
|
const dcRepo = await this.getRepository()
|
|
47
|
-
const createdResult: DigitalCredentialEntity = await dcRepo.save(credentialEntity
|
|
47
|
+
const createdResult: DigitalCredentialEntity = await dcRepo.save(credentialEntity)
|
|
48
48
|
return Promise.resolve(digitalCredentialFrom(createdResult))
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -79,10 +79,10 @@ export class DigitalCredentialEntity extends BaseEntity implements DigitalCreden
|
|
|
79
79
|
@Column('text', { name: 'linked_vp_id', nullable: true })
|
|
80
80
|
linkedVpId?: string
|
|
81
81
|
|
|
82
|
-
@
|
|
82
|
+
@Column({ name: 'linked_vp_from', nullable: true, type: typeOrmDateTime() })
|
|
83
83
|
linkedVpFrom?: Date
|
|
84
84
|
|
|
85
|
-
@
|
|
85
|
+
@Column({ name: 'linked_vp_until', nullable: true, type: typeOrmDateTime() })
|
|
86
86
|
linkedVpUntil?: Date
|
|
87
87
|
|
|
88
88
|
@CreateDateColumn({ name: 'created_at', nullable: false, type: typeOrmDateTime() })
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
PrimaryGeneratedColumn,
|
|
13
13
|
UpdateDateColumn,
|
|
14
14
|
} from 'typeorm'
|
|
15
|
-
import { CredentialLocaleBrandingEntity } from './CredentialLocaleBrandingEntity'
|
|
15
|
+
import { CredentialLocaleBrandingEntity, computeCredentialLocaleBrandingState } from './CredentialLocaleBrandingEntity'
|
|
16
|
+
import { computeCompactHash } from '../../utils/issuanceBranding/HashUtils'
|
|
16
17
|
|
|
17
18
|
@Entity('CredentialBranding')
|
|
18
19
|
@Index('IDX_CredentialBrandingEntity_vcHash', ['vcHash'])
|
|
@@ -29,6 +30,9 @@ export class CredentialBrandingEntity extends BaseEntity {
|
|
|
29
30
|
@IsNotEmpty({ message: 'Blank issuerCorrelationIds are not allowed' })
|
|
30
31
|
issuerCorrelationId!: string
|
|
31
32
|
|
|
33
|
+
@Column('varchar', { name: 'state', length: 255, nullable: false })
|
|
34
|
+
state!: string
|
|
35
|
+
|
|
32
36
|
@OneToMany(
|
|
33
37
|
() => CredentialLocaleBrandingEntity,
|
|
34
38
|
(credentialLocaleBrandingEntity: CredentialLocaleBrandingEntity) => credentialLocaleBrandingEntity.credentialBranding,
|
|
@@ -55,6 +59,12 @@ export class CredentialBrandingEntity extends BaseEntity {
|
|
|
55
59
|
this.lastUpdatedAt = new Date()
|
|
56
60
|
}
|
|
57
61
|
|
|
62
|
+
@BeforeInsert()
|
|
63
|
+
@BeforeUpdate()
|
|
64
|
+
setState(): void {
|
|
65
|
+
this.state = this.computeState()
|
|
66
|
+
}
|
|
67
|
+
|
|
58
68
|
@BeforeInsert()
|
|
59
69
|
@BeforeUpdate()
|
|
60
70
|
async validate(): Promise<undefined> {
|
|
@@ -64,4 +74,35 @@ export class CredentialBrandingEntity extends BaseEntity {
|
|
|
64
74
|
}
|
|
65
75
|
return
|
|
66
76
|
}
|
|
77
|
+
|
|
78
|
+
private computeState(): string {
|
|
79
|
+
const localeStates: Array<{ locale: string; alias: string; id: string; state: string }> = (this.localeBranding ?? []).map(
|
|
80
|
+
(localeBranding: CredentialLocaleBrandingEntity) => ({
|
|
81
|
+
locale: localeBranding.locale ?? '',
|
|
82
|
+
alias: localeBranding.alias ?? '',
|
|
83
|
+
id: localeBranding.id ?? '',
|
|
84
|
+
state: computeCredentialLocaleBrandingState(localeBranding),
|
|
85
|
+
}),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
localeStates.sort((first, second) => {
|
|
89
|
+
const localeCompare: number = first.locale.localeCompare(second.locale)
|
|
90
|
+
if (localeCompare !== 0) {
|
|
91
|
+
return localeCompare
|
|
92
|
+
}
|
|
93
|
+
const aliasCompare: number = first.alias.localeCompare(second.alias)
|
|
94
|
+
if (aliasCompare !== 0) {
|
|
95
|
+
return aliasCompare
|
|
96
|
+
}
|
|
97
|
+
return first.id.localeCompare(second.id)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const payload = {
|
|
101
|
+
issuerCorrelationId: this.issuerCorrelationId,
|
|
102
|
+
vcHash: this.vcHash,
|
|
103
|
+
localeBranding: localeStates.map((entry) => entry.state),
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return computeCompactHash(JSON.stringify(payload))
|
|
107
|
+
}
|
|
67
108
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ChildEntity, Column, Index, JoinColumn, ManyToOne, OneToMany } from 'typeorm'
|
|
1
|
+
import { BeforeInsert, BeforeUpdate, ChildEntity, Column, Index, JoinColumn, ManyToOne, OneToMany } from 'typeorm'
|
|
2
|
+
import { computeCompactHash } from '../../utils/issuanceBranding/HashUtils'
|
|
2
3
|
import { BaseLocaleBrandingEntity } from './BaseLocaleBrandingEntity'
|
|
3
4
|
import { CredentialBrandingEntity } from './CredentialBrandingEntity'
|
|
4
5
|
import { CredentialClaimsEntity } from './CredentialClaimsEntity'
|
|
@@ -23,4 +24,66 @@ export class CredentialLocaleBrandingEntity extends BaseLocaleBrandingEntity {
|
|
|
23
24
|
|
|
24
25
|
@Column('uuid', { name: 'credentialBrandingId', nullable: false })
|
|
25
26
|
credentialBrandingId!: string
|
|
27
|
+
|
|
28
|
+
@Column('varchar', { name: 'state', length: 255, nullable: false })
|
|
29
|
+
state!: string
|
|
30
|
+
|
|
31
|
+
@BeforeInsert()
|
|
32
|
+
@BeforeUpdate()
|
|
33
|
+
setState(): void {
|
|
34
|
+
this.state = computeCredentialLocaleBrandingState(this)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const computeCredentialLocaleBrandingState = (localeBranding: CredentialLocaleBrandingEntity): string => {
|
|
39
|
+
const sortedClaims: Array<{ key: string; name: string }> = (localeBranding.claims ?? [])
|
|
40
|
+
.map((claim: CredentialClaimsEntity) => ({ key: claim.key, name: claim.name }))
|
|
41
|
+
.sort((first: { key: string }, second: { key: string }) => first.key.localeCompare(second.key))
|
|
42
|
+
|
|
43
|
+
const payload = {
|
|
44
|
+
alias: localeBranding.alias ?? null,
|
|
45
|
+
locale: localeBranding.locale ?? null,
|
|
46
|
+
description: localeBranding.description ?? null,
|
|
47
|
+
logo: localeBranding.logo
|
|
48
|
+
? {
|
|
49
|
+
uri: localeBranding.logo.uri ?? null,
|
|
50
|
+
dataUri: localeBranding.logo.dataUri ?? null,
|
|
51
|
+
mediaType: localeBranding.logo.mediaType ?? null,
|
|
52
|
+
alt: localeBranding.logo.alt ?? null,
|
|
53
|
+
dimensions: localeBranding.logo.dimensions
|
|
54
|
+
? {
|
|
55
|
+
width: localeBranding.logo.dimensions.width,
|
|
56
|
+
height: localeBranding.logo.dimensions.height,
|
|
57
|
+
}
|
|
58
|
+
: null,
|
|
59
|
+
}
|
|
60
|
+
: null,
|
|
61
|
+
background: localeBranding.background
|
|
62
|
+
? {
|
|
63
|
+
color: localeBranding.background.color ?? null,
|
|
64
|
+
image: localeBranding.background.image
|
|
65
|
+
? {
|
|
66
|
+
uri: localeBranding.background.image.uri ?? null,
|
|
67
|
+
dataUri: localeBranding.background.image.dataUri ?? null,
|
|
68
|
+
mediaType: localeBranding.background.image.mediaType ?? null,
|
|
69
|
+
alt: localeBranding.background.image.alt ?? null,
|
|
70
|
+
dimensions: localeBranding.background.image.dimensions
|
|
71
|
+
? {
|
|
72
|
+
width: localeBranding.background.image.dimensions.width,
|
|
73
|
+
height: localeBranding.background.image.dimensions.height,
|
|
74
|
+
}
|
|
75
|
+
: null,
|
|
76
|
+
}
|
|
77
|
+
: null,
|
|
78
|
+
}
|
|
79
|
+
: null,
|
|
80
|
+
text: localeBranding.text
|
|
81
|
+
? {
|
|
82
|
+
color: localeBranding.text.color ?? null,
|
|
83
|
+
}
|
|
84
|
+
: null,
|
|
85
|
+
claims: sortedClaims,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return computeCompactHash(JSON.stringify(payload))
|
|
26
89
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Validate } from 'class-validator'
|
|
2
|
-
import { ChildEntity, Column, Index, JoinColumn, ManyToOne } from 'typeorm'
|
|
2
|
+
import { BeforeInsert, BeforeUpdate, ChildEntity, Column, Index, JoinColumn, ManyToOne } from 'typeorm'
|
|
3
|
+
import { computeCompactHash } from '../../utils/issuanceBranding/HashUtils'
|
|
3
4
|
import { IsNonEmptyStringConstraint } from '../validators'
|
|
4
5
|
import { BaseLocaleBrandingEntity } from './BaseLocaleBrandingEntity'
|
|
5
6
|
import { IssuerBrandingEntity } from './IssuerBrandingEntity'
|
|
@@ -30,4 +31,65 @@ export class IssuerLocaleBrandingEntity extends BaseLocaleBrandingEntity {
|
|
|
30
31
|
|
|
31
32
|
@Column('text', { name: 'issuerBrandingId', nullable: false })
|
|
32
33
|
issuerBrandingId!: string
|
|
34
|
+
|
|
35
|
+
@Column('varchar', { name: 'state', length: 255, nullable: false })
|
|
36
|
+
state!: string
|
|
37
|
+
|
|
38
|
+
@BeforeInsert()
|
|
39
|
+
@BeforeUpdate()
|
|
40
|
+
setState(): void {
|
|
41
|
+
this.state = this.computeState()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private computeState(): string {
|
|
45
|
+
const payload = {
|
|
46
|
+
alias: this.alias ?? null,
|
|
47
|
+
locale: this.locale ?? null,
|
|
48
|
+
description: this.description ?? null,
|
|
49
|
+
clientUri: this.clientUri ?? null,
|
|
50
|
+
tosUri: this.tosUri ?? null,
|
|
51
|
+
policyUri: this.policyUri ?? null,
|
|
52
|
+
contacts: this.contacts ?? null,
|
|
53
|
+
logo: this.logo
|
|
54
|
+
? {
|
|
55
|
+
uri: this.logo.uri ?? null,
|
|
56
|
+
dataUri: this.logo.dataUri ?? null,
|
|
57
|
+
mediaType: this.logo.mediaType ?? null,
|
|
58
|
+
alt: this.logo.alt ?? null,
|
|
59
|
+
dimensions: this.logo.dimensions
|
|
60
|
+
? {
|
|
61
|
+
width: this.logo.dimensions.width,
|
|
62
|
+
height: this.logo.dimensions.height,
|
|
63
|
+
}
|
|
64
|
+
: null,
|
|
65
|
+
}
|
|
66
|
+
: null,
|
|
67
|
+
background: this.background
|
|
68
|
+
? {
|
|
69
|
+
color: this.background.color ?? null,
|
|
70
|
+
image: this.background.image
|
|
71
|
+
? {
|
|
72
|
+
uri: this.background.image.uri ?? null,
|
|
73
|
+
dataUri: this.background.image.dataUri ?? null,
|
|
74
|
+
mediaType: this.background.image.mediaType ?? null,
|
|
75
|
+
alt: this.background.image.alt ?? null,
|
|
76
|
+
dimensions: this.background.image.dimensions
|
|
77
|
+
? {
|
|
78
|
+
width: this.background.image.dimensions.width,
|
|
79
|
+
height: this.background.image.dimensions.height,
|
|
80
|
+
}
|
|
81
|
+
: null,
|
|
82
|
+
}
|
|
83
|
+
: null,
|
|
84
|
+
}
|
|
85
|
+
: null,
|
|
86
|
+
text: this.text
|
|
87
|
+
? {
|
|
88
|
+
color: this.text.color ?? null,
|
|
89
|
+
}
|
|
90
|
+
: null,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return computeCompactHash(JSON.stringify(payload))
|
|
94
|
+
}
|
|
33
95
|
}
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
credentialBrandingEntityFrom,
|
|
45
45
|
credentialBrandingFrom,
|
|
46
46
|
credentialLocaleBrandingEntityFrom,
|
|
47
|
+
credentialLocaleBrandingFromEntity,
|
|
47
48
|
issuerBrandingEntityFrom,
|
|
48
49
|
issuerBrandingFrom,
|
|
49
50
|
issuerLocaleBrandingEntityFrom,
|
|
@@ -83,7 +84,7 @@ export class IssuanceBrandingStore extends AbstractIssuanceBrandingStore {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
public getCredentialBranding = async (args?: IGetCredentialBrandingArgs): Promise<Array<ICredentialBranding>> => {
|
|
86
|
-
const { filter } = args ?? {}
|
|
87
|
+
const { filter, knownStates } = args ?? {}
|
|
87
88
|
if (filter) {
|
|
88
89
|
filter.forEach((filter: IPartialCredentialBranding): void => {
|
|
89
90
|
if (filter.localeBranding && 'locale' in filter.localeBranding && filter.localeBranding.locale === undefined) {
|
|
@@ -97,7 +98,16 @@ export class IssuanceBrandingStore extends AbstractIssuanceBrandingStore {
|
|
|
97
98
|
...(filter && { where: filter }),
|
|
98
99
|
})
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
const credentialBranding: Array<ICredentialBranding> = result.map((branding: CredentialBrandingEntity) => credentialBrandingFrom(branding))
|
|
102
|
+
|
|
103
|
+
if (!knownStates) {
|
|
104
|
+
return credentialBranding
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return credentialBranding.filter((branding: ICredentialBranding) => {
|
|
108
|
+
const knownState: string | undefined = knownStates[branding.id]
|
|
109
|
+
return !knownState || knownState !== branding.state
|
|
110
|
+
})
|
|
101
111
|
}
|
|
102
112
|
|
|
103
113
|
public removeCredentialBranding = async (args: IRemoveCredentialBrandingArgs): Promise<void> => {
|
|
@@ -133,7 +143,7 @@ export class IssuanceBrandingStore extends AbstractIssuanceBrandingStore {
|
|
|
133
143
|
return Promise.reject(Error(`No credential branding found for id: ${credentialBranding.id}`))
|
|
134
144
|
}
|
|
135
145
|
|
|
136
|
-
const branding: Omit<ICredentialBranding, 'createdAt' | 'lastUpdatedAt'> = {
|
|
146
|
+
const branding: Omit<ICredentialBranding, 'createdAt' | 'lastUpdatedAt' | 'state'> = {
|
|
137
147
|
...credentialBranding,
|
|
138
148
|
localeBranding: credentialBrandingEntity.localeBranding,
|
|
139
149
|
}
|
|
@@ -218,7 +228,8 @@ export class IssuanceBrandingStore extends AbstractIssuanceBrandingStore {
|
|
|
218
228
|
|
|
219
229
|
return credentialBrandingLocale
|
|
220
230
|
? credentialBrandingLocale.map(
|
|
221
|
-
(credentialLocaleBranding: CredentialLocaleBrandingEntity) =>
|
|
231
|
+
(credentialLocaleBranding: CredentialLocaleBrandingEntity) =>
|
|
232
|
+
credentialLocaleBrandingFromEntity(credentialLocaleBranding) as ICredentialLocaleBranding,
|
|
222
233
|
)
|
|
223
234
|
: []
|
|
224
235
|
}
|
|
@@ -342,7 +353,7 @@ export class IssuanceBrandingStore extends AbstractIssuanceBrandingStore {
|
|
|
342
353
|
return Promise.reject(Error(`No issuer branding found for id: ${issuerBranding.id}`))
|
|
343
354
|
}
|
|
344
355
|
|
|
345
|
-
const branding: Omit<IIssuerBranding, 'createdAt' | 'lastUpdatedAt'> = {
|
|
356
|
+
const branding: Omit<IIssuerBranding, 'createdAt' | 'lastUpdatedAt' | 'state'> = {
|
|
346
357
|
...issuerBranding,
|
|
347
358
|
localeBranding: issuerBrandingEntity.localeBranding,
|
|
348
359
|
}
|