Skip to content

Commit 4136d96

Browse files
authored
Merge pull request #873 from oceanprotocol/issue-871-checkCredentials-accessList
add support for accessList on download checkCredentials
2 parents 263bf4a + 329fb95 commit 4136d96

4 files changed

Lines changed: 63 additions & 31 deletions

File tree

src/components/core/handler/downloadHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ export class DownloadHandler extends Handler {
292292
).success
293293
} else {
294294
accessGrantedDDOLevel = areKnownCredentialTypes(ddo.credentials)
295-
? checkCredentials(ddo.credentials, task.consumerAddress, ddo.chainId)
295+
? await checkCredentials(ddo.credentials, task.consumerAddress, ddo.chainId)
296296
: true
297297
}
298298
if (!accessGrantedDDOLevel) {
@@ -397,7 +397,7 @@ export class DownloadHandler extends Handler {
397397
).success)
398398
} else {
399399
accessGrantedServiceLevel = areKnownCredentialTypes(service.credentials)
400-
? checkCredentials(service.credentials, task.consumerAddress, chainId)
400+
? await checkCredentials(service.credentials, task.consumerAddress, chainId)
401401
: true
402402
}
403403

src/test/unit/credentials.test.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,26 @@ describe('credentials', () => {
2929
envOverrides = await setupEnvironment(null, envOverrides)
3030
})
3131

