Skip to content

Commit 93b053a

Browse files
committed
fix search
1 parent 74d0fe9 commit 93b053a

File tree

2 files changed

+183
-36
lines changed

2 files changed

+183
-36
lines changed

src/storage/filters/jsonQuery.ts

+36-36
Original file line numberDiff line numberDiff line change
@@ -84,48 +84,28 @@ const greaterThan = (
8484
a: ComparableType | ComparableType[],
8585
b: ComparableType | ComparableType[]
8686
) => {
87-
if (Array.isArray(a) && Array.isArray(b)) {
88-
return a.every((val, index) => val > (b as ComparableType[])[index]);
89-
}
90-
if (!Array.isArray(a) && Array.isArray(b)) {
91-
return b.every((val) => a > val);
92-
}
93-
if (Array.isArray(a) && !Array.isArray(b)) {
94-
return a.every((val) => val > b);
95-
}
96-
return a > b;
87+
const predicate = (a: ComparableType, b: ComparableType) => {
88+
if (isNumeric(a.toString()) && isNumeric(b.toString())) {
89+
return BigInt(a) > BigInt(b);
90+
}
91+
return a > b;
92+
};
93+
94+
return operatorIndependentCheck(a, b, predicate);
9795
};
9896

9997
const greaterThanOrEqual = (
10098
a: ComparableType | ComparableType[],
10199
b: ComparableType | ComparableType[]
102100
) => {
103-
if (Array.isArray(a) && Array.isArray(b)) {
104-
return a.every((val, index) => val >= (b as ComparableType[])[index]);
105-
}
106-
if (!Array.isArray(a) && Array.isArray(b)) {
107-
return b.every((val) => a >= val);
108-
}
109-
if (Array.isArray(a) && !Array.isArray(b)) {
110-
return a.every((val) => val >= b);
111-
}
112-
return a >= b;
113-
};
101+
const predicate = (a: ComparableType, b: ComparableType) => {
102+
if (isNumeric(a.toString()) && isNumeric(b.toString())) {
103+
return BigInt(a) >= BigInt(b);
104+
}
105+
return a >= b;
106+
};
114107

115-
const lessThanOrEqual = (
116-
a: ComparableType | ComparableType[],
117-
b: ComparableType | ComparableType[]
118-
) => {
119-
if (Array.isArray(a) && Array.isArray(b)) {
120-
return a.every((val, index) => val <= (b as ComparableType[])[index]);
121-
}
122-
if (!Array.isArray(a) && Array.isArray(b)) {
123-
return b.every((val) => a <= val);
124-
}
125-
if (Array.isArray(a) && !Array.isArray(b)) {
126-
return a.every((val) => val <= b);
127-
}
128-
return a <= b;
108+
return operatorIndependentCheck(a, b, predicate);
129109
};
130110

131111
// a - field value
@@ -190,7 +170,7 @@ export const comparatorOptions: { [v in FilterOperatorMethod]: FilterOperatorFun
190170
$gte: (a: ComparableType | ComparableType[], b: ComparableType | ComparableType[]) =>
191171
greaterThanOrEqual(a, b),
192172
$lte: (a: ComparableType | ComparableType[], b: ComparableType | ComparableType[]) =>
193-
lessThanOrEqual(a, b),
173+
!greaterThan(a, b),
194174
$between: (a: ComparableType | ComparableType[], b: ComparableType | ComparableType[]) =>
195175
betweenOperator(a, b),
196176
$nonbetween: (a: ComparableType | ComparableType[], b: ComparableType | ComparableType[]) =>
@@ -320,3 +300,23 @@ export const StandardJSONCredentialsQueryFilter = (query: ProofQuery): FilterQue
320300
}
321301
}, []);
322302
};
303+
304+
const operatorIndependentCheck = (
305+
a: ComparableType | ComparableType[],
306+
b: ComparableType | ComparableType[],
307+
predicate: (a: ComparableType, b: ComparableType) => boolean
308+
) => {
309+
if (Array.isArray(a) && Array.isArray(b)) {
310+
return a.every((val, index) => predicate(val, (b as ComparableType[])[index]));
311+
}
312+
if (!Array.isArray(a) && Array.isArray(b)) {
313+
return b.every((val) => predicate(a, val));
314+
}
315+
if (Array.isArray(a) && !Array.isArray(b)) {
316+
return a.every((val) => predicate(val, b));
317+
}
318+
// in this case a and b are not arrays
319+
return predicate(a as ComparableType, b as ComparableType);
320+
};
321+
322+
const isNumeric = (s: string) => /^[+-]?\d+(\.\d+)?$/.test(s);

