我在带有注册表的基于角色的权限的合同网络上做了一些工作。注册表应该跟踪合同地址,以便每次我部署所有内容时都不必手动输入地址。我按此顺序部署:
注册表 UserCRUD 角色CRUD 权限CRUD UserRoles 角色权限 PermissionGate(这是我正在测试的对象) 部署完每个合同后,将其添加到注册表中,或者如果它需要填充地址(这很罕见),请输入0x00000 ...和合同名称,然后稍后再进行编辑。我正在测试PermissionGate,这是我要尝试做的真正内容。它检查ID为5的所有角色。(我设置了5个权限,然后设置了某些角色,以便某些角色确实具有该权限)。应该按ID将这些角色保存在数组中,然后当用户尝试执行添加功能(具有门)时,门会查询UserRoles以确定他们是否具有这些角色。 从理论上讲,只有具有ID 5权限的角色的人才能执行添加功能,因为它上面带有Gate修饰符。不幸的是,每次我尝试运行PermissionGate合同时,它都会使我的浏览器崩溃。我已经尝试使用谷歌浏览器,Firefox和Safari。我还尝试增加委托给浏览器的内存量。看来这是Remix或solidity编译器的问题。我真的很感激这个错误已得到修复,或者意识到我犯了一些愚蠢的错误,使Remix无法事先识别。我在下面的坚固性文件中附加了ZIP。谢谢! 实用性^ 0.4.24;
contract UserCRUD {
// constructor() public {
// addUser(msg.sender, "Charlie", "Dalton");
// }
struct User {
string fName;
string lName;
uint index;
}
mapping(address => User) private users;
address[] private userIndex;
function isUser(address _userAddress)
public
constant
returns(bool isIndeed)
{
if(userIndex.length == 0) return false;
return (userIndex[users[_userAddress].index] == _userAddress);
}
function addUser(
address _userAddress,
string _fName,
string _lName)
public
returns(uint index)
{
require(isUser(_userAddress) != true);
users[_userAddress].fName = _fName;
users[_userAddress].lName = _lName;
users[_userAddress].index = userIndex.push(_userAddress)-1;
return userIndex.length-1;
}
function deleteUser(address _userAddress)
public
returns(uint index)
{
require(isUser(_userAddress));
uint rowToDelete = users[_userAddress].index;
address keyToMove = userIndex[userIndex.length-1];
userIndex[rowToDelete] = keyToMove; //https://cdn-images-1.medium.com/max/800/1*uAgZIY1PLmeleguryyeLWQ.png
users[keyToMove].index = rowToDelete;
userIndex.length--;
return rowToDelete;
}
function getUser(address _userAddress)
public
constant
returns(string fName, string lName, uint index)
{
require(isUser(_userAddress));
return(
users[_userAddress].fName,
users[_userAddress].lName,
users[_userAddress].index);
}
function getUserFName(address _userAddress)
public
constant
returns(string fName)
{
require(isUser(_userAddress));
return(
users[_userAddress].fName);
}
function updateUserFName(address _userAddress, string _fName)
public
returns(bool success)
{
require(isUser(_userAddress));
users[_userAddress].fName = _fName;
return true;
}
function updateUserLName(address _userAddress, string _lName)
public
returns(bool success)
{
require(isUser(_userAddress));
users[_userAddress].lName = _lName;
return true;
}
function getUserCount()
public
constant
returns(uint count)
{
return userIndex.length;
}
function getUserAtIndex(uint index)
public
constant
returns(address _userAddress)
{
return userIndex[index];
}
}
contract RoleCRUD {
struct RoleStruct {
string roleName;
uint index;
bool validity;
}
mapping(uint => RoleStruct) private roles;
uint[] private roleIndex;
function isRole(uint _roleId)
public
constant
returns(bool isIndeed)
{
if(roleIndex.length == 0){
return false;
}
else if(roles[_roleId].validity == false) {
return false;
}
return (roleIndex[roles[_roleId].index] == _roleId);
}
function createRole(
uint _roleId,
string _roleName)
public
returns(uint index)
{
require(!isRole(_roleId));
roles[_roleId].roleName = _roleName;
roles[_roleId].index = roleIndex.push(_roleId)-1;
roles[_roleId].validity = true;
return roleIndex.length-1;
}
/* function deleteUser(uint _userId)
public
returns(uint index)
{
require(isRole(_roleId));
uint rowToDelete = userStructs[userAddress].index;
address keyToMove = userIndex[userIndex.length-1];
userIndex[rowToDelete] = keyToMove;
userStructs[keyToMove].index = rowToDelete;
userIndex.length--;
return rowToDelete;
} */
function deleteRole(uint _roleId)
public
{
require(isRole(_roleId));
roles[_roleId].roleName = ("Sorry, but this role is no longer valid");
roles[_roleId].index = 404;
roles[_roleId].validity = false;
}
function readRole(uint _roleId)
public
constant
returns(string _roleName, uint _index)
{
require(isRole(_roleId));
return(
roles[_roleId].roleName,
roles[_roleId].index);
}
function updateRoleName(uint _roleId, string _roleName)
public
{
require(isRole(_roleId));
roles[_roleId].roleName = _roleName;
}
function getRoleCount() //not completely accurate because there are still the roles that were soft deleted
public
view
returns(uint count)
{
return roleIndex.length;
}
/* function getUserAtIndex(uint index)
public
constant
returns(address userAddress)
{
return userIndex[index];
} */
}
contract PermissionCRUD {
struct PermissionStruct {
string permissionName;
uint registryRefId;
uint index;
bool validity;
}
mapping(uint => PermissionStruct) private permissions;
uint[] private permissionIndex;
function isPermission(uint _permissionId)
public
constant
returns(bool isIndeed)
{
if(permissionIndex.length == 0){
return false;
}
else if(permissions[_permissionId].validity == false) {
return false;
}
return (permissionIndex[permissions[_permissionId].index] == _permissionId);
}
function createPermission(
uint _permissionId,
string _permissionName,
uint _registryRefId)
public
returns(uint index)
{
require(!isPermission(_permissionId));
permissions[_permissionId].permissionName = _permissionName;
permissions[_permissionId].index = permissionIndex.push(_permissionId)-1;
permissions[_permissionId].registryRefId = _registryRefId;
permissions[_permissionId].validity = true;
return permissionIndex.length-1;
}
/* function deleteUser(uint _userId)
public
returns(uint index)
{
require(isRole(_roleId));
uint rowToDelete = userStructs[userAddress].index;
address keyToMove = userIndex[userIndex.length-1];
userIndex[rowToDelete] = keyToMove;
userStructs[keyToMove].index = rowToDelete;
userIndex.length--;
return rowToDelete;
} */
function deletePermission(uint _permissionId)
public
{
require(isPermission(_permissionId));
permissions[_permissionId].permissionName = ("Sorry, but this permission is no longer valid");
permissions[_permissionId].registryRefId = 10000; // a big number, we will never have that many contracts deployed
permissions[_permissionId].index = 404;
permissions[_permissionId].validity = false;
}
function readPermission(uint _permissionId)
public
view
returns(string _permissionName, uint _registryRefId, uint _index)
{
require(isPermission(_permissionId));
return(
permissions[_permissionId].permissionName,
permissions[_permissionId].registryRefId,
permissions[_permissionId].index);
}
function updatePermissionName(uint _permissionId, string _permissionName)
public
{
require(isPermission(_permissionId));
permissions[_permissionId].permissionName = _permissionName;
}
function updatePermissionRegistryRef(uint _permissionId, uint _registryRefId)
public
{
require(isPermission(_permissionId));
permissions[_permissionId].registryRefId = _registryRefId;
}
function getPermissionCount() //not completely accurate because there are still the roles that were soft deleted
public
view
returns(uint count)
{
return permissionIndex.length;
}
/* function getUserAtIndex(uint index)
public
constant
returns(address userAddress)
{
return userIndex[index];
} */
}
contract UserRoles {
Registry reg = Registry(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);
UserCRUD uCTL = UserCRUD(reg.getContractAddress(0));
RoleCRUD rCTL = RoleCRUD(reg.getContractAddress(1));
mapping(address => mapping(uint => bool)) roles;
constructor() public {
//
}
function assignRole (address _userAddress, uint _roleId) public {
require(uCTL.isUser(_userAddress)); //can delete the == true
require(rCTL.isRole(_roleId)); //can delete the == true
roles[_userAddress][_roleId] = true;
}
function unassignRole (address _userAddress, uint _roleId) public {
require(uCTL.isUser(_userAddress) == true); //can delete the == true
require(rCTL.isRole(_roleId) == true); //can delete the == true
roles[_userAddress][_roleId] = false;
}
function isAssignedRole (address _userAddress, uint _roleId) public view returns(bool) {
if(uCTL.isUser(_userAddress) == false) {
return false;
}
if(rCTL.isRole(_roleId) == false) {
return false;
}
return roles[_userAddress][_roleId];
}
}
contract RolePermissions {
Registry reg = Registry(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);
RoleCRUD rCTL = RoleCRUD(reg.getContractAddress(1));
PermissionCRUD pCTL = PermissionCRUD(reg.getContractAddress(2));
UserRoles URCTL = UserRoles(reg.getContractAddress(3));
//RolePermissions RPCTL = RolePermissions(reg.getContractAddress(4))
mapping(uint => mapping(uint => bool)) permissions;
function assignPermission (uint _roleId, uint _permissionId) public {
require(rCTL.isRole(_roleId));
require(pCTL.isPermission(_permissionId));
permissions[_roleId][_permissionId] = true;
}
function unassignPermission (uint _roleId, uint _permissionId) public {
require(rCTL.isRole(_roleId) == true); //can delete the == true
require(pCTL.isPermission(_permissionId) == true); //can delete the == true
permissions[_roleId][_permissionId] = false;
}
function isAssignedPermission (uint _roleId, uint _permissionId) public view returns(bool) {
if(rCTL.isRole(_roleId) == false) {
return false;
}
if(rCTL.isRole(_roleId) == false) {
return false;
}
return permissions[_roleId][_permissionId];
}
}
contract Registry {
address[] public admins;
address creator;
uint128 idCounter;
uint[] public contractIds;
constructor() public {
creator = msg.sender;
addAdmin(creator);
}
struct InxeptContract {
address contractAddress;
string contractName;
}
mapping(uint => InxeptContract) contracts;
function addContract(address _contractAddress, string _contractName) public adminOnly {
contracts[idCounter].contractAddress = _contractAddress;
contracts[idCounter].contractName = _contractName;
contractIds.push(idCounter) -1;
idCounter++;
}
function removeContract(uint _contractId) public adminOnly {
delete contracts[_contractId];
delete contractIds[_contractId];
contractIds[_contractId]--;
}
function updateContract(uint _contractId, address _newContractAddress, string _newContractName) public {
contracts[_contractId].contractAddress = _newContractAddress;
contracts[_contractId].contractName = _newContractName;
}
function getContractAddress(uint _contractId) public view returns(address) {
return contracts[_contractId].contractAddress;
}
function getContractName(uint _contractId) public view returns(string) {
return contracts[_contractId].contractName;
}
function getContracts() public view returns(uint[]) {
uint[] cleanedIds;
for(uint i = 0; i < contractIds.length; i++) {
if(contractIds[i] < 10000000) {
cleanedIds.push(contractIds[i]);
}
}
return cleanedIds;
}
modifier adminOnly {
if((msg.sender == creator) || anAdmin() ) {
_;
}
}
function anAdmin() public view returns (bool) {
for(uint i = 0; i < admins.length; i++) {
if(admins[i] == msg.sender) {
return true;
}
}
return false;
}
function getAdmins() public view returns(address[]) {
return admins;
}
function addAdmin(address _adminAddress) public adminOnly {
admins.push(_adminAddress);
}
function removeAdmin(address _adminAddress) public adminOnly {
for(uint i = 0; i < admins.length; i++) {
if(admins[i] == _adminAddress) {
delete admins[i];
for(i = 0; i < (admins.length - 1); i++) {
admins[i] = admins[i + 1];
}
admins.length--;
}
}
}
}
contract PermissionGate{
Registry reg = Registry(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);
RoleCRUD rCTL = RoleCRUD(reg.getContractAddress(1));
PermissionCRUD pCTL = PermissionCRUD(reg.getContractAddress(2));
UserRoles URCTL = UserRoles(reg.getContractAddress(3));
RolePermissions RPCTL = RolePermissions(reg.getContractAddress(4));
uint thisContractId = 5;
constructor() public {
checkRoles();
}
uint[] roleIdsThatWork;
uint i;
function checkRoles() public {
uint[] _roleIdsThatWork;
for(i = 0; i < rCTL.getRoleCount(); i++) {
bool makeItEasy = RPCTL.isAssignedPermission(i, thisContractId);
if(makeItEasy == true){
_roleIdsThatWork.push(i);
}
}
roleIdsThatWork = _roleIdsThatWork;
}
modifier Gate {
for(i = 0; i < roleIdsThatWork.length; i++) {
if(URCTL.isAssignedRole(msg.sender, i) == true) {
_;
}
}
}
function add(uint a, uint b) public Gate returns(uint) {
return a + b;
}
}