32-
it('should deny access with undefined or empty credentials', () => {
32+
it('should deny access with undefined or empty credentials', async () => {
3333
const credentialsUndefined: Credentials = undefined
3434
const consumerAddress = '0x123'
35-
const accessGranted1 = checkCredentials(credentialsUndefined, consumerAddress)
35+
const accessGranted1 = await checkCredentials(credentialsUndefined, consumerAddress)
3636
expect(accessGranted1).to.equal(false)
3737
const credentialsEmapty = {} as Credentials
38-
const accessGranted2 = checkCredentials(credentialsEmapty, consumerAddress)
38+
const accessGranted2 = await checkCredentials(credentialsEmapty, consumerAddress)
3939
expect(accessGranted2).to.equal(false)
4040
})
41-
it('should deny access with empty allow and deny lists', () => {
41+
it('should deny access with empty allow and deny lists', async () => {
4242
// if list does not exist or is empty access is denied
4343
const credentials: Credentials = {
4444
allow: [],
4545
deny: []
4646
}
4747
const consumerAddress = '0x123'
48-
const accessGranted = checkCredentials(credentials, consumerAddress)
48+
const accessGranted = await checkCredentials(credentials, consumerAddress)
4949
expect(accessGranted).to.equal(false)
5050
})
51-
it('should deny access with empty values in deny lists', () => {
51+
it('should deny access with empty values in deny lists', async () => {
5252
const credentials: Credentials = {
5353
deny: [
5454
{
@@ -58,11 +58,11 @@ describe('credentials', () => {
5858
]
5959
}
6060
const consumerAddress = '0x123'
61-
const accessGranted = checkCredentials(credentials, consumerAddress)
61+
const accessGranted = await checkCredentials(credentials, consumerAddress)
6262
expect(accessGranted).to.equal(false)
6363
})
6464

65-
it('should deny access with "accessList" credentials (default behaviour if cannot check)', () => {
65+
it('should deny access with "accessList" credentials (default behaviour if cannot check)', async () => {
6666
const consumerAddress = '0x123'
6767
const credentials: Credentials = {
6868
deny: [
@@ -73,11 +73,11 @@ describe('credentials', () => {
7373
]
7474
}
7575

76-
const accessGranted = checkCredentials(credentials, consumerAddress)
76+
const accessGranted = await checkCredentials(credentials, consumerAddress)
7777
expect(accessGranted).to.equal(false)
7878
})
7979

80-
it('should deny access with empty values in allow lists', () => {
80+
it('should deny access with empty values in allow lists', async () => {
8181
const credentials: Credentials = {
8282
allow: [
8383
{
@@ -87,10 +87,10 @@ describe('credentials', () => {
8787
]
8888
}
8989
const consumerAddress = '0x123'
90-
const accessGranted = checkCredentials(credentials, consumerAddress)
90+
const accessGranted = await checkCredentials(credentials, consumerAddress)
9191
expect(accessGranted).to.equal(false)
9292
})
93-
it('should allow access with address in allow list', () => {
93+
it('should allow access with address in allow list', async () => {
9494
const credentials: Credentials = {
9595
allow: [
9696
{
@@ -100,10 +100,10 @@ describe('credentials', () => {
100100
]
101101
}
102102
const consumerAddress = '0x123'
103-
const accessGranted = checkCredentials(credentials, consumerAddress)
103+
const accessGranted = await checkCredentials(credentials, consumerAddress)
104104
expect(accessGranted).to.equal(true)
105105
})
106-
it('should deny access with address not explicitly in deny list but also without any allow list', () => {
106+
it('should deny access with address not explicitly in deny list but also without any allow list', async () => {
107107
const credentials: Credentials = {
108108
deny: [
109109
{
@@ -113,10 +113,10 @@ describe('credentials', () => {
113113
]
114114
}
115115
const consumerAddress = '0x123'
116-
const accessGranted = checkCredentials(credentials, consumerAddress)
116+
const accessGranted = await checkCredentials(credentials, consumerAddress)
117117
expect(accessGranted).to.equal(false) // its not denied explicitly but not allowed either
118118
})
119-
it('should deny access with address in deny list', () => {
119+
it('should deny access with address in deny list', async () => {
120120
const credentials: Credentials = {
121121
allow: [
122122
{
@@ -132,10 +132,10 @@ describe('credentials', () => {
132132
]
133133
}
134134
const consumerAddress = '0x123'
135-
const accessGranted = checkCredentials(credentials, consumerAddress)
135+
const accessGranted = await checkCredentials(credentials, consumerAddress)
136136
expect(accessGranted).to.equal(false)
137137
})
138-
it('should deny access with address not in allow list', () => {
138+
it('should deny access with address not in allow list', async () => {
139139
const credentials: Credentials = {
140140
allow: [
141141
{
@@ -151,7 +151,7 @@ describe('credentials', () => {
151151
]
152152
}
153153
const consumerAddress = '0x123'
154-
const accessGranted = checkCredentials(credentials, consumerAddress)
154+
const accessGranted = await checkCredentials(credentials, consumerAddress)
155155
expect(accessGranted).to.equal(false)
156156
})
157157

@@ -229,7 +229,7 @@ describe('credentials', () => {
229229
expect(hasAddressMatchAllRule(creds2.credentials.allow)).to.be.equal(false)
230230
})
231231

232-
it('should deny access by default if no specific allow rule is a match', () => {
232+
it('should deny access by default if no specific allow rule is a match', async () => {
233233
const credentials: Credentials = {
234234
allow: [
235235
{
@@ -245,7 +245,7 @@ describe('credentials', () => {
245245
]
246246
}
247247
const consumerAddress = '0x123'
248-
const accessGranted = checkCredentials(
248+
const accessGranted = await checkCredentials(
249249
credentials,
250250
consumerAddress,
251251
DEVELOPMENT_CHAIN_ID

src/utils/blockchain.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
import { getConfiguration } from './config.js'
1515
import { CORE_LOGGER } from './logging/common.js'
1616
import { sleep } from './util.js'
17-
import { ConnectionStatus } from '../@types/blockchain.js'
17+
import { ConnectionStatus, SupportedNetwork } from '../@types/blockchain.js'
1818
import { ValidateChainId } from '../@types/commands.js'
1919

2020
export class Blockchain {
@@ -218,3 +218,14 @@ export async function getJsonRpcProvider(
218218
}
219219
return new JsonRpcProvider(checkResult.networkRpc)
220220
}
221+
222+
// useful for getting a Blockchain instance, as we repeat this piece of code often
223+
export function getBlockchainHandler(network: SupportedNetwork): Blockchain {
224+
const blockChain = new Blockchain(
225+
network.rpc,
226+
network.network,
227+
network.chainId,
228+
network.fallbackRPCs
229+
)
230+
return blockChain
231+
}

src/utils/credentials.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
} from '../@types/DDO/Credentials.js'
1111
import { getNFTContract } from '../components/Indexer/utils.js'
1212
import { isDefined } from './util.js'
13+
import { getConfiguration } from './config.js'
14+
import { getBlockchainHandler } from './blockchain.js'
1315

1416
export function findCredential(
1517
credentials: Credential[],
@@ -73,11 +75,11 @@ export function hasAddressMatchAllRule(credentials: Credential[]): boolean {
7375
* @param credentials credentials
7476
* @param consumerAddress consumer address
7577
*/
76-
export function checkCredentials(
78+
export async function checkCredentials(
7779
credentials: Credentials,
7880
consumerAddress: string,
7981
chainId?: number
80-
) {
82+
): Promise<boolean> {
8183
const consumerCredentials: Credential = {
8284
type: CREDENTIAL_TYPES.ADDRESS, // 'address',
8385
values: [String(consumerAddress)?.toLowerCase()]
@@ -128,10 +130,22 @@ export function checkCredentials(
128130
// otherwise, match 'all', in this case the amount of matches should be the same of the amount of rules
129131
matchCount++
130132
}
133+
} else if (type === CREDENTIAL_TYPES.ACCESS_LIST && chainId) {
134+
const config = await getConfiguration()
135+
const supportedNetwork = config.supportedNetworks[String(chainId)]
136+
if (supportedNetwork) {
137+
const blockChain = getBlockchainHandler(supportedNetwork)
138+
for (const accessListContractAddress of cred.values) {
139+
const balanceOk = await findAccessListCredentials(
140+
blockChain.getSigner(),
141+
accessListContractAddress,
142+
consumerAddress
143+
)
144+
if (balanceOk) return true
145+
}
146+
}
131147
}
132148
// extend function to ACCESS_LIST (https://github.com/oceanprotocol/ocean-node/issues/804)
133-
// else if (type === CREDENTIAL_TYPES.ACCESS_LIST && chainId) {
134-
// }
135149
}
136150
if (credentials.match_allow === 'all' && matchCount === credentials.allow.length) {
137151
return true
@@ -212,11 +226,18 @@ export async function findAccessListCredentials(
212226
contractAddress: string,
213227
address: string
214228
): Promise<boolean> {
215-
const nftContract: ethers.Contract = getNFTContract(signer, contractAddress)
216-
if (!nftContract) {
229+
try {
230+
const nftContract: ethers.Contract = getNFTContract(signer, contractAddress)
231+
if (!nftContract) {
232+
return false
233+
}
234+
return await findAccountFromAccessList(nftContract, address)
235+
} catch (e) {
236+
CORE_LOGGER.error(
237+
`Unable to read accessList contract from address ${contractAddress}: ${e.message}`
238+
)
217239
return false
218240
}
219-
return await findAccountFromAccessList(nftContract, address)
220241
}
221242

222243
export async function findAccountFromAccessList(

0 commit comments

Comments
 (0)