tests/credentials/credential-wallet.test.ts

+147
Original file line numberDiff line numberDiff line change
@@ -464,4 +464,151 @@ describe('credential-wallet', () => {
464464
mockedProof.issuerData.state.claimsTreeRoot.bigInt().toString()
465465
);
466466
});
467+
468+
it('Credential search by query', async () => {
469+
const credentialStorage = new CredentialStorage(new InMemoryDataSource<W3CCredential>());
470+
471+
const credToTest = W3CCredential.fromJSON(
472+
JSON.parse(`{
473+
"id": "urn:uuid:9c421fdc-16cc-11f0-9a77-0a58a9feac02",
474+
"@context": [
475+
"https://www.w3.org/2018/credentials/v1",
476+
"https://schema.iden3.io/core/jsonld/iden3proofs.jsonld",
477+
"ipfs://Qmb48rJ5SiQMLXjVkaLQB6fWbT7C8LK75MHsCoHv8GAc15"
478+
],
479+
"type": [
480+
"VerifiableCredential",
481+
"operators"
482+
],
483+
"credentialSubject": {
484+
"boolean1": true,
485+
"date-time1": "2025-04-09T15:48:08.800+02:00",
486+
"id": "did:iden3:privado:main:2SeEkMwamyzKWr3aGUT9AvDjiQK4rMEAZbUZgEzP72",
487+
"integer1": 5342,
488+
"non-negative-integer1": "32423",
489+
"number1": 1234,
490+
"positive-integer1": "12345555",
491+
"string1": "testData",
492+
"type": "operators"
493+
},
494+
"issuer": "did:iden3:polygon:amoy:xJNwv94NrHy1xXU3poKTRL24WJEXmkEggwbBWy6gu",
495+
"credentialSchema": {
496+
"id": "https://ipfs.io/ipfs/QmWDmZQrtvidcNK7d6rJwq7ZSi8SUygJaKepN7NhKtGryc",
497+
"type": "JsonSchema2023"
498+
},
499+
"credentialStatus": {
500+
"id": "https://issuer-node-core-api-testing.privado.id/v2/agent",
501+
"revocationNonce": 978385127,
502+
"type": "Iden3commRevocationStatusV1.0"
503+
},
504+
"issuanceDate": "2025-04-11T12:00:49.921271223Z",
505+
"proof": [
506+
{
507+
"issuerData": {
508+
"id": "did:iden3:polygon:amoy:xJNwv94NrHy1xXU3poKTRL24WJEXmkEggwbBWy6gu",
509+
"state": {
510+
"claimsTreeRoot": "1483789a545832ba69d54ed1691ce758f9b8297542b2749f6fa4786e74fbe80e",
511+
"value": "310ccc3f33fbbfd50da56755e442896065b388e9c4adadd644588eaa6e171b1a",
512+
"rootOfRoots": "0000000000000000000000000000000000000000000000000000000000000000",
513+
"revocationTreeRoot": "0000000000000000000000000000000000000000000000000000000000000000"
514+
},
515+
"mtp": {
516+
"existence": true,
517+
"siblings": []
518+
},
519+
"authCoreClaim": "cca3371a6cb1b715004407e325bd993c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000079adcc5f988e5e6fb7d04adcb5e07afdd53babf34acdb75aa51ac8e1ddc0ee20211c823ff2b1ee62e988fba84247930add22fbbc2fcc4f1b4fd3a50e07f9e6170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
520+
"credentialStatus": {
521+
"id": "https://issuer-node-core-api-testing.privado.id/v2/agent",
522+
"revocationNonce": 0,
523+
"type": "Iden3commRevocationStatusV1.0"
524+
}
525+
},
526+
"type": "BJJSignature2021",
527+
"coreClaim": "637056ad190ec7df5fef1345fda35e1f2200000000000000000000000000000001a16e78ba913717bc15cbe326e236c7eef4f9201582b50e145cb669139c0d0068fbed6c1ddf63a9a4eaa0d4a577b770a5acaf37a542cf86cb6e9e93e9b608020000000000000000000000000000000000000000000000000000000000000000e7f8503a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
528+
"signature": "b17ca01ab223b6281e0b22b4f8945729ffb39eaf4b2a0db59548db7ab0df092e423dfc2472cce2e269a80a4d37bb520eda59ab3a0adfae043caa38a464869505"
529+
}
530+
]
531+
}`)
532+
);
533+
await credentialStorage.saveCredential(credToTest);
534+
535+
// positive-integer
536+
537+
let cred = await credentialStorage.findCredentialsByQuery({
538+
allowedIssuers: ['*'],
539+
context: 'ipfs://Qmb48rJ5SiQMLXjVkaLQB6fWbT7C8LK75MHsCoHv8GAc15',
540+
credentialSubject: {
541+
'positive-integer1': {
542+
$gt: '2'
543+
}
544+
},
545+
groupId: 1745320529,
546+
type: 'operators'
547+
});
548+
expect(1).to.be.equal(cred.length);
549+
expect(cred[0].credentialSubject['positive-integer1']).to.be.equal('12345555');
550+
551+
//number
552+
553+
cred = await credentialStorage.findCredentialsByQuery({
554+
allowedIssuers: ['*'],
555+
context: 'ipfs://Qmb48rJ5SiQMLXjVkaLQB6fWbT7C8LK75MHsCoHv8GAc15',
556+
credentialSubject: {
557+
number1: {
558+
$gt: 1
559+
}
560+
},
561+
groupId: 1745320529,
562+
type: 'operators'
563+
});
564+
expect(1).to.be.equal(cred.length);
565+
expect(cred[0].credentialSubject['number1']).to.be.equal(1234);
566+
567+
//boolean
568+
569+
cred = await credentialStorage.findCredentialsByQuery({
570+
allowedIssuers: ['*'],
571+
context: 'ipfs://Qmb48rJ5SiQMLXjVkaLQB6fWbT7C8LK75MHsCoHv8GAc15',
572+
credentialSubject: {
573+
boolean1: {
574+
$eq: true
575+
}
576+
},
577+
groupId: 1745320529,
578+
type: 'operators'
579+
});
580+
expect(1).to.be.equal(cred.length);
581+
expect(cred[0].credentialSubject['boolean1']).to.be.equal(true);
582+
583+
//datetime lt
584+
585+
cred = await credentialStorage.findCredentialsByQuery({
586+
allowedIssuers: ['*'],
587+
context: 'ipfs://Qmb48rJ5SiQMLXjVkaLQB6fWbT7C8LK75MHsCoHv8GAc15',
588+
credentialSubject: {
589+
'date-time1': {
590+
$lt: '2027-04-09T15:48:08.800+02:00'
591+
}
592+
},
593+
groupId: 1745320529,
594+
type: 'operators'
595+
});
596+
expect(1).to.be.equal(cred.length);
597+
expect(cred[0].credentialSubject['date-time1']).to.be.equal('2025-04-09T15:48:08.800+02:00');
598+
599+
// datetime gt
600+
cred = await credentialStorage.findCredentialsByQuery({
601+
allowedIssuers: ['*'],
602+
context: 'ipfs://Qmb48rJ5SiQMLXjVkaLQB6fWbT7C8LK75MHsCoHv8GAc15',
603+
credentialSubject: {
604+
'date-time1': {
605+
$gt: '2022-04-09T15:48:08.800+02:00'
606+
}
607+
},
608+
groupId: 1745320529,
609+
type: 'operators'
610+
});
611+
expect(1).to.be.equal(cred.length);
612+
expect(cred[0].credentialSubject['date-time1']).to.be.equal('2025-04-09T15:48:08.800+02:00');
613+
});
467614
});

0 commit comments

Comments
 (0)