mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-06-04 05:06:37 +00:00
move orbit-db-access-controller tests here
This commit is contained in:
parent
6151cdff18
commit
c9fcb75f9b
8236
package-lock.json
generated
8236
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -47,6 +47,7 @@
|
||||
"cpy-cli": "^3.1.1",
|
||||
"cross-env": "^7.0.2",
|
||||
"fs-extra": "^9.0.1",
|
||||
"ganache-cli": "^6.12.2",
|
||||
"go-ipfs": "^0.10.0-rc1",
|
||||
"ipfs": "^0.59.0",
|
||||
"ipfsd-ctl": "^10.0.3",
|
||||
@ -67,6 +68,7 @@
|
||||
"rimraf": "^3.0.2",
|
||||
"standard": "^14.3.4",
|
||||
"validate-maintainers": "^1.2.2",
|
||||
"web3": "^1.5.3",
|
||||
"webpack": "^4.41.2",
|
||||
"webpack-cli": "^3.3.10"
|
||||
},
|
||||
@ -77,7 +79,7 @@
|
||||
"examples:browser-webpack": "open-cli examples/browser/browser-webpack-example/index.html",
|
||||
"lint:docs": "remark -qf -u validate-links .",
|
||||
"test:all": "npm run test:browser-multiple-tabs && npm run test",
|
||||
"test": "cross-env TEST=all mocha",
|
||||
"test": "cross-env TEST=all mocha && cross-env TEST=all mocha ./test/access-controllers --exit",
|
||||
"test:browser-multiple-tabs": "npm run build:dist && cpy dist/orbitdb.min.js ./test/browser --rename=orbitdb.js && cpy node_modules/ipfs/index.min.js ./test/browser --rename=ipfs.js && cpy node_modules/orbit-db-identity-provider/dist/index-browser.min.js ./test/browser --rename=identities.js && cpy node_modules/ipfs-log/dist/ipfslog.min.js ./test/browser && mocha ./test/browser/concurrent.spec.js",
|
||||
"build": "npm run build:es5 && npm run build:debug && npm run build:dist && npm run build:examples && npm run build:docs/toc",
|
||||
"build:examples": "webpack --config conf/webpack.example.config.js --sort-modules-by size",
|
||||
|
6
test/access-controllers/.mocharc.js
Normal file
6
test/access-controllers/.mocharc.js
Normal file
@ -0,0 +1,6 @@
|
||||
'use strict'
|
||||
module.exports = {
|
||||
exit: true,
|
||||
recursive: true,
|
||||
slow: 1000
|
||||
}
|
174
test/access-controllers/Access.json
Normal file
174
test/access-controllers/Access.json
Normal file
@ -0,0 +1,174 @@
|
||||
{
|
||||
"contractName": "Access",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "capabilities",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "OGAdmin",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "capability",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "CapabilityGranted",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "capability",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "CapabilityRevoked",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newAdmin",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "grantAdminStatus",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "adminToRemove",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "revokeAdminStatus",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "capability",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "grantCapability",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "capability",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "revokeCapability",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "capability",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "isPermitted",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"bytecode": "0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550610822806100b76000396000f3fe608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063106bab8c146100885780631faad3c4146100fb578063228e3f9b14610152578063330506d9146101ad5780637caac39814610208578063e21c478314610259578063fa62a1ff146102cc575b600080fd5b34801561009457600080fd5b506100e1600480360360408110156100ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061031d565b604051808215151515815260200191505060405180910390f35b34801561010757600080fd5b5061011061034c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561015e57600080fd5b506101ab6004803603604081101561017557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610371565b005b3480156101b957600080fd5b50610206600480360360408110156101d057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506104a3565b005b34801561021457600080fd5b506102576004803603602081101561022b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105d5565b005b34801561026557600080fd5b506102b26004803603604081101561027c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610689565b604051808215151515815260200191505060405180910390f35b3480156102d857600080fd5b5061031b600480360360208110156102ef57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610745565b005b60026020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141561049f576000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff0219169083151502179055507f6cc46c13bf9ecc309370a9150165239f833c3742128d77220c49cb4915a07bc78282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5050565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156105d1576001600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff0219169083151502179055507faf409f79c52d1fc6127b156de998c22b9c6cf6d4f0f58e934e62f983c4dc82bf8282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5050565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156106865760018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168061073d5750600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900460ff165b905092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156107f3576000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5056fea165627a7a7230582009cc4036faa4edfffcc9ba31cfc8caab65942780eb1dedaa2459f3514b30db5d0029",
|
||||
"deployedBytecode": "0x608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063106bab8c146100885780631faad3c4146100fb578063228e3f9b14610152578063330506d9146101ad5780637caac39814610208578063e21c478314610259578063fa62a1ff146102cc575b600080fd5b34801561009457600080fd5b506100e1600480360360408110156100ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061031d565b604051808215151515815260200191505060405180910390f35b34801561010757600080fd5b5061011061034c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561015e57600080fd5b506101ab6004803603604081101561017557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610371565b005b3480156101b957600080fd5b50610206600480360360408110156101d057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506104a3565b005b34801561021457600080fd5b506102576004803603602081101561022b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105d5565b005b34801561026557600080fd5b506102b26004803603604081101561027c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610689565b604051808215151515815260200191505060405180910390f35b3480156102d857600080fd5b5061031b600480360360208110156102ef57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610745565b005b60026020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141561049f576000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff0219169083151502179055507f6cc46c13bf9ecc309370a9150165239f833c3742128d77220c49cb4915a07bc78282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5050565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156105d1576001600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff0219169083151502179055507faf409f79c52d1fc6127b156de998c22b9c6cf6d4f0f58e934e62f983c4dc82bf8282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5050565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156106865760018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff168061073d5750600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900460ff165b905092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156107f3576000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5056fea165627a7a7230582009cc4036faa4edfffcc9ba31cfc8caab65942780eb1dedaa2459f3514b30db5d0029",
|
||||
"sourceMap": "25:1342:0:-;;;185:93;8:9:-1;5:2;;;30:1;27;20:12;5:2;185:93:0;227:10;217:7;;:20;;;;;;;;;;;;;;;;;;267:4;247:5;:17;253:10;247:17;;;;;;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;25:1342;;;;;;",
|
||||
"deployedSourceMap": "25:1342:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112:66;;8:9:-1;5:2;;;30:1;27;20:12;5:2;112:66:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;112:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47:22;;8:9:-1;5:2;;;30:1;27;20:12;5:2;47:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;978:230;;8:9:-1;5:2;;;30:1;27;20:12;5:2;978:230:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;978:230:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;744:228;;8:9:-1;5:2;;;30:1;27;20:12;5:2;744:228:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;744:228:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;434:145;;8:9:-1;5:2;;;30:1;27;20:12;5:2;434:145:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;434:145:0;;;;;;;;;;;;;;;;;;;;;;1214:151;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1214:151:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1214:151:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;585:153;;8:9:-1;5:2;;;30:1;27;20:12;5:2;585:153:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;585:153:0;;;;;;;;;;;;;;;;;;;;;;112:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;47:22::-;;;;;;;;;;;;;:::o;978:230::-;1079:4;1058:25;;:5;:17;1064:10;1058:17;;;;;;;;;;;;;;;;;;;;;;;;;:25;;;1055:147;;;1132:5;1099:12;:18;1112:4;1099:18;;;;;;;;;;;;;;;:30;1118:10;1099:30;;;;;;;;;;;;:38;;;;;;;;;;;;;;;;;;1156:35;1174:4;1180:10;1156:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;1055:147;978:230;;:::o;744:228::-;844:4;823:25;;:5;:17;829:10;823:17;;;;;;;;;;;;;;;;;;;;;;;;;:25;;;820:146;;;897:4;864:12;:18;877:4;864:18;;;;;;;;;;;;;;;:30;883:10;864:30;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;920:35;938:4;944:10;920:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;820:146;744:228;;:::o;434:145::-;520:4;499:25;;:5;:17;505:10;499:17;;;;;;;;;;;;;;;;;;;;;;;;;:25;;;495:78;;;558:4;540:5;:15;546:8;540:15;;;;;;;;;;;;;;;;:22;;;;;;;;;;;;;;;;;;495:78;434:145;:::o;1214:151::-;1290:4;1313:5;:11;1319:4;1313:11;;;;;;;;;;;;;;;;;;;;;;;;;:45;;;;1328:12;:18;1341:4;1328:18;;;;;;;;;;;;;;;:30;1347:10;1328:30;;;;;;;;;;;;;;;;;;;;;1313:45;1306:52;;1214:151;;;;:::o;585:153::-;670:7;;;;;;;;;;;656:21;;:10;:21;;;652:80;;;716:5;693;:20;699:13;693:20;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;652:80;585:153;:::o",
|
||||
"source": "pragma solidity ^0.5.0;\n\ncontract Access {\n address public OGAdmin;\n mapping (address => bool) admin;\n mapping (address => mapping (bytes32 => bool)) public capabilities;\n\n constructor () public {\n OGAdmin = msg.sender;\n admin[msg.sender] = true;\n }\n\n event CapabilityGranted(address user, bytes32 capability);\n\n event CapabilityRevoked(\n address user,\n bytes32 capability\n );\n\n function grantAdminStatus(address newAdmin) public {\n if (admin[msg.sender] == true) {\n admin[newAdmin] = true;\n }\n }\n\n function revokeAdminStatus(address adminToRemove) public {\n if (msg.sender == OGAdmin) {\n admin[adminToRemove] = false;\n }\n }\n\n function grantCapability(address user, bytes32 capability) public {\n if(admin[msg.sender] == true) {\n capabilities[user][capability] = true;\n emit CapabilityGranted(user, capability);\n }\n }\n\n function revokeCapability(address user, bytes32 capability) public {\n if(admin[msg.sender] == true) {\n capabilities[user][capability] = false;\n emit CapabilityRevoked(user, capability);\n }\n }\n\n function isPermitted(address user, bytes32 capability) public view returns (bool) {\n return admin[user] || capabilities[user][capability];\n }\n}\n"
|
||||
}
|
124
test/access-controllers/PayDeposit.json
Normal file
124
test/access-controllers/PayDeposit.json
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"contractName": "PayDeposit",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "OGAdmin",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "paid",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newAdmin",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "grantAdminStatus",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "adminToRemove",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "revokeAdminStatus",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "payDeposit",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "expireDeposit",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "hasPaidDeposit",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"bytecode": "0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555061068b806100b76000396000f3fe608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631faad3c4146100885780632c679d63146100df57806354dae7801461013057806359f3ef05146101995780637caac398146101ea578063a340cf791461023b578063fa62a1ff146102a4575b600080fd5b34801561009457600080fd5b5061009d6102f5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100eb57600080fd5b5061012e6004803603602081101561010257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061031a565b005b34801561013c57600080fd5b5061017f6004803603602081101561015357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103cf565b604051808215151515815260200191505060405180910390f35b3480156101a557600080fd5b506101e8600480360360208110156101bc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610425565b005b3480156101f657600080fd5b506102396004803603602081101561020d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104da565b005b34801561024757600080fd5b5061028a6004803603602081101561025e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061058e565b604051808215151515815260200191505060405180910390f35b3480156102b057600080fd5b506102f3600480360360208110156102c757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105ae565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156103cc576000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156104d7576001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141561058b5760018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b60026020528060005260406000206000915054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561065c576000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5056fea165627a7a72305820d6f5392496318abaff5d492d31c15fee1934106beb9aa461d99727d9d77955cb0029",
|
||||
"deployedBytecode": "0x608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631faad3c4146100885780632c679d63146100df57806354dae7801461013057806359f3ef05146101995780637caac398146101ea578063a340cf791461023b578063fa62a1ff146102a4575b600080fd5b34801561009457600080fd5b5061009d6102f5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100eb57600080fd5b5061012e6004803603602081101561010257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061031a565b005b34801561013c57600080fd5b5061017f6004803603602081101561015357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506103cf565b604051808215151515815260200191505060405180910390f35b3480156101a557600080fd5b506101e8600480360360208110156101bc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610425565b005b3480156101f657600080fd5b506102396004803603602081101561020d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104da565b005b34801561024757600080fd5b5061028a6004803603602081101561025e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061058e565b604051808215151515815260200191505060405180910390f35b3480156102b057600080fd5b506102f3600480360360208110156102c757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105ae565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156103cc576000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156104d7576001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141561058b5760018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b50565b60026020528060005260406000206000915054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561065c576000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b5056fea165627a7a72305820d6f5392496318abaff5d492d31c15fee1934106beb9aa461d99727d9d77955cb0029",
|
||||
"sourceMap": "25:919:2:-;;;160:93;8:9:-1;5:2;;;30:1;27;20:12;5:2;160:93:2;202:10;192:7;;:20;;;;;;;;;;;;;;;;;;242:4;222:5;:17;228:10;222:17;;;;;;;;;;;;;;;;:24;;;;;;;;;;;;;;;;;;25:919;;;;;;",
|
||||
"deployedSourceMap": "25:919:2:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51:22;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51:22:2;;;;;;;;;;;;;;;;;;;;;;;;;;;704:133;;8:9:-1;5:2;;;30:1;27;20:12;5:2;704:133:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;704:133:2;;;;;;;;;;;;;;;;;;;;;;843:99;;8:9:-1;5:2;;;30:1;27;20:12;5:2;843:99:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;843:99:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;569:129;;8:9:-1;5:2;;;30:1;27;20:12;5:2;569:129:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;569:129:2;;;;;;;;;;;;;;;;;;;;;;259:145;;8:9:-1;5:2;;;30:1;27;20:12;5:2;259:145:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;259:145:2;;;;;;;;;;;;;;;;;;;;;;116:37;;8:9:-1;5:2;;;30:1;27;20:12;5:2;116:37:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;116:37:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;410:153;;8:9:-1;5:2;;;30:1;27;20:12;5:2;410:153:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;410:153:2;;;;;;;;;;;;;;;;;;;;;;51:22;;;;;;;;;;;;;:::o;704:133::-;782:4;761:25;;:5;:17;767:10;761:17;;;;;;;;;;;;;;;;;;;;;;;;;:25;;;758:73;;;815:5;802:4;:10;807:4;802:10;;;;;;;;;;;;;;;;:18;;;;;;;;;;;;;;;;;;758:73;704:133;:::o;843:99::-;902:4;925;:10;930:4;925:10;;;;;;;;;;;;;;;;;;;;;;;;;918:17;;843:99;;;:::o;569:129::-;644:4;623:25;;:5;:17;629:10;623:17;;;;;;;;;;;;;;;;;;;;;;;;;:25;;;620:72;;;677:4;664;:10;669:4;664:10;;;;;;;;;;;;;;;;:17;;;;;;;;;;;;;;;;;;620:72;569:129;:::o;259:145::-;345:4;324:25;;:5;:17;330:10;324:17;;;;;;;;;;;;;;;;;;;;;;;;;:25;;;320:78;;;383:4;365:5;:15;371:8;365:15;;;;;;;;;;;;;;;;:22;;;;;;;;;;;;;;;;;;320:78;259:145;:::o;116:37::-;;;;;;;;;;;;;;;;;;;;;;:::o;410:153::-;495:7;;;;;;;;;;;481:21;;:10;:21;;;477:80;;;541:5;518;:20;524:13;518:20;;;;;;;;;;;;;;;;:28;;;;;;;;;;;;;;;;;;477:80;410:153;:::o",
|
||||
"source": "pragma solidity ^0.5.0;\n\ncontract PayDeposit {\n address public OGAdmin;\n mapping (address => bool) admin;\n mapping (address => bool) public paid;\n\n constructor () public {\n OGAdmin = msg.sender;\n admin[msg.sender] = true;\n }\n\n function grantAdminStatus(address newAdmin) public {\n if (admin[msg.sender] == true) {\n admin[newAdmin] = true;\n }\n }\n\n function revokeAdminStatus(address adminToRemove) public {\n if (msg.sender == OGAdmin) {\n admin[adminToRemove] = false;\n }\n }\n\n function payDeposit(address user) public {\n if(admin[msg.sender] == true) {\n paid[user] = true;\n }\n }\n\n function expireDeposit(address user) public {\n if(admin[msg.sender] == true) {\n paid[user] = false;\n }\n }\n\n function hasPaidDeposit(address user) public view returns (bool) {\n return paid[user];\n }\n}\n"
|
||||
}
|
142
test/access-controllers/access-controller-handlers.test.js
Normal file
142
test/access-controllers/access-controller-handlers.test.js
Normal file
@ -0,0 +1,142 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const Web3 = require('web3')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
const ContractAccessController = require('orbit-db-access-controllers/src/contract-access-controller.js')
|
||||
const ganache = require('ganache-cli')
|
||||
const { abi, bytecode } = require('./Access')
|
||||
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/orbitdb-access-controller/1'
|
||||
const dbPath2 = './orbitdb/tests/orbitdb-access-controller/2'
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - Access Controller Handlers (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let web3, contract, ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ id: 'A', keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ id: 'B', keystore: keystore2 })
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) { await orbitdb1.stop() }
|
||||
|
||||
if (orbitdb2) { await orbitdb2.stop() }
|
||||
|
||||
if (ipfsd1) { await stopIpfs(ipfsd1) }
|
||||
|
||||
if (ipfsd2) { await stopIpfs(ipfsd2) }
|
||||
})
|
||||
|
||||
describe('isSupported', function () {
|
||||
it('supports default access controllers', () => {
|
||||
assert.strictEqual(AccessControllers.isSupported('ipfs'), true)
|
||||
assert.strictEqual(AccessControllers.isSupported('orbitdb'), true)
|
||||
})
|
||||
|
||||
it('doesn\'t support smart contract access controller by default', () => {
|
||||
assert.strictEqual(AccessControllers.isSupported(ContractAccessController.type), false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('addAccessController', function () {
|
||||
it('supports added access controller', () => {
|
||||
const options = {
|
||||
AccessController: ContractAccessController,
|
||||
web3: web3,
|
||||
abi: abi
|
||||
}
|
||||
AccessControllers.addAccessController(options)
|
||||
assert.strictEqual(AccessControllers.isSupported(ContractAccessController.type), true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('create access controllers', function () {
|
||||
let options = {
|
||||
AccessController: ContractAccessController
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
web3 = new Web3(ganache.provider())
|
||||
const accounts = await web3.eth.getAccounts()
|
||||
contract = await new web3.eth.Contract(abi)
|
||||
.deploy({ data: bytecode })
|
||||
.send({ from: accounts[0], gas: '1000000' })
|
||||
options = Object.assign({}, options, { web3, abi, contractAddress: contract._address, defaultAccount: accounts[0] })
|
||||
AccessControllers.addAccessController(options)
|
||||
})
|
||||
|
||||
it('throws an error if AccessController is not defined', async () => {
|
||||
let err
|
||||
try {
|
||||
AccessControllers.addAccessController({})
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, 'Error: AccessController class needs to be given as an option')
|
||||
})
|
||||
|
||||
it('throws an error if AccessController doesn\'t define type', async () => {
|
||||
let err
|
||||
try {
|
||||
AccessControllers.addAccessController({ AccessController: {} })
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, 'Error: Given AccessController class needs to implement: static get type() { /* return a string */}.')
|
||||
})
|
||||
|
||||
it('creates a custom access controller', async () => {
|
||||
const type = ContractAccessController.type
|
||||
const acManifestHash = await AccessControllers.create(orbitdb1, type, options)
|
||||
assert.notStrictEqual(acManifestHash, null)
|
||||
|
||||
const ac = await AccessControllers.resolve(orbitdb1, acManifestHash, options)
|
||||
assert.strictEqual(ac.type, type)
|
||||
})
|
||||
|
||||
it('removes the custom access controller', async () => {
|
||||
AccessControllers.removeAccessController(ContractAccessController.type)
|
||||
assert.strictEqual(AccessControllers.isSupported(ContractAccessController.type), false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -0,0 +1,267 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const EthIdentityProvider = require('orbit-db-identity-provider/src/ethereum-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
const ContractAccessController = require('orbit-db-access-controllers/src/contract-access-controller')
|
||||
const DepositContractAccessController = require('orbit-db-access-controllers/src/deposit-contract-access-controller')
|
||||
const ganache = require('ganache-cli')
|
||||
const Web3 = require('web3')
|
||||
const io = require('orbit-db-io')
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/contract-access-controller-integration/1'
|
||||
const dbPath2 = './orbitdb/tests/contract-access-controller-integration/2'
|
||||
|
||||
const accessControllers = [
|
||||
{
|
||||
AccessController: ContractAccessController,
|
||||
contract: require('./Access')
|
||||
},
|
||||
{
|
||||
AccessController: DepositContractAccessController,
|
||||
contract: require('./PayDeposit')
|
||||
}
|
||||
]
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - ContractAccessController Integration (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
let web3, accounts
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
IdentityProvider.addIdentityProvider(EthIdentityProvider)
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ type: 'ethereum', keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ type: 'ethereum', keystore: keystore2 })
|
||||
|
||||
web3 = new Web3(ganache.provider())
|
||||
accounts = await web3.eth.getAccounts()
|
||||
|
||||
accessControllers.forEach(ac => AccessControllers.addAccessController(ac))
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) {
|
||||
await orbitdb1.stop()
|
||||
}
|
||||
|
||||
if (orbitdb2) {
|
||||
await orbitdb2.stop()
|
||||
}
|
||||
|
||||
if (ipfsd1) {
|
||||
await stopIpfs(ipfsd1)
|
||||
}
|
||||
|
||||
if (ipfsd2) {
|
||||
await stopIpfs(ipfsd2)
|
||||
}
|
||||
})
|
||||
|
||||
describe('OrbitDB Integration', function () {
|
||||
accessControllers.forEach(async (ac, i) => {
|
||||
let db, db2
|
||||
let dbManifest, acManifest, access
|
||||
let contract
|
||||
|
||||
before(async () => {
|
||||
contract = await new web3.eth.Contract(ac.contract.abi)
|
||||
.deploy({ data: ac.contract.bytecode })
|
||||
.send({ from: accounts[i], gas: '1000000' })
|
||||
|
||||
// DB creator needs to provide ac-type, abi and contract-address
|
||||
db = await orbitdb1.feed('AABB', {
|
||||
identity: id1,
|
||||
accessController: {
|
||||
type: ac.AccessController.type,
|
||||
web3: web3,
|
||||
abi: ac.contract.abi,
|
||||
contractAddress: contract._address,
|
||||
defaultAccount: accounts[i]
|
||||
}
|
||||
})
|
||||
|
||||
// DB peer needs to provide web3 instance
|
||||
db2 = await orbitdb2.feed(db.address, {
|
||||
identity: id2,
|
||||
accessController: {
|
||||
web3: web3,
|
||||
defaultAccount: accounts[(i + 1) % accessControllers.length] // peer owns different eth-account
|
||||
}
|
||||
})
|
||||
|
||||
await db2.load()
|
||||
|
||||
dbManifest = await io.read(ipfs1, db.address.root)
|
||||
const hash = dbManifest.accessController.split('/').pop()
|
||||
acManifest = await io.read(ipfs1, hash)
|
||||
access = await io.read(ipfs1, acManifest.params.address)
|
||||
})
|
||||
|
||||
it('makes database use the correct access controller', async () => {
|
||||
assert.strictEqual(access.contractAddress, db.access.address)
|
||||
})
|
||||
|
||||
it('saves database manifest file locally', async () => {
|
||||
assert.notStrictEqual(dbManifest, null)
|
||||
})
|
||||
|
||||
it('saves access controller manifest file locally', async () => {
|
||||
assert.notStrictEqual(acManifest, null)
|
||||
})
|
||||
|
||||
describe('database manifest', () => {
|
||||
it('has correct name', async () => {
|
||||
assert.strictEqual(dbManifest.name, 'AABB')
|
||||
})
|
||||
|
||||
it('has correct type', async () => {
|
||||
assert.strictEqual(dbManifest.type, 'feed')
|
||||
})
|
||||
|
||||
it('has correct address', async () => {
|
||||
assert.notStrictEqual(dbManifest.accessController, null)
|
||||
assert.strictEqual(dbManifest.accessController.indexOf('/ipfs'), 0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('access controller manifest', () => {
|
||||
it('has correct type', async () => {
|
||||
assert.strictEqual(acManifest.type, ac.AccessController.type)
|
||||
})
|
||||
|
||||
it('has correct address', async () => {
|
||||
assert.strictEqual(access.contractAddress.indexOf('0x'), 0)
|
||||
assert.strictEqual(access.contractAddress, db.access.address)
|
||||
})
|
||||
})
|
||||
|
||||
describe('access controls', () => {
|
||||
it('throws error if key not permitted to write', async () => {
|
||||
let err
|
||||
try {
|
||||
await db.add('hello?') // should throw error
|
||||
assert.strictEqual('Should not end here', false)
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, `Error: Could not append entry, key "${id1.id}" is not allowed to write to the log`)
|
||||
})
|
||||
|
||||
it('granting access enables to write to the database', async () => {
|
||||
await db.access.grant('write', id1.id)
|
||||
const doChanges = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
db2.events.once('replicated', () => {
|
||||
// FIXME: timeout to get rid of the "libp2p node not started yet" errors
|
||||
setTimeout(() => resolve(), 1000)
|
||||
})
|
||||
db.add('hello!')
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
// Try adding something again
|
||||
await doChanges()
|
||||
|
||||
const res1 = await db.iterator().collect().map(e => e.payload.value)
|
||||
const res2 = await db2.iterator().collect().map(e => e.payload.value)
|
||||
assert.deepStrictEqual(res1, ['hello!'])
|
||||
assert.deepStrictEqual(res2, ['hello!'])
|
||||
})
|
||||
|
||||
it('can\'t grant access if not admin', async () => {
|
||||
await db2.access.grant('write', id2.id)
|
||||
const canAppend = await db2.access.canAppend({ identity: id2 }, id2.provider)
|
||||
assert.strictEqual(canAppend, false)
|
||||
})
|
||||
|
||||
it('can\'t revoke access if not admin', async () => {
|
||||
await db2.access.revoke('write', id1.id)
|
||||
const canAppend = await db2.access.canAppend({ identity: id1 }, id1.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
})
|
||||
|
||||
it('can check permissions without defaultAccount set', async () => {
|
||||
db2.access.defaultAccount = null
|
||||
const canAppend = await db2.access.canAppend({ identity: id1 }, id1.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
})
|
||||
|
||||
it('can\'t change permissions without from address if no defaultAccount set', async () => {
|
||||
let err
|
||||
db2.access.defaultAccount = null
|
||||
try {
|
||||
await db2.access.grant('write', id2.id)
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, 'Error: No "from" address specified in neither the given options, nor the default options.')
|
||||
})
|
||||
|
||||
it('can change permissions by passing in from address', async () => {
|
||||
let err
|
||||
db2.access.defaultAccount = null
|
||||
try {
|
||||
await db2.access.grant('write', id2.id, { from: accounts[i] }) // from address can grant/revoke access
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, undefined)
|
||||
const canAppend = await db2.access.canAppend({ identity: id2 }, id2.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
})
|
||||
|
||||
it('revoking access disables ability to write to the database', async () => {
|
||||
let err
|
||||
try {
|
||||
// Revoke user's access
|
||||
await db.access.revoke('write', id2.id)
|
||||
await db2.add('hello?')
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, `Error: Could not append entry, key "${id2.id}" is not allowed to write to the log`)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
183
test/access-controllers/contract-access-controller.test.js
Normal file
183
test/access-controllers/contract-access-controller.test.js
Normal file
@ -0,0 +1,183 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const EthIdentityProvider = require('orbit-db-identity-provider/src/ethereum-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const ContractAccessController = require('orbit-db-access-controllers/src/contract-access-controller')
|
||||
const DepositContractAccessController = require('orbit-db-access-controllers/src/deposit-contract-access-controller')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
const Web3 = require('web3')
|
||||
const ganache = require('ganache-cli')
|
||||
const io = require('orbit-db-io')
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/contract-access-controller/1'
|
||||
const dbPath2 = './orbitdb/tests/contract-access-controller/2'
|
||||
|
||||
const accessControllers = [
|
||||
{
|
||||
AccessController: ContractAccessController,
|
||||
contract: require('./Access')
|
||||
},
|
||||
{
|
||||
AccessController: DepositContractAccessController,
|
||||
contract: require('./PayDeposit')
|
||||
}
|
||||
]
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - ContractAccessController (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
let web3, accounts
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
|
||||
IdentityProvider.addIdentityProvider(EthIdentityProvider)
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ type: EthIdentityProvider.type, keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ type: EthIdentityProvider.type, keystore: keystore2 })
|
||||
|
||||
web3 = new Web3(ganache.provider())
|
||||
accounts = await web3.eth.getAccounts()
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) {
|
||||
await orbitdb1.stop()
|
||||
}
|
||||
|
||||
if (orbitdb2) {
|
||||
await orbitdb2.stop()
|
||||
}
|
||||
|
||||
if (ipfsd1) {
|
||||
await stopIpfs(ipfsd1)
|
||||
}
|
||||
|
||||
if (ipfsd2) {
|
||||
await stopIpfs(ipfsd2)
|
||||
}
|
||||
})
|
||||
|
||||
describe('Constructor', function () {
|
||||
accessControllers.forEach(async (ac, i) => {
|
||||
let accessController, contract
|
||||
before(async () => {
|
||||
contract = await new web3.eth.Contract(ac.contract.abi)
|
||||
.deploy({ data: ac.contract.bytecode })
|
||||
.send({ from: accounts[i], gas: '1000000' })
|
||||
|
||||
accessController = await ac.AccessController.create(orbitdb1, {
|
||||
type: ac.AccessController.type,
|
||||
web3: web3,
|
||||
abi: ac.contract.abi,
|
||||
contractAddress: contract._address,
|
||||
defaultAccount: accounts[i]
|
||||
})
|
||||
await accessController.load()
|
||||
})
|
||||
|
||||
it('creates an access controller', () => {
|
||||
assert.notStrictEqual(accessController, null)
|
||||
assert.notStrictEqual(accessController, undefined)
|
||||
})
|
||||
|
||||
it('sets the controller type', () => {
|
||||
assert.strictEqual(accessController.type, ac.AccessController.type)
|
||||
})
|
||||
|
||||
it('grants access to key', async () => {
|
||||
const mockEntry = {
|
||||
identity: id1
|
||||
// ...
|
||||
// doesn't matter what we put here, only identity is used for the check
|
||||
}
|
||||
await accessController.grant('write', id1.id)
|
||||
const canAppend = await accessController.canAppend(mockEntry, id1.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
})
|
||||
|
||||
it('grants access to multiple keys', async () => {
|
||||
const canAppend1 = await accessController.canAppend({ identity: orbitdb1.identity }, orbitdb1.identity.provider)
|
||||
const canAppend2 = await accessController.canAppend({ identity: orbitdb2.identity }, orbitdb2.identity.provider)
|
||||
|
||||
await accessController.grant('write', orbitdb2.identity.id)
|
||||
const canAppend3 = await accessController.canAppend({ identity: orbitdb2.identity }, orbitdb2.identity.provider)
|
||||
|
||||
assert.strictEqual(canAppend1, true)
|
||||
assert.strictEqual(canAppend2, false)
|
||||
assert.strictEqual(canAppend3, true)
|
||||
})
|
||||
|
||||
describe('save and load', function () {
|
||||
let accessController, manifest
|
||||
|
||||
before(async () => {
|
||||
accessController = await ac.AccessController.create(orbitdb1, {
|
||||
type: ac.AccessController.type,
|
||||
web3: web3,
|
||||
abi: ac.contract.abi,
|
||||
contractAddress: contract._address,
|
||||
defaultAccount: accounts[i]
|
||||
})
|
||||
manifest = await accessController.save()
|
||||
const access = await io.read(ipfs1, manifest.address)
|
||||
|
||||
accessController = await ac.AccessController.create(orbitdb1, {
|
||||
type: ac.AccessController.type,
|
||||
web3: web3,
|
||||
abi: JSON.parse(access.abi),
|
||||
contractAddress: access.contractAddress,
|
||||
defaultAccount: accounts[i]
|
||||
})
|
||||
|
||||
await accessController.load(manifest.address)
|
||||
})
|
||||
|
||||
it('has correct capabalities', async () => {
|
||||
const canAppend1 = await accessController.canAppend({ identity: orbitdb1.identity }, orbitdb1.identity.provider)
|
||||
const canAppend2 = await accessController.canAppend({ identity: orbitdb2.identity }, orbitdb2.identity.provider)
|
||||
const canAppend3 = await accessController.canAppend({ identity: { id: 'someotherid' } }, orbitdb1.identity.provider)
|
||||
|
||||
assert.strictEqual(canAppend1, true)
|
||||
assert.strictEqual(canAppend2, true)
|
||||
assert.strictEqual(canAppend3, false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -0,0 +1,156 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
const io = require('orbit-db-io')
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/orbitdb-access-controller-integration/1'
|
||||
const dbPath2 = './orbitdb/tests/orbitdb-access-controller-integration/2'
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - IPFSAccessController Integration (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ id: 'A', keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ id: 'B', keystore: keystore2 })
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) { await orbitdb1.stop() }
|
||||
|
||||
if (orbitdb2) { await orbitdb2.stop() }
|
||||
|
||||
if (ipfsd1) { await stopIpfs(ipfsd1) }
|
||||
|
||||
if (ipfsd2) { await stopIpfs(ipfsd2) }
|
||||
})
|
||||
|
||||
describe('OrbitDB Integration', function () {
|
||||
let db, db2
|
||||
let dbManifest, acManifest
|
||||
|
||||
before(async () => {
|
||||
db = await orbitdb1.feed('AABB', {
|
||||
identity: id1,
|
||||
accessController: {
|
||||
type: 'ipfs',
|
||||
write: [id1.id]
|
||||
}
|
||||
})
|
||||
|
||||
db2 = await orbitdb2.feed(db.address, {
|
||||
identity: id2
|
||||
})
|
||||
await db2.load()
|
||||
|
||||
dbManifest = await io.read(ipfs1, db.address.root)
|
||||
const hash = dbManifest.accessController.split('/').pop()
|
||||
acManifest = await io.read(ipfs1, hash)
|
||||
})
|
||||
|
||||
it('has the correct access rights after creating the database', async () => {
|
||||
assert.deepStrictEqual(db.access.write, [id1.id])
|
||||
})
|
||||
|
||||
it('makes database use the correct access controller', async () => {
|
||||
const { address } = await db.access.save()
|
||||
assert.strictEqual(acManifest.params.address, address)
|
||||
})
|
||||
|
||||
it('saves database manifest file locally', async () => {
|
||||
assert.notStrictEqual(dbManifest, null)
|
||||
})
|
||||
|
||||
it('saves access controller manifest file locally', async () => {
|
||||
assert.notStrictEqual(acManifest, null)
|
||||
})
|
||||
|
||||
it('has correct type', async () => {
|
||||
assert.strictEqual(acManifest.type, 'ipfs')
|
||||
})
|
||||
|
||||
describe('database manifest', () => {
|
||||
it('has correct name', async () => {
|
||||
assert.strictEqual(dbManifest.name, 'AABB')
|
||||
})
|
||||
|
||||
it('has correct type', async () => {
|
||||
assert.strictEqual(dbManifest.type, 'feed')
|
||||
})
|
||||
|
||||
it('has correct address', async () => {
|
||||
assert.notStrictEqual(dbManifest.accessController, null)
|
||||
assert.strictEqual(dbManifest.accessController.indexOf('/ipfs'), 0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('access controls', () => {
|
||||
it('allows to write if user has write access', async () => {
|
||||
let err
|
||||
try {
|
||||
await db.add('hello?')
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
|
||||
const res = await db.iterator().collect().map(e => e.payload.value)
|
||||
assert.strictEqual(err, undefined)
|
||||
assert.deepStrictEqual(res, ['hello?'])
|
||||
})
|
||||
|
||||
it('doesn\'t allow to write without write access', async () => {
|
||||
let err
|
||||
try {
|
||||
await db2.add('hello!!')
|
||||
assert.strictEqual('Should not end here', false)
|
||||
} catch (e) {
|
||||
err = e
|
||||
}
|
||||
|
||||
const res = await db2.iterator().collect().map(e => e.payload.value)
|
||||
assert.strictEqual(err.message, `Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
||||
assert.deepStrictEqual(res.includes(e => e === 'hello!!'), false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
// TODO: use two separate peers for testing the AC
|
||||
// TODO: add tests for revocation correctness with a database (integration tests)
|
||||
})
|
130
test/access-controllers/ipfs-access-controller.test.js
Normal file
130
test/access-controllers/ipfs-access-controller.test.js
Normal file
@ -0,0 +1,130 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const IPFSAccessController = require('orbit-db-access-controllers/src/ipfs-access-controller')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/ipfs-access-controller/1'
|
||||
const dbPath2 = './orbitdb/tests/ipfs-access-controller/2'
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - IPFSAccessController (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ id: 'A', keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ id: 'B', keystore: keystore2 })
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) {
|
||||
await orbitdb1.stop()
|
||||
}
|
||||
|
||||
if (orbitdb2) {
|
||||
await orbitdb2.stop()
|
||||
}
|
||||
|
||||
if (ipfsd1) {
|
||||
await stopIpfs(ipfsd1)
|
||||
}
|
||||
|
||||
if (ipfsd2) {
|
||||
await stopIpfs(ipfsd2)
|
||||
}
|
||||
})
|
||||
|
||||
describe('Constructor', function () {
|
||||
let accessController
|
||||
|
||||
before(async () => {
|
||||
accessController = await IPFSAccessController.create(orbitdb1, {
|
||||
write: [id1.id]
|
||||
})
|
||||
})
|
||||
|
||||
it('creates an access controller', () => {
|
||||
assert.notStrictEqual(accessController, null)
|
||||
assert.notStrictEqual(accessController, undefined)
|
||||
})
|
||||
|
||||
it('sets the controller type', () => {
|
||||
assert.strictEqual(accessController.type, 'ipfs')
|
||||
})
|
||||
|
||||
it('has IPFS instance', async () => {
|
||||
const peerId1 = await accessController._ipfs.id()
|
||||
const peerId2 = await ipfs1.id()
|
||||
assert.strictEqual(peerId1.id, peerId2.id)
|
||||
})
|
||||
|
||||
it('sets default capabilities', async () => {
|
||||
assert.deepStrictEqual(accessController.write, [id1.id])
|
||||
})
|
||||
|
||||
it('allows owner to append after creation', async () => {
|
||||
const mockEntry = {
|
||||
identity: id1,
|
||||
v: 1
|
||||
// ...
|
||||
// doesn't matter what we put here, only identity is used for the check
|
||||
}
|
||||
const canAppend = await accessController.canAppend(mockEntry, id1.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('save and load', function () {
|
||||
let accessController, manifest
|
||||
|
||||
before(async () => {
|
||||
accessController = await IPFSAccessController.create(orbitdb1, {
|
||||
write: ['A', 'B', id1.id]
|
||||
})
|
||||
manifest = await accessController.save()
|
||||
await accessController.load(manifest.address)
|
||||
})
|
||||
|
||||
it('has correct capabalities', async () => {
|
||||
assert.deepStrictEqual(accessController.write, ['A', 'B', id1.id])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -0,0 +1,228 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
const io = require('orbit-db-io')
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/orbitdb-access-controller-integration/1'
|
||||
const dbPath2 = './orbitdb/tests/orbitdb-access-controller-integration/2'
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - OrbitDBAccessController Integration (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ id: 'A', keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ id: 'B', keystore: keystore2 })
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) {
|
||||
await orbitdb1.stop()
|
||||
}
|
||||
|
||||
if (orbitdb2) {
|
||||
await orbitdb2.stop()
|
||||
}
|
||||
|
||||
if (ipfsd1) {
|
||||
await stopIpfs(ipfsd1)
|
||||
}
|
||||
|
||||
if (ipfsd2) {
|
||||
await stopIpfs(ipfsd2)
|
||||
}
|
||||
})
|
||||
|
||||
describe('OrbitDB Integration', function () {
|
||||
let db, db2
|
||||
let dbManifest, acManifest
|
||||
|
||||
before(async () => {
|
||||
db = await orbitdb1.feed('AABB', {
|
||||
identity: id1,
|
||||
accessController: {
|
||||
type: 'orbitdb',
|
||||
write: [id1.id]
|
||||
}
|
||||
})
|
||||
|
||||
db2 = await orbitdb2.feed(db.address, { identity: id2 })
|
||||
await db2.load()
|
||||
|
||||
dbManifest = await io.read(ipfs1, db.address.root)
|
||||
const hash = dbManifest.accessController.split('/').pop()
|
||||
acManifest = await io.read(ipfs1, hash)
|
||||
})
|
||||
|
||||
it('has the correct access rights after creating the database', async () => {
|
||||
assert.deepStrictEqual(db.access.capabilities, {
|
||||
admin: new Set([id1.id]),
|
||||
write: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('makes database use the correct access controller', async () => {
|
||||
assert.strictEqual(acManifest.params.address, db.access._db.address.toString())
|
||||
})
|
||||
|
||||
it('saves database manifest file locally', async () => {
|
||||
assert.notStrictEqual(dbManifest, null)
|
||||
})
|
||||
|
||||
it('saves access controller manifest file locally', async () => {
|
||||
assert.notStrictEqual(acManifest, null)
|
||||
})
|
||||
|
||||
describe('database manifest', () => {
|
||||
it('has correct name', async () => {
|
||||
assert.strictEqual(dbManifest.name, 'AABB')
|
||||
})
|
||||
|
||||
it('has correct type', async () => {
|
||||
assert.strictEqual(dbManifest.type, 'feed')
|
||||
})
|
||||
|
||||
it('has correct address', async () => {
|
||||
assert.notStrictEqual(dbManifest.accessController, null)
|
||||
assert.strictEqual(dbManifest.accessController.indexOf('/ipfs'), 0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('access controller manifest', () => {
|
||||
it('has correct type', async () => {
|
||||
assert.strictEqual(acManifest.type, 'orbitdb')
|
||||
})
|
||||
|
||||
it('has correct address', async () => {
|
||||
assert.strictEqual(acManifest.params.address.indexOf('/orbitdb'), 0)
|
||||
assert.strictEqual(acManifest.params.address.split('/').pop(), '_access')
|
||||
})
|
||||
})
|
||||
|
||||
describe('access controls', () => {
|
||||
it('granting access enables to write to the database', async () => {
|
||||
let err
|
||||
try {
|
||||
await db2.add('hello?')
|
||||
assert.strictEqual('Should not end here', false)
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
|
||||
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
||||
|
||||
const doChanges = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// Wait for the second user's AC to notify it was updated
|
||||
db2.access.once('updated', async () => {
|
||||
// Wait for the first user's db to replicate the update
|
||||
db.events.once('replicated', () => {
|
||||
// FIXME: timeout to get rid of the "libp2p node not started yet" errors
|
||||
setTimeout(() => resolve(), 1000)
|
||||
})
|
||||
// Try adding something again
|
||||
await db2.add('hello!')
|
||||
})
|
||||
// Give access to the second user
|
||||
db.access.grant('write', id2.id)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
await doChanges()
|
||||
const res1 = await db.iterator().collect().map(e => e.payload.value)
|
||||
const res2 = await db2.iterator().collect().map(e => e.payload.value)
|
||||
assert.deepStrictEqual(res1, ['hello!'])
|
||||
assert.deepStrictEqual(res2, ['hello!'])
|
||||
})
|
||||
|
||||
it('can\'t grant access if doesn\'t have write access', async () => {
|
||||
let err
|
||||
try {
|
||||
await db2.access.grant('write', id2.id)
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
||||
})
|
||||
|
||||
it('can\'t revoke access if doesn\'t have write access', async () => {
|
||||
let err
|
||||
try {
|
||||
await db2.access.revoke('write', id1.id)
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
||||
})
|
||||
|
||||
it('revoking access disables ability to write to the database', async () => {
|
||||
const getError = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// Wait for the second user's AC to notify it was updated
|
||||
db2.access.once('updated', async () => {
|
||||
let err
|
||||
try {
|
||||
// Try adding something again
|
||||
await db2.add('hello?')
|
||||
} catch (e) {
|
||||
err = e.toString()
|
||||
}
|
||||
resolve(err)
|
||||
})
|
||||
// Revoke user's access
|
||||
db.access.revoke('write', id2.id)
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
const err = await getError()
|
||||
assert.strictEqual(err, `Error: Could not append entry, key "${db2.identity.id}" is not allowed to write to the log`)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
// TODO: use two separate peers for testing the AC
|
||||
// TODO: add tests for revocation correctness with a database (integration tests)
|
||||
})
|
338
test/access-controllers/orbit-db-access-controller.test.js
Normal file
338
test/access-controllers/orbit-db-access-controller.test.js
Normal file
@ -0,0 +1,338 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const rmrf = require('rimraf')
|
||||
const OrbitDB = require('../../src/OrbitDB.js')
|
||||
const IdentityProvider = require('orbit-db-identity-provider')
|
||||
const Keystore = require('orbit-db-keystore')
|
||||
const OrbitDBAccessController = require('orbit-db-access-controllers/src/orbitdb-access-controller')
|
||||
const AccessControllers = require('orbit-db-access-controllers')
|
||||
|
||||
// Include test utilities
|
||||
const {
|
||||
config,
|
||||
startIpfs,
|
||||
stopIpfs,
|
||||
testAPIs
|
||||
} = require('orbit-db-test-utils')
|
||||
|
||||
const dbPath1 = './orbitdb/tests/orbitdb-access-controller/1'
|
||||
const dbPath2 = './orbitdb/tests/orbitdb-access-controller/2'
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - OrbitDBAccessController (${API})`, function () {
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd1, ipfsd2, ipfs1, ipfs2, id1, id2
|
||||
let orbitdb1, orbitdb2
|
||||
|
||||
before(async () => {
|
||||
rmrf.sync(dbPath1)
|
||||
rmrf.sync(dbPath2)
|
||||
ipfsd1 = await startIpfs(API, config.daemon1)
|
||||
ipfsd2 = await startIpfs(API, config.daemon2)
|
||||
ipfs1 = ipfsd1.api
|
||||
ipfs2 = ipfsd2.api
|
||||
|
||||
const keystore1 = new Keystore(dbPath1 + '/keys')
|
||||
const keystore2 = new Keystore(dbPath2 + '/keys')
|
||||
|
||||
id1 = await IdentityProvider.createIdentity({ id: 'A', keystore: keystore1 })
|
||||
id2 = await IdentityProvider.createIdentity({ id: 'B', keystore: keystore2 })
|
||||
|
||||
orbitdb1 = await OrbitDB.createInstance(ipfs1, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath1,
|
||||
identity: id1
|
||||
})
|
||||
|
||||
orbitdb2 = await OrbitDB.createInstance(ipfs2, {
|
||||
AccessControllers: AccessControllers,
|
||||
directory: dbPath2,
|
||||
identity: id2
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (orbitdb1) {
|
||||
await orbitdb1.stop()
|
||||
}
|
||||
|
||||
if (orbitdb2) {
|
||||
await orbitdb2.stop()
|
||||
}
|
||||
|
||||
if (ipfsd1) {
|
||||
await stopIpfs(ipfsd1)
|
||||
}
|
||||
|
||||
if (ipfsd2) {
|
||||
await stopIpfs(ipfsd2)
|
||||
}
|
||||
})
|
||||
|
||||
describe('Constructor', function () {
|
||||
let accessController
|
||||
|
||||
before(async () => {
|
||||
accessController = await OrbitDBAccessController.create(orbitdb1)
|
||||
})
|
||||
|
||||
it('creates an access controller', () => {
|
||||
assert.notStrictEqual(accessController, null)
|
||||
assert.notStrictEqual(accessController, undefined)
|
||||
})
|
||||
|
||||
it('sets the controller type', () => {
|
||||
assert.strictEqual(accessController.type, 'orbitdb')
|
||||
})
|
||||
|
||||
it('has OrbitDB instance', async () => {
|
||||
assert.notStrictEqual(accessController._orbitdb, null)
|
||||
assert.strictEqual(accessController._orbitdb.id, orbitdb1.id)
|
||||
})
|
||||
|
||||
it('has IPFS instance', async () => {
|
||||
const peerId1 = await accessController._orbitdb._ipfs.id()
|
||||
const peerId2 = await ipfs1.id()
|
||||
assert.strictEqual(peerId1.id, peerId2.id)
|
||||
})
|
||||
|
||||
it('sets default capabilities', async () => {
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('allows owner to append after creation', async () => {
|
||||
const mockEntry = {
|
||||
identity: id1
|
||||
// ...
|
||||
// doesn't matter what we put here, only identity is used for the check
|
||||
}
|
||||
const canAppend = await accessController.canAppend(mockEntry, id1.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('grant', function () {
|
||||
let accessController
|
||||
|
||||
before(async () => {
|
||||
accessController = new OrbitDBAccessController(orbitdb1)
|
||||
await accessController.load('testdb/add')
|
||||
})
|
||||
|
||||
it('loads the root access controller from IPFS', () => {
|
||||
assert.strictEqual(accessController._db.access.type, 'ipfs')
|
||||
assert.deepStrictEqual(accessController._db.access.write, [id1.id])
|
||||
})
|
||||
|
||||
it('adds a capability', async () => {
|
||||
try {
|
||||
await accessController.grant('write', id1.id)
|
||||
} catch (e) {
|
||||
assert(e, null)
|
||||
}
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id]),
|
||||
write: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('adds more capabilities', async () => {
|
||||
try {
|
||||
await accessController.grant('read', 'ABCD')
|
||||
await accessController.grant('delete', 'ABCD')
|
||||
} catch (e) {
|
||||
assert.strictEqual(e, null)
|
||||
}
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id]),
|
||||
write: new Set([id1.id]),
|
||||
read: new Set(['ABCD']),
|
||||
delete: new Set(['ABCD'])
|
||||
})
|
||||
})
|
||||
|
||||
it('emit \'updated\' event when a capability was added', async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
accessController.on('updated', () => {
|
||||
try {
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id]),
|
||||
write: new Set([id1.id]),
|
||||
read: new Set(['ABCD', 'AXES']),
|
||||
delete: new Set(['ABCD'])
|
||||
})
|
||||
resolve()
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
accessController.grant('read', 'AXES')
|
||||
})
|
||||
})
|
||||
|
||||
it('can append after acquiring capability', async () => {
|
||||
try {
|
||||
await accessController.grant('write', id1.id)
|
||||
await accessController.grant('write', id2.id)
|
||||
} catch (e) {
|
||||
assert(e, null)
|
||||
}
|
||||
const mockEntry1 = {
|
||||
identity: id1
|
||||
}
|
||||
const mockEntry2 = {
|
||||
identity: id2
|
||||
}
|
||||
const canAppend1 = await accessController.canAppend(mockEntry1, id1.provider)
|
||||
const canAppend2 = await accessController.canAppend(mockEntry2, id2.provider)
|
||||
assert.strictEqual(canAppend1, true)
|
||||
assert.strictEqual(canAppend2, true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('revoke', function () {
|
||||
let accessController
|
||||
|
||||
before(async () => {
|
||||
accessController = new OrbitDBAccessController(orbitdb1)
|
||||
await accessController.load('testdb/remove')
|
||||
})
|
||||
|
||||
it('removes a capability', async () => {
|
||||
try {
|
||||
await accessController.grant('write', id1.id)
|
||||
await accessController.grant('write', 'AABB')
|
||||
await accessController.revoke('write', 'AABB')
|
||||
} catch (e) {
|
||||
assert.strictEqual(e, null)
|
||||
}
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id]),
|
||||
write: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('can remove the creator\'s write access', async () => {
|
||||
try {
|
||||
await accessController.revoke('write', id1.id)
|
||||
} catch (e) {
|
||||
assert.strictEqual(e, null)
|
||||
}
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('can\'t remove the creator\'s admin access', async () => {
|
||||
try {
|
||||
await accessController.revoke('admin', id1.id)
|
||||
} catch (e) {
|
||||
assert.strictEqual(e, null)
|
||||
}
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('removes more capabilities', async () => {
|
||||
try {
|
||||
await accessController.grant('read', 'ABCD')
|
||||
await accessController.grant('delete', 'ABCD')
|
||||
await accessController.grant('write', id1.id)
|
||||
await accessController.revoke('read', 'ABCDE')
|
||||
await accessController.revoke('delete', 'ABCDE')
|
||||
} catch (e) {
|
||||
assert.strictEqual(e, null)
|
||||
}
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id]),
|
||||
delete: new Set(['ABCD']),
|
||||
read: new Set(['ABCD']),
|
||||
write: new Set([id1.id])
|
||||
})
|
||||
})
|
||||
|
||||
it('can\'t append after revoking capability', async () => {
|
||||
try {
|
||||
await accessController.grant('write', id2.id)
|
||||
await accessController.revoke('write', id2.id)
|
||||
} catch (e) {
|
||||
assert(e, null)
|
||||
}
|
||||
const mockEntry1 = {
|
||||
identity: id1
|
||||
}
|
||||
const mockEntry2 = {
|
||||
identity: id2
|
||||
}
|
||||
const canAppend = await accessController.canAppend(mockEntry1, id1.provider)
|
||||
const noAppend = await accessController.canAppend(mockEntry2, id2.provider)
|
||||
assert.strictEqual(canAppend, true)
|
||||
assert.strictEqual(noAppend, false)
|
||||
})
|
||||
|
||||
it('emits \'updated\' event when a capability was removed', async () => {
|
||||
await accessController.grant('admin', 'cats')
|
||||
await accessController.grant('admin', 'dogs')
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
accessController.on('updated', () => {
|
||||
try {
|
||||
assert.deepStrictEqual(accessController.capabilities, {
|
||||
admin: new Set([id1.id, 'dogs']),
|
||||
delete: new Set(['ABCD']),
|
||||
read: new Set(['ABCD']),
|
||||
write: new Set([id1.id])
|
||||
})
|
||||
resolve()
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
accessController.revoke('admin', 'cats')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('save and load', function () {
|
||||
let accessController, dbName
|
||||
|
||||
before(async () => {
|
||||
dbName = 'testdb-load-' + new Date().getTime()
|
||||
accessController = new OrbitDBAccessController(orbitdb1)
|
||||
await accessController.load(dbName)
|
||||
await accessController.grant('write', 'A')
|
||||
await accessController.grant('write', 'B')
|
||||
await accessController.grant('write', 'C')
|
||||
await accessController.grant('write', 'C') // double entry
|
||||
await accessController.grant('another', 'AA')
|
||||
await accessController.grant('another', 'BB')
|
||||
await accessController.revoke('another', 'AA')
|
||||
await accessController.grant('admin', id1.id)
|
||||
return new Promise((resolve) => {
|
||||
// Test that the access controller emits 'updated' after it was loaded
|
||||
accessController.on('updated', () => resolve())
|
||||
accessController.load(accessController.address)
|
||||
})
|
||||
})
|
||||
|
||||
it('has the correct database address for the internal db', async () => {
|
||||
const addr = accessController._db.address.toString().split('/')
|
||||
assert.strictEqual(addr[addr.length - 1], '_access')
|
||||
assert.strictEqual(addr[addr.length - 2], dbName)
|
||||
})
|
||||
|
||||
it('has correct capabalities', async () => {
|
||||
assert.deepStrictEqual(accessController.get('admin'), new Set([id1.id]))
|
||||
assert.deepStrictEqual(accessController.get('write'), new Set(['A', 'B', 'C']))
|
||||
assert.deepStrictEqual(accessController.get('another'), new Set(['BB']))
|
||||
})
|
||||
})
|
||||
})
|
||||
// TODO: use two separate peers for testing the AC
|
||||
// TODO: add tests for revocation correctness with a database (integration tests)
|
||||
})
|
75
test/access-controllers/utils/config.js
Normal file
75
test/access-controllers/utils/config.js
Normal file
@ -0,0 +1,75 @@
|
||||
module.exports = {
|
||||
timeout: 30000,
|
||||
dbname: 'orbit-db-tests',
|
||||
defaultIpfsConfig: {
|
||||
start: true,
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
},
|
||||
config: {
|
||||
Addresses: {
|
||||
API: '/ip4/127.0.0.1/tcp/0',
|
||||
Swarm: ['/ip4/0.0.0.0/tcp/0'],
|
||||
Gateway: '/ip4/0.0.0.0/tcp/0'
|
||||
},
|
||||
Bootstrap: [],
|
||||
Discovery: {
|
||||
MDNS: {
|
||||
Enabled: true,
|
||||
Interval: 1
|
||||
},
|
||||
webRTCStar: {
|
||||
Enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
daemon1: {
|
||||
repo: './ipfs/orbitdb/tests/daemon1',
|
||||
start: true,
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
},
|
||||
config: {
|
||||
Addresses: {
|
||||
API: '/ip4/127.0.0.1/tcp/0',
|
||||
Swarm: ['/ip4/0.0.0.0/tcp/0'],
|
||||
Gateway: '/ip4/0.0.0.0/tcp/0'
|
||||
},
|
||||
Bootstrap: [],
|
||||
Discovery: {
|
||||
MDNS: {
|
||||
Enabled: true,
|
||||
Interval: 1
|
||||
},
|
||||
webRTCStar: {
|
||||
Enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
daemon2: {
|
||||
repo: './ipfs/orbitdb/tests/daemon2',
|
||||
start: true,
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
},
|
||||
config: {
|
||||
Addresses: {
|
||||
API: '/ip4/127.0.0.1/tcp/0',
|
||||
Swarm: ['/ip4/0.0.0.0/tcp/0'],
|
||||
Gateway: '/ip4/0.0.0.0/tcp/0'
|
||||
},
|
||||
Bootstrap: [],
|
||||
Discovery: {
|
||||
MDNS: {
|
||||
Enabled: true,
|
||||
Interval: 1
|
||||
},
|
||||
webRTCStar: {
|
||||
Enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
test/access-controllers/utils/connect-peers.js
Normal file
10
test/access-controllers/utils/connect-peers.js
Normal file
@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const connectIpfsNodes = async (ipfs1, ipfs2) => {
|
||||
const id1 = await ipfs1.id()
|
||||
const id2 = await ipfs2.id()
|
||||
await ipfs1.swarm.connect(id2.addresses[0])
|
||||
await ipfs2.swarm.connect(id1.addresses[0])
|
||||
}
|
||||
|
||||
module.exports = connectIpfsNodes
|
53
test/access-controllers/utils/custom-test-keystore.js
Normal file
53
test/access-controllers/utils/custom-test-keystore.js
Normal file
@ -0,0 +1,53 @@
|
||||
const EC = require('elliptic').ec
|
||||
const ec = new EC('secp256k1')
|
||||
|
||||
/**
|
||||
* A custom keystore example
|
||||
*/
|
||||
class CustomTestKeystore {
|
||||
constructor (signer) {
|
||||
this.createKey()
|
||||
}
|
||||
|
||||
createKey () {
|
||||
const key = ec.genKeyPair()
|
||||
this.key = ec.keyPair({
|
||||
pub: key.getPublic('hex'),
|
||||
priv: key.getPrivate('hex'),
|
||||
privEnc: 'hex',
|
||||
pubEnc: 'hex'
|
||||
})
|
||||
|
||||
return this.key
|
||||
}
|
||||
|
||||
getKey () {
|
||||
return this.key
|
||||
}
|
||||
|
||||
// TODO: check if this is really in use
|
||||
generateKey () {
|
||||
return Promise.resolve(this.createKey())
|
||||
}
|
||||
|
||||
importPublicKey (key) {
|
||||
return Promise.resolve(ec.keyFromPublic(key, 'hex'))
|
||||
}
|
||||
|
||||
importPrivateKey (key) {
|
||||
return Promise.resolve(ec.keyFromPrivate(key, 'hex'))
|
||||
}
|
||||
|
||||
sign (key, data) {
|
||||
const sig = ec.sign(data, key)
|
||||
return Promise.resolve(sig.toDER('hex'))
|
||||
}
|
||||
|
||||
verify (signature, key, data) {
|
||||
let res = false
|
||||
res = ec.verify(data, signature, key)
|
||||
return Promise.resolve(res)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new CustomTestKeystore()
|
8
test/access-controllers/utils/index.js
Normal file
8
test/access-controllers/utils/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
exports.config = require('./config.js')
|
||||
exports.testAPIs = require('./test-apis')
|
||||
exports.startIpfs = require('./start-ipfs')
|
||||
exports.stopIpfs = require('./stop-ipfs')
|
||||
exports.waitForPeers = require('./wait-for-peers')
|
||||
exports.connectPeers = require('./connect-peers')
|
||||
exports.MemStore = require('./mem-store')
|
||||
exports.CustomTestKeystore = require('./custom-test-keystore')
|
70
test/access-controllers/utils/mem-store.js
Normal file
70
test/access-controllers/utils/mem-store.js
Normal file
@ -0,0 +1,70 @@
|
||||
'use strict'
|
||||
|
||||
const multihashing = require('multihashing-async')
|
||||
const mh = require('multihashes')
|
||||
|
||||
const defaultHashAlg = 'sha2-256'
|
||||
|
||||
// 'use strict'
|
||||
|
||||
// const ImmutableDB = require('./immutabledb-interface')
|
||||
|
||||
const createMultihash = (data, hashAlg) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
multihashing(data, hashAlg || defaultHashAlg, (err, multihash) => {
|
||||
if (err) { return reject(err) }
|
||||
|
||||
resolve(mh.toB58String(multihash))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// const LRU = require('lru')
|
||||
// const ImmutableDB = require('./immutabledb-interface')
|
||||
// const createMultihash = require('./create-multihash')
|
||||
|
||||
/* Memory store using an LRU cache */
|
||||
class MemStore {
|
||||
constructor () {
|
||||
this._store = {}// new LRU(1000)
|
||||
}
|
||||
|
||||
async put (value) {
|
||||
const data = value// new Buffer(JSON.stringify(value))
|
||||
const hash = await createMultihash(data)
|
||||
// console.log(this._store)
|
||||
// this._store.set(hash, data)
|
||||
if (!this._store) this._store = {}
|
||||
// console.log(this._store)
|
||||
// console.log(hash, data)
|
||||
this._store[hash] = data
|
||||
// return hash
|
||||
return {
|
||||
toJSON: () => {
|
||||
return {
|
||||
data: value,
|
||||
multihash: hash
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async get (key) {
|
||||
// if (data) {
|
||||
// const value = JSON.parse(data)
|
||||
// return value
|
||||
// }
|
||||
|
||||
// return data
|
||||
return {
|
||||
toJSON: () => {
|
||||
return {
|
||||
data: this._store[key],
|
||||
multihash: key
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MemStore
|
43
test/access-controllers/utils/start-ipfs.js
Normal file
43
test/access-controllers/utils/start-ipfs.js
Normal file
@ -0,0 +1,43 @@
|
||||
'use strict'
|
||||
|
||||
const IPFSFactory = require('ipfsd-ctl')
|
||||
const testAPIs = require('./test-apis')
|
||||
|
||||
/**
|
||||
* Start an IPFS instance
|
||||
* @param {Object} config [IPFS configuration to use]
|
||||
* @return {[Promise<IPFS>]} [IPFS instance]
|
||||
*/
|
||||
const startIpfs = (type, config = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!testAPIs[type]) {
|
||||
reject(new Error(`Wanted API type ${JSON.stringify(type)} is unknown. Available types: ${Object.keys(testAPIs).join(', ')}`))
|
||||
}
|
||||
|
||||
// If we're starting a process, pass command line arguments to it
|
||||
if (!config.args) {
|
||||
config.args = ['--enable-pubsub-experiment']
|
||||
}
|
||||
|
||||
// Spawn an IPFS daemon (type defined in)
|
||||
IPFSFactory
|
||||
.create(testAPIs[type])
|
||||
.spawn(config, async (err, ipfsd) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
|
||||
// Monkey patch _peerInfo to the ipfs api/instance
|
||||
// to make js-ipfs-api compatible with js-ipfs
|
||||
// TODO: Get IPFS id via coherent API call (without it being asynchronous)
|
||||
if (!ipfsd.api._peerInfo) {
|
||||
const { id } = await ipfsd.api.id()
|
||||
ipfsd.api._peerInfo = { id: { _idB58String: id } }
|
||||
}
|
||||
|
||||
resolve(ipfsd)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = startIpfs
|
17
test/access-controllers/utils/stop-ipfs.js
Normal file
17
test/access-controllers/utils/stop-ipfs.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Stop an IPFS or ipfsd-ctl instance
|
||||
* @param {Object} config [IPFS ipfsd-ctl to stop]
|
||||
* @return {None}
|
||||
*/
|
||||
const stopIpfs = (ipfs) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipfs.stop((err) => {
|
||||
if (err) { reject(err) }
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = stopIpfs
|
30
test/access-controllers/utils/test-apis.js
Normal file
30
test/access-controllers/utils/test-apis.js
Normal file
@ -0,0 +1,30 @@
|
||||
const IPFS = require('ipfs')
|
||||
|
||||
/**
|
||||
* IPFS daemons to run the tests with.
|
||||
*/
|
||||
|
||||
// Available daemon types are defined in:
|
||||
// https://github.com/ipfs/js-ipfsd-ctl#ipfsfactory---const-f--ipfsfactorycreateoptions
|
||||
const jsIpfs = {
|
||||
'js-ipfs': {
|
||||
type: 'proc',
|
||||
exec: IPFS
|
||||
}
|
||||
}
|
||||
|
||||
const goIpfs = {
|
||||
'go-ipfs': {
|
||||
type: 'go'
|
||||
}
|
||||
}
|
||||
|
||||
// By default, we run tests against js-ipfs.
|
||||
let testAPIs = Object.assign({}, jsIpfs)
|
||||
|
||||
// Setting env variable 'TEST=all' will make tests run with js-ipfs and go-ipfs.
|
||||
// Setting env variable 'TEST=go' will make tests run with go-ipfs.
|
||||
// Eg. 'TEST=go mocha' runs tests with go-ipfs
|
||||
if (process.env.TEST === 'all') { testAPIs = Object.assign({}, testAPIs, goIpfs) } else if (process.env.TEST === 'go') { testAPIs = Object.assign({}, goIpfs) }
|
||||
|
||||
module.exports = testAPIs
|
16
test/access-controllers/utils/wait-for-peers.js
Normal file
16
test/access-controllers/utils/wait-for-peers.js
Normal file
@ -0,0 +1,16 @@
|
||||
'use strict'
|
||||
|
||||
const waitForPeers = (ipfs, peersToWait, topic, callback) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const i = setInterval(async () => {
|
||||
const peers = await ipfs.pubsub.peers(topic)
|
||||
const hasAllPeers = peersToWait.map((e) => peers.includes(e)).filter((e) => e === false).length === 0
|
||||
if (hasAllPeers) {
|
||||
clearInterval(i)
|
||||
resolve()
|
||||
}
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = waitForPeers
|
Loading…
x
Reference in New Issue
Block a user