diff --git a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java index 7a49e2ba..9e76d988 100644 --- a/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java +++ b/source/base/src/main/java/com/jd/blockchain/consts/DataCodes.java @@ -56,8 +56,14 @@ public interface DataCodes { public static final int TX_OP_RESULT = 0x360; // enum types of permissions; - public static final int ENUM_TX_PERMISSIONS = 0x401; - public static final int ENUM_LEDGER_PERMISSIONS = 0x402; + public static final int ENUM_TX_PERMISSION = 0x401; + public static final int ENUM_LEDGER_PERMISSION = 0x402; + public static final int ENUM_MULTI_ROLES_POLICY = 0x403; + + public static final int ROLE_PRIVILEGE = 0x410; + + public static final int ROLE_SET = 0x411; + // contract types of metadata; public static final int METADATA = 0x600; diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AbstractPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AbstractPrivilege.java index f4925a3d..01ba5afd 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AbstractPrivilege.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/AbstractPrivilege.java @@ -12,52 +12,47 @@ import com.jd.blockchain.utils.io.BytesSerializable; */ public abstract class AbstractPrivilege> implements Privilege, BytesSerializable { - private BitSet permissions; + private BitSet permissionBits; + + public AbstractPrivilege() { + permissionBits = new BitSet(); + } public AbstractPrivilege(byte[] codeBytes) { - permissions = BitSet.valueOf(codeBytes); + permissionBits = BitSet.valueOf(codeBytes); } public boolean isEnable(E permission) { - return permissions.get(getCodeIndex(permission)); + return permissionBits.get(getCodeIndex(permission)); } public void enable(E permission) { - permissions.set(getCodeIndex(permission)); + permissionBits.set(getCodeIndex(permission)); } public void disable(E permission) { - permissions.clear(getCodeIndex(permission)); + permissionBits.clear(getCodeIndex(permission)); + } + + @SuppressWarnings("unchecked") + public void enable(E... permissions) { + for (E p : permissions) { + permissionBits.set(getCodeIndex(p)); + } + } + + @SuppressWarnings("unchecked") + public void disable(E... permissions) { + for (E p : permissions) { + permissionBits.clear(getCodeIndex(p)); + } } - -// private int getCodeIndex(E permission) { -// return permission.CODE & 0xFF; -// } protected abstract int getCodeIndex(E permission); @Override public byte[] toBytes() { - return permissions.toByteArray(); - } - -// public boolean[] getPermissionStates() { -// LedgerPermission[] PMs = LedgerPermission.values(); -// -// LedgerPermission maxPermission = Arrays.stream(PMs).max(new Comparator() { -// @Override -// public int compare(LedgerPermission o1, LedgerPermission o2) { -// return getCodeIndex(o1) - getCodeIndex(o2); -// } -// }).get(); -// -// boolean[] states = new boolean[getCodeIndex(maxPermission) + 1]; -// int idx = -1; -// for (LedgerPermission pm : PMs) { -// idx = getCodeIndex(pm); -// states[idx] = permissions.get(idx); -// } -// -// return states; -// } + return permissionBits.toByteArray(); + } + } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPermission.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPermission.java index e5b6b751..2a5cec59 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPermission.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPermission.java @@ -11,7 +11,7 @@ import com.jd.blockchain.consts.DataCodes; * @author huanghaiquan * */ -@EnumContract(code = DataCodes.ENUM_LEDGER_PERMISSIONS) +@EnumContract(code = DataCodes.ENUM_LEDGER_PERMISSION) public enum LedgerPermission { /** diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPrivilege.java index f4efbecb..73cdf9ef 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPrivilege.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerPrivilege.java @@ -8,6 +8,9 @@ package com.jd.blockchain.ledger.core; */ public class LedgerPrivilege extends AbstractPrivilege { + public LedgerPrivilege() { + } + public LedgerPrivilege(byte[] codeBytes) { super(codeBytes); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java index a44dc575..fc8151f3 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerSecurityManager.java @@ -22,11 +22,11 @@ public class LedgerSecurityManager { throw new IllegalStateException("Not implemented!"); } - public Role setRole(String role, LedgerPrivilege privilege) { + public RolePrivilegeAuthorization setRole(String role, LedgerPrivilege privilege) { throw new IllegalStateException("Not implemented!"); } - public Role getRole(String role) { + public RolePrivilegeAuthorization getRole(String role) { throw new IllegalStateException("Not implemented!"); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java index b8dd170b..d17d219f 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java @@ -149,6 +149,22 @@ public class MerkleDataSet implements Transactional, MerkleProvable { } return values; } + + public VersioningKVEntry[] getLatestDataEntries(int fromIndex, int count) { + if (count > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { + throw new IllegalArgumentException("Index out of bound!"); + } + VersioningKVEntry[] values = new VersioningKVEntry[count]; + for (int i = 0; i < count; i++) { + MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); + Bytes dataKey = encodeDataKey(dataNode.getKey()); + values[i] = valueStorage.getEntry(dataKey, dataNode.getVersion()); + } + return values; + } /** * get the data at the specific index; @@ -404,6 +420,11 @@ public class MerkleDataSet implements Transactional, MerkleProvable { return getDataEntry(Bytes.fromString(key)); } + /** + * + * @param key + * @return Null if the key doesn't exist! + */ public VersioningKVEntry getDataEntry(Bytes key) { long latestVersion = getMerkleVersion(key); if (latestVersion < 0) { diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Role.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Role.java deleted file mode 100644 index 7ece80cf..00000000 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Role.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.jd.blockchain.ledger.core; - -public class Role { - - private String name; - - private long version; - - private LedgerPrivilege privilege; - - - - public String getName() { - return name; - } - - public long getVersion() { - return version; - } - - public LedgerPrivilege getPrivilege() { - return privilege; - } - - - -} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RoleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RoleDataSet.java new file mode 100644 index 00000000..6fb3ee65 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RoleDataSet.java @@ -0,0 +1,175 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVEntry; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +public class RoleDataSet implements Transactional, MerkleProvable { + + /** + * 角色名称的最大 Unicode 字符数; + */ + public static final int MAX_ROLE_NAME_LENGTH = 20; + + private MerkleDataSet dataset; + + public RoleDataSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage verStorage) { + dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage); + } + + public RoleDataSet(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { + dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); + } + + @Override + public HashDigest getRootHash() { + return dataset.getRootHash(); + } + + @Override + public MerkleProof getProof(Bytes key) { + return dataset.getProof(key); + } + + @Override + public boolean isUpdated() { + return dataset.isUpdated(); + } + + @Override + public void commit() { + dataset.commit(); + } + + @Override + public void cancel() { + dataset.cancel(); + } + + public long getRoleCount() { + return dataset.getDataCount(); + } + + /** + * 加入新的角色授权;
+ * + * 如果指定的角色已经存在,则引发 {@link LedgerException} 异常; + * + * @param roleName 角色名称;不能超过 {@link #MAX_ROLE_NAME_LENGTH} 个 Unicode 字符; + * @param ledgerPrivilege + * @param txPrivilege + */ + public void addRoleAuthorization(String roleName, LedgerPrivilege ledgerPrivilege, + TransactionPrivilege txPrivilege) { + RolePrivilegeAuthorization roleAuth = new RolePrivilegeAuthorization(roleName, -1, ledgerPrivilege, txPrivilege); + long nv = innerSetRoleAuthorization(roleAuth); + if (nv < 0) { + throw new LedgerException("Role[" + roleName + "] already exist!"); + } + } + + /** + * 设置角色授权;
+ * 如果版本校验不匹配,则返回 -1; + * + * @param roleAuth + * @return + */ + public long innerSetRoleAuthorization(RolePrivilegeAuthorization roleAuth) { + if (roleAuth.getRoleName().length() > MAX_ROLE_NAME_LENGTH) { + throw new LedgerException("Too long role name!"); + } + Bytes key = encodeKey(roleAuth.getRoleName()); + byte[] privilegeBytes = BinaryProtocol.encode(roleAuth, RolePrivilege.class); + return dataset.setValue(key, privilegeBytes, roleAuth.getVersion()); + } + + /** + * 更新角色授权;
+ * 如果指定的角色不存在,或者版本不匹配,则引发 {@link LedgerException} 异常; + * + * @param participant + */ + public void updateRoleAuthorization(RolePrivilegeAuthorization roleAuth) { + long nv = innerSetRoleAuthorization(roleAuth); + if (nv < 0) { + throw new LedgerException("Update to RoleAuthorization[" + roleAuth.getRoleName() + + "] failed due to wrong version[" + roleAuth.getVersion() + "] !"); + } + } + + /** + * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1; + * + * @param participant + */ + public long authorizePermissions(String roleName, LedgerPermission... permissions) { + RolePrivilegeAuthorization roleAuth = getRoleAuthorization(roleName); + if (roleAuth == null) { + return -1; + } + roleAuth.getLedgerPrivilege().enable(permissions); + return innerSetRoleAuthorization(roleAuth); + } + + /** + * 授权角色指定的权限;
+ * 如果角色不存在,则返回 -1; + * + * @param participant + */ + public long authorizePermissions(String roleName, TransactionPermission... permissions) { + RolePrivilegeAuthorization roleAuth = getRoleAuthorization(roleName); + if (roleAuth == null) { + return -1; + } + roleAuth.getTransactionPrivilege().enable(permissions); + return innerSetRoleAuthorization(roleAuth); + } + + private Bytes encodeKey(String address) { + // return id + ""; + return Bytes.fromString(address); + } + + /** + * 查询角色授权; + * + *
+ * 如果不存在,则返回 null; + * + * @param address + * @return + */ + public RolePrivilegeAuthorization getRoleAuthorization(String roleName) { + // 只返回最新版本; + Bytes key = encodeKey(roleName); + VersioningKVEntry kv = dataset.getDataEntry(key); + if (kv == null) { + return null; + } + RolePrivilege privilege = BinaryProtocol.decode(kv.getValue()); + return new RolePrivilegeAuthorization(roleName, kv.getVersion(), privilege); + } + + public RolePrivilegeAuthorization[] getRoleAuthorizations() { + VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); + RolePrivilegeAuthorization[] pns = new RolePrivilegeAuthorization[kvEntries.length]; + RolePrivilege privilege; + for (int i = 0; i < pns.length; i++) { + privilege = BinaryProtocol.decode(kvEntries[i].getValue()); + pns[i] = new RolePrivilegeAuthorization(kvEntries[i].getKey().toUTF8String(), kvEntries[i].getVersion(), privilege); + } + return pns; + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilege.java index 19949af5..e40649b2 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilege.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilege.java @@ -1,10 +1,9 @@ package com.jd.blockchain.ledger.core; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; - -import com.jd.blockchain.utils.io.BytesEncoding; -import com.jd.blockchain.utils.io.BytesSerializable; +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; /** * 表示赋予角色的特权码; @@ -12,57 +11,13 @@ import com.jd.blockchain.utils.io.BytesSerializable; * @author huanghaiquan * */ -public class RolePrivilege implements BytesSerializable { - - // 权限码的数量;目前有2种:账本权限 + 交易权限; - private static final int SEGMENT_COUNT = 2; - - private LedgerPrivilege ledgerPrivilege; - - private TxPrivilege txPrivilege; - - public Privilege getTxPrivilege() { - return txPrivilege; - } - - public Privilege getLedgerPrivilege() { - return ledgerPrivilege; - } - - public RolePrivilege(byte[] priviledgeCodes) { - byte[][] bytesSegments = decodeBytes(priviledgeCodes); - ledgerPrivilege = new LedgerPrivilege(bytesSegments[0]); - txPrivilege = new TxPrivilege(bytesSegments[1]); - } - - private byte[] encodeBytes(byte[]... bytes) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // write one byte; - out.write(bytes.length); - for (int i = 0; i < bytes.length; i++) { - BytesEncoding.writeInTiny(bytes[i], out); - } - return out.toByteArray(); - } +@DataContract(code = DataCodes.ROLE_PRIVILEGE, name = "ROLE-PRIVILEGE") +public interface RolePrivilege { - private byte[][] decodeBytes(byte[] bytes) { - ByteArrayInputStream in = new ByteArrayInputStream(bytes); - // read one byte; - int len = in.read(); - if (len < 1 || len > SEGMENT_COUNT) { - throw new IllegalStateException("Decoded illegal privilege bytes!"); - } - byte[][] bytesSegments = new byte[len][]; - for (int i = 0; i < bytesSegments.length; i++) { - bytesSegments[i] = BytesEncoding.readInTiny(in); - } - return bytesSegments; - } + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + LedgerPrivilege getLedgerPrivilege(); - @Override - public byte[] toBytes() { - // 保持和解码时一致的顺序; - return encodeBytes(ledgerPrivilege.toBytes(), txPrivilege.toBytes()); - } + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + TransactionPrivilege getTransactionPrivilege(); } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeAuthorization.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeAuthorization.java new file mode 100644 index 00000000..b73f940c --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolePrivilegeAuthorization.java @@ -0,0 +1,66 @@ +package com.jd.blockchain.ledger.core; + +/** + * 对角色的授权; + * + * @author huanghaiquan + * + */ +public class RolePrivilegeAuthorization implements RolePrivilege { + + private String roleName; + + private long version; + + private LedgerPrivilege ledgerPrivilege; + + private TransactionPrivilege txPrivilege; + + public RolePrivilegeAuthorization(String roleName, long version) { + this.roleName = roleName; + this.version = version; + this.ledgerPrivilege = new LedgerPrivilege(); + this.txPrivilege = new TransactionPrivilege(); + } + + public RolePrivilegeAuthorization(String roleName, long version, RolePrivilege privilege) { + this.roleName = roleName; + this.version = version; + this.ledgerPrivilege = privilege.getLedgerPrivilege(); + this.txPrivilege = privilege.getTransactionPrivilege(); + } + + public RolePrivilegeAuthorization(String roleName, long version, LedgerPrivilege ledgerPrivilege, TransactionPrivilege txPrivilege) { + this.roleName = roleName; + this.version = version; + this.ledgerPrivilege = ledgerPrivilege; + this.txPrivilege = txPrivilege; + } + + public String getRoleName() { + return roleName; + } + + public long getVersion() { + return version; + } + + @Override + public LedgerPrivilege getLedgerPrivilege() { + return ledgerPrivilege; + } + + public void setLedgerPrivilege(LedgerPrivilege ledgerPrivilege) { + this.ledgerPrivilege = ledgerPrivilege; + } + + @Override + public TransactionPrivilege getTransactionPrivilege() { + return txPrivilege; + } + + public void setTransactionPrivilege(TransactionPrivilege txPrivilege) { + this.txPrivilege = txPrivilege; + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RoleSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RoleSet.java new file mode 100644 index 00000000..da4f5b6a --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RoleSet.java @@ -0,0 +1,23 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +/** + * 角色集; + * + * @author huanghaiquan + * + */ +@DataContract(code = DataCodes.ROLE_SET) +public interface RoleSet { + + @DataField(order = 1, refEnum = true) + RolesPolicy getPolicy(); + + @DataField(order = 2, primitiveType = PrimitiveType.TEXT, list = true) + String[] getRoles(); + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolesPolicy.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolesPolicy.java new file mode 100644 index 00000000..42b72bb8 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/RolesPolicy.java @@ -0,0 +1,40 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.binaryproto.EnumContract; +import com.jd.blockchain.binaryproto.EnumField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +/** + * 多角色策略;
+ * + * 表示如何处理一个对象被赋予多个角色时的综合权限; + * + * @author huanghaiquan + * + */ +@EnumContract(code = DataCodes.ENUM_MULTI_ROLES_POLICY, name = "USER-ROLE-POLICY") +public enum RolesPolicy { + + /** + * 合并权限;
+ * + * 综合权限是所有角色权限的并集,即任何一个角色的权限都被继承; + */ + UNION((byte) 0), + + /** + * 交叉权限;
+ * + * 综合权限是所有角色权限的交集,即只有全部角色共同拥有的权限才会被继承; + */ + INTERSECT((byte) 1); + + @EnumField(type = PrimitiveType.INT8) + public final byte CODE; + + private RolesPolicy(byte code) { + this.CODE = code; + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TxPermission.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionPermission.java similarity index 73% rename from source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TxPermission.java rename to source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionPermission.java index b73ceaa3..fb513938 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TxPermission.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionPermission.java @@ -11,23 +11,23 @@ import com.jd.blockchain.consts.DataCodes; * @author huanghaiquan * */ -@EnumContract(code = DataCodes.ENUM_TX_PERMISSIONS) -public enum TxPermission { +@EnumContract(code = DataCodes.ENUM_TX_PERMISSION) +public enum TransactionPermission { /** * 交易中包含指令操作; */ - COMMAND((byte) 0x01), + DIRECT_OPERATION((byte) 0x01), /** * 交易中包含合约操作; */ - CONTRACT((byte) 0x02); + CONTRACT_OPERATION((byte) 0x02); @EnumField(type = PrimitiveType.INT8) public final byte CODE; - private TxPermission(byte code) { + private TransactionPermission(byte code) { this.CODE = code; } diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionPrivilege.java new file mode 100644 index 00000000..366e39f5 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TransactionPrivilege.java @@ -0,0 +1,17 @@ +package com.jd.blockchain.ledger.core; + +public class TransactionPrivilege extends AbstractPrivilege { + + public TransactionPrivilege() { + } + + public TransactionPrivilege(byte[] codeBytes) { + super(codeBytes); + } + + @Override + protected int getCodeIndex(TransactionPermission permission) { + return permission.CODE & 0xFF; + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TxPrivilege.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TxPrivilege.java deleted file mode 100644 index 30e45a18..00000000 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/TxPrivilege.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.jd.blockchain.ledger.core; - -public class TxPrivilege extends AbstractPrivilege { - - public TxPrivilege(byte[] codeBytes) { - super(codeBytes); - } - - @Override - protected int getCodeIndex(TxPermission permission) { - return permission.CODE & 0xFF; - } - -} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataSet.java new file mode 100644 index 00000000..e4ddb63e --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRoleDataSet.java @@ -0,0 +1,155 @@ +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVEntry; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +public class UserRoleDataSet implements Transactional, MerkleProvable { + + /** + * 角色名称的最大 Unicode 字符数; + */ + public static final int MAX_ROLE_NAME_LENGTH = 20; + + private MerkleDataSet dataset; + + public UserRoleDataSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage verStorage) { + dataset = new MerkleDataSet(cryptoSetting, prefix, exPolicyStorage, verStorage); + } + + public UserRoleDataSet(HashDigest merkleRootHash, CryptoSetting cryptoSetting, String prefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage verStorage, boolean readonly) { + dataset = new MerkleDataSet(merkleRootHash, cryptoSetting, prefix, exPolicyStorage, verStorage, readonly); + } + + @Override + public HashDigest getRootHash() { + return dataset.getRootHash(); + } + + @Override + public MerkleProof getProof(Bytes key) { + return dataset.getProof(key); + } + + @Override + public boolean isUpdated() { + return dataset.isUpdated(); + } + + @Override + public void commit() { + dataset.commit(); + } + + @Override + public void cancel() { + dataset.cancel(); + } + + public long getRoleCount() { + return dataset.getDataCount(); + } + + /** + * 加入新的用户角色授权;
+ * + * 如果该用户的授权已经存在,则引发 {@link LedgerException} 异常; + * + * @param userAddress + * @param rolesPolicy + * @param roles + */ + public void addUserRoles(Bytes userAddress, RolesPolicy rolesPolicy, String... roles) { + UserRolesAuthorization roleAuth = new UserRolesAuthorization(userAddress, -1, rolesPolicy); + roleAuth.addRoles(roles); + long nv = innerSetUserRolesAuthorization(roleAuth); + if (nv < 0) { + throw new LedgerException("Roles authorization of User[" + userAddress + "] already exists!"); + } + } + + /** + * 设置用户角色授权;
+ * 如果版本校验不匹配,则返回 -1; + * + * @param userRoles + * @return + */ + public long innerSetUserRolesAuthorization(UserRolesAuthorization userRoles) { + byte[] rolesetBytes = BinaryProtocol.encode(userRoles, RoleSet.class); + return dataset.setValue(userRoles.getUserAddress(), rolesetBytes, userRoles.getVersion()); + } + + /** + * 更新用户角色授权;
+ * 如果指定用户的授权不存在,或者版本不匹配,则引发 {@link LedgerException} 异常; + * + * @param userRoles + */ + public void updateUserRolesAuthorization(UserRolesAuthorization userRoles) { + long nv = innerSetUserRolesAuthorization(userRoles); + if (nv < 0) { + throw new LedgerException("Update to roles of user[" + userRoles.getUserAddress() + + "] failed due to wrong version[" + userRoles.getVersion() + "] !"); + } + } + + /** + * 设置用户的角色;
+ * 如果用户的角色授权不存在,则创建新的授权; + * + * @param userAddress 用户; + * @param policy 角色策略; + * @param roles 角色列表; + * @return + */ + public long setRoles(Bytes userAddress, RolesPolicy policy, String... roles) { + UserRolesAuthorization userRoles = getUserRolesAuthorization(userAddress); + if (userRoles == null) { + userRoles = new UserRolesAuthorization(userAddress, -1, policy); + } + userRoles.setPolicy(policy); + userRoles.setRoles(roles); + return innerSetUserRolesAuthorization(userRoles); + } + + /** + * 查询角色授权; + * + *
+ * 如果不存在,则返回 null; + * + * @param address + * @return + */ + public UserRolesAuthorization getUserRolesAuthorization(Bytes userAddress) { + // 只返回最新版本; + VersioningKVEntry kv = dataset.getDataEntry(userAddress); + if (kv == null) { + return null; + } + RoleSet roleSet = BinaryProtocol.decode(kv.getValue()); + return new UserRolesAuthorization(userAddress, kv.getVersion(), roleSet); + } + + public RolePrivilegeAuthorization[] getRoleAuthorizations() { + VersioningKVEntry[] kvEntries = dataset.getLatestDataEntries(0, (int) dataset.getDataCount()); + RolePrivilegeAuthorization[] pns = new RolePrivilegeAuthorization[kvEntries.length]; + RolePrivilege privilege; + for (int i = 0; i < pns.length; i++) { + privilege = BinaryProtocol.decode(kvEntries[i].getValue()); + pns[i] = new RolePrivilegeAuthorization(kvEntries[i].getKey().toUTF8String(), kvEntries[i].getVersion(), + privilege); + } + return pns; + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesAuthorization.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesAuthorization.java new file mode 100644 index 00000000..bc038827 --- /dev/null +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserRolesAuthorization.java @@ -0,0 +1,84 @@ +package com.jd.blockchain.ledger.core; + +import java.util.Set; +import java.util.TreeSet; + +import com.jd.blockchain.utils.Bytes; + +public class UserRolesAuthorization implements RoleSet { + + private Bytes userAddress; + + private RolesPolicy policy; + + private Set roles; + + private long version; + + public UserRolesAuthorization(Bytes userAddress, long version, RolesPolicy policy) { + this.userAddress = userAddress; + this.version = version; + this.policy = policy; + this.roles = new TreeSet(); + } + + public UserRolesAuthorization(Bytes userAddress, long version, RoleSet roleSet) { + this.userAddress = userAddress; + this.version = version; + this.policy = roleSet.getPolicy(); + this.roles = initRoles(roleSet.getRoles()); + + } + + private Set initRoles(String[] roles) { + TreeSet roleset = new TreeSet(); + if (roles != null) { + for (String r : roles) { + roleset.add(r); + } + } + return roleset; + } + + public Bytes getUserAddress() { + return userAddress; + } + + @Override + public RolesPolicy getPolicy() { + return policy; + } + + public void setPolicy(RolesPolicy policy) { + this.policy = policy; + } + + public int getRoleCount() { + return roles.size(); + } + + @Override + public String[] getRoles() { + return roles.toArray(new String[roles.size()]); + } + + public long getVersion() { + return version; + } + + public void addRoles(String... roles) { + for (String r : roles) { + this.roles.add(r); + } + } + + /** + * 设置角色集合;
+ * 注意,这不是追加;现有的不在参数指定范围的角色将被移除; + * + * @param roles + */ + public void setRoles(String[] roles) { + + } +}