diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java
index 18d0fdfd..82793392 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerPermission.java
@@ -36,34 +36,26 @@ public enum LedgerPermission {
REGISTER_PARTICIPANT((byte) 0x04),
/**
- * 设置参与方的权限;
+ * 注册用户;
*
- * 如果不具备此项权限,则无法设置参与方的“提交交易”、“参与共识”的权限;
+ * 如果不具备此项权限,则无法注册用户;
*/
- SET_PARTICIPANT_PERMISSION((byte) 0x05),
+ REGISTER_USER((byte) 0x05),
/**
- * 参与方核准交易;
- *
- * 如果不具备此项权限,则无法作为节点签署由终端提交的交易;
- *
- * 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响;
+ * 注册数据账户;
*/
- APPROVE_TX((byte) 0x06),
+ REGISTER_DATA_ACCOUNT((byte) 0x06),
/**
- * 参与方共识交易;
- *
- * 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识;
+ * 注册合约;
*/
- CONSENSUS_TX((byte) 0x07),
+ REGISTER_CONTRACT((byte) 0x07),
/**
- * 注册用户;
- *
- * 如果不具备此项权限,则无法注册用户;
+ * 升级合约
*/
- REGISTER_USER((byte) 0x08),
+ UPGRADE_CONTRACT((byte) 0x08),
/**
* 设置用户属性;
@@ -71,24 +63,27 @@ public enum LedgerPermission {
SET_USER_ATTRIBUTES((byte) 0x09),
/**
- * 注册数据账户;
- */
- REGISTER_DATA_ACCOUNT((byte) 0x0A),
-
- /**
* 写入数据账户;
*/
- WRITE_DATA_ACCOUNT((byte) 0x0B),
+ WRITE_DATA_ACCOUNT((byte) 0x0A),
/**
- * 注册合约;
+ * 参与方核准交易;
+ *
+ * 如果不具备此项权限,则无法作为节点签署由终端提交的交易;
+ *
+ * 只对交易请求的节点签名列表{@link TransactionRequest#getNodeSignatures()}的用户产生影响;
*/
- REGISTER_CONTRACT((byte) 0x0C),
+ APPROVE_TX((byte) 0x0B),
/**
- * 升级合约
+ * 参与方共识交易;
+ *
+ * 如果不具备此项权限,则无法作为共识节点接入并对交易进行共识;
*/
- UPGRADE_CONTRACT((byte) 0x0D);
+ CONSENSUS_TX((byte) 0x0C);
+
+
@EnumField(type = PrimitiveType.INT8)
public final byte CODE;
diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
index 9e4a5d55..9ba2e250 100644
--- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
+++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SecurityInitData.java
@@ -5,7 +5,7 @@ import java.util.List;
public class SecurityInitData implements SecurityInitSettings {
- private List roles = new ArrayList();
+ private List roles = new ArrayList();
@Override
public RoleInitData[] getRoles() {
@@ -13,8 +13,8 @@ public class SecurityInitData implements SecurityInitSettings {
}
public void setRoles(RoleInitData[] roles) {
- List list = new ArrayList();
- for (RoleInitSettings r : roles) {
+ List list = new ArrayList();
+ for (RoleInitData r : roles) {
list.add(r);
}
this.roles = list;
diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java
index fab4c57a..6bf9d1f5 100644
--- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java
+++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SecurityInitDataTest.java
@@ -29,6 +29,18 @@ public class SecurityInitDataTest {
assertEquals(LedgerPermission.REGISTER_USER, permissions2[0]);
assertEquals(LedgerPermission.REGISTER_DATA_ACCOUNT, permissions2[1]);
+ LedgerPermission[] allLedgerPermissions = LedgerPermission.values();
+ String jsonLedgerPersioms = JSONSerializeUtils.serializeToJSON(allLedgerPermissions);
+
+ TransactionPermission[] allTransactionPermissions = TransactionPermission.values();
+ String jsonTransactionPersioms = JSONSerializeUtils.serializeToJSON(allTransactionPermissions);
+
+ System.out.println("----------- Ledger Permissions JSON ------------");
+ System.out.println(jsonLedgerPersioms);
+ System.out.println("-----------------------");
+ System.out.println("----------- Transaction Permissions JSON ------------");
+ System.out.println(jsonTransactionPersioms);
+ System.out.println("-----------------------");
}
@Test
diff --git a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java
index d01de50f..101c874b 100644
--- a/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java
+++ b/source/test/test-integration/src/test/java/test/com/jd/blockchain/intgr/initializer/LedgerInitializeTest.java
@@ -13,8 +13,6 @@ import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import com.jd.blockchain.binaryproto.DataContractRegistry;
-import com.jd.blockchain.consensus.ConsensusProvider;
-import com.jd.blockchain.consensus.ConsensusSettings;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.AsymmetricKeypair;
import com.jd.blockchain.crypto.Crypto;
diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java
index 407501e9..ccc97362 100644
--- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java
+++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/LedgerInitProperties.java
@@ -7,15 +7,23 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
+import java.util.TreeMap;
import com.jd.blockchain.consts.Global;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.LedgerPermission;
import com.jd.blockchain.ledger.ParticipantNode;
+import com.jd.blockchain.ledger.RoleInitData;
+import com.jd.blockchain.ledger.RoleInitSettings;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
import com.jd.blockchain.utils.Bytes;
import com.jd.blockchain.utils.PropertiesUtils;
+import com.jd.blockchain.utils.StringUtils;
import com.jd.blockchain.utils.codec.HexUtils;
import com.jd.blockchain.utils.io.FileUtils;
import com.jd.blockchain.utils.net.NetworkAddress;
@@ -33,6 +41,13 @@ public class LedgerInitProperties {
// 创建时间的格式;
public static final String CREATED_TIME_FORMAT = Global.DEFAULT_TIME_FORMAT;
+ // 角色清单;
+ public static final String ROLES = "security.roles";
+ // 角色的账本权限;用角色名称替代占位符;
+ public static final String ROLE_LEDGER_PRIVILEGES_PATTERN = "security.role.%s.ledger-privileges";
+ // 角色的交易权限;用角色名称替代占位符;
+ public static final String ROLE_TX_PRIVILEGES_PATTERN = "security.role.%s.tx-privileges";
+
// 共识参与方的个数,后续以 part.id 分别标识每一个参与方的配置;
public static final String PART_COUNT = "cons_parti.count";
// 共识参与方的名称的模式;
@@ -43,6 +58,10 @@ public class LedgerInitProperties {
public static final String PART_PUBKEY_PATH = "pubkey-path";
// 参与方的公钥文件路径;
public static final String PART_PUBKEY = "pubkey";
+ // 参与方的角色清单;
+ public static final String PART_ROLES = "roles";
+ // 参与方的角色权限策略;
+ public static final String PART_ROLES_POLICY = "roles-policy";
// 共识参与方的账本初始服务的主机;
public static final String PART_INITIALIZER_HOST = "initializer.host";
@@ -66,6 +85,8 @@ public class LedgerInitProperties {
private String ledgerName;
+ private RoleInitData[] roles;
+
private List consensusParticipants = new ArrayList<>();
private String consensusProvider;
@@ -143,7 +164,7 @@ public class LedgerInitProperties {
consensusParticipants.add(participant);
}
- private static String getKeyOfCsParti(int partId, String partPropKey) {
+ private static String getKeyOfParticipant(int partId, String partPropKey) {
String partAddrStr = String.format(PART_ID_PATTERN, partId);
return String.format("%s.%s", partAddrStr, partPropKey);
}
@@ -162,12 +183,20 @@ public class LedgerInitProperties {
public static LedgerInitProperties resolve(Properties props) {
return resolve(null, props);
}
-
- public static LedgerInitProperties resolve(String dir, Properties props) {
+
+ /**
+ * 从属性表解析账本初始化参数;
+ *
+ * @param baseDirectory 基础路径;属性中涉及文件位置的相对路径以此参数指定的目录为父目录;
+ * @param props 要解析的属性表;
+ * @return
+ */
+ public static LedgerInitProperties resolve(String baseDirectory, Properties props) {
String hexLedgerSeed = PropertiesUtils.getRequiredProperty(props, LEDGER_SEED).replace("-", "");
byte[] ledgerSeed = HexUtils.decode(hexLedgerSeed);
LedgerInitProperties initProps = new LedgerInitProperties(ledgerSeed);
+ // 解析账本信息;
// 账本名称
String ledgerName = PropertiesUtils.getRequiredProperty(props, LEDGER_NAME);
initProps.ledgerName = ledgerName;
@@ -180,11 +209,35 @@ public class LedgerInitProperties {
throw new IllegalArgumentException(ex.getMessage(), ex);
}
+ // 解析角色清单;
+ String strRoleNames = PropertiesUtils.getOptionalProperty(props, ROLES);
+ String[] roles = StringUtils.splitToArray(strRoleNames, ",");
+
+ Map rolesInitSettingMap = new TreeMap();
+ // 解析角色权限表;
+ for (String role : roles) {
+ String ledgerPrivilegeKey = getKeyOfRoleLedgerPrivilege(role);
+ String strLedgerPermissions = PropertiesUtils.getOptionalProperty(props, ledgerPrivilegeKey);
+ LedgerPermission[] ledgerPermissions = resolveLedgerPermissions(strLedgerPermissions);
+
+ String txPrivilegeKey = getKeyOfRoleTxPrivilege(role);
+ String strTxPermissions = PropertiesUtils.getOptionalProperty(props, txPrivilegeKey);
+ TransactionPermission[] txPermissions = resolveTransactionPermissions(strTxPermissions);
+
+ if (ledgerPermissions.length > 0 || txPermissions.length > 0) {
+ RoleInitData rolesSettings = new RoleInitData(role, ledgerPermissions, txPermissions);
+ rolesInitSettingMap.put(role, rolesSettings);
+ }
+ }
+ RoleInitData[] rolesInitDatas = rolesInitSettingMap.values()
+ .toArray(new RoleInitData[rolesInitSettingMap.size()]);
+ initProps.setRoles(rolesInitDatas);
+
// 解析共识相关的属性;
initProps.consensusProvider = PropertiesUtils.getRequiredProperty(props, CONSENSUS_SERVICE_PROVIDER);
String consensusConfigFilePath = PropertiesUtils.getRequiredProperty(props, CONSENSUS_CONFIG);
try {
- File consensusConfigFile = FileUtils.getFile(dir, consensusConfigFilePath);
+ File consensusConfigFile = FileUtils.getFile(baseDirectory, consensusConfigFilePath);
initProps.consensusConfig = FileUtils.readProperties(consensusConfigFile);
} catch (FileNotFoundException e) {
throw new IllegalArgumentException(
@@ -212,13 +265,13 @@ public class LedgerInitProperties {
parti.setId(i);
- String nameKey = getKeyOfCsParti(i, PART_NAME);
+ String nameKey = getKeyOfParticipant(i, PART_NAME);
parti.setName(PropertiesUtils.getRequiredProperty(props, nameKey));
- String pubkeyPathKey = getKeyOfCsParti(i, PART_PUBKEY_PATH);
+ String pubkeyPathKey = getKeyOfParticipant(i, PART_PUBKEY_PATH);
String pubkeyPath = PropertiesUtils.getProperty(props, pubkeyPathKey, false);
- String pubkeyKey = getKeyOfCsParti(i, PART_PUBKEY);
+ String pubkeyKey = getKeyOfParticipant(i, PART_PUBKEY);
String base58PubKey = PropertiesUtils.getProperty(props, pubkeyKey, false);
if (base58PubKey != null) {
PubKey pubKey = KeyGenCommand.decodePubKey(base58PubKey);
@@ -231,13 +284,27 @@ public class LedgerInitProperties {
String.format("Property[%s] and property[%s] are all empty!", pubkeyKey, pubkeyPathKey));
}
- String initializerHostKey = getKeyOfCsParti(i, PART_INITIALIZER_HOST);
+ // 解析参与方的角色权限配置;
+ String partiRolesKey = getKeyOfParticipant(i, PART_ROLES);
+ String strPartiRoles = PropertiesUtils.getOptionalProperty(props, partiRolesKey);
+ String[] partiRoles = StringUtils.splitToArray(strPartiRoles, ",");
+ parti.setRoles(partiRoles);
+
+ String partiRolePolicyKey = getKeyOfParticipant(i, PART_ROLES_POLICY);
+ String strPartiPolicy = PropertiesUtils.getOptionalProperty(props, partiRolePolicyKey);
+ RolesPolicy policy = strPartiPolicy == null ? RolesPolicy.UNION
+ : RolesPolicy.valueOf(strPartiPolicy.trim());
+ policy = policy == null ? RolesPolicy.UNION : policy;
+ parti.setRolesPolicy(policy);
+
+ // 解析参与方的网络配置参数;
+ String initializerHostKey = getKeyOfParticipant(i, PART_INITIALIZER_HOST);
String initializerHost = PropertiesUtils.getRequiredProperty(props, initializerHostKey);
- String initializerPortKey = getKeyOfCsParti(i, PART_INITIALIZER_PORT);
+ String initializerPortKey = getKeyOfParticipant(i, PART_INITIALIZER_PORT);
int initializerPort = getInt(PropertiesUtils.getRequiredProperty(props, initializerPortKey));
- String initializerSecureKey = getKeyOfCsParti(i, PART_INITIALIZER_SECURE);
+ String initializerSecureKey = getKeyOfParticipant(i, PART_INITIALIZER_SECURE);
boolean initializerSecure = Boolean
.parseBoolean(PropertiesUtils.getRequiredProperty(props, initializerSecureKey));
NetworkAddress initializerAddress = new NetworkAddress(initializerHost, initializerPort, initializerSecure);
@@ -249,10 +316,54 @@ public class LedgerInitProperties {
return initProps;
}
+ private static TransactionPermission[] resolveTransactionPermissions(String strTxPermissions) {
+ String[] strPermissions = StringUtils.splitToArray(strTxPermissions, ",");
+ List permissions = new ArrayList();
+ if (strPermissions != null) {
+ for (String pm : strPermissions) {
+ TransactionPermission permission = TransactionPermission.valueOf(pm);
+ if (permission != null) {
+ permissions.add(permission);
+ }
+ }
+ }
+ return permissions.toArray(new TransactionPermission[permissions.size()]);
+ }
+
+ private static LedgerPermission[] resolveLedgerPermissions(String strLedgerPermissions) {
+ String[] strPermissions = StringUtils.splitToArray(strLedgerPermissions, ",");
+ List permissions = new ArrayList();
+ if (strPermissions != null) {
+ for (String pm : strPermissions) {
+ LedgerPermission permission = LedgerPermission.valueOf(pm);
+ if (permission != null) {
+ permissions.add(permission);
+ }
+ }
+ }
+ return permissions.toArray(new LedgerPermission[permissions.size()]);
+ }
+
+ private static String getKeyOfRoleLedgerPrivilege(String role) {
+ return String.format(ROLE_LEDGER_PRIVILEGES_PATTERN, role);
+ }
+
+ private static String getKeyOfRoleTxPrivilege(String role) {
+ return String.format(ROLE_TX_PRIVILEGES_PATTERN, role);
+ }
+
private static int getInt(String strInt) {
return Integer.parseInt(strInt.trim());
}
+ public RoleInitData[] getRoles() {
+ return roles;
+ }
+
+ public void setRoles(RoleInitData[] roles) {
+ this.roles = roles;
+ }
+
/**
* 参与方配置信息;
*
@@ -267,10 +378,12 @@ public class LedgerInitProperties {
private String name;
-// private String pubKeyPath;
-
private PubKey pubKey;
+ private String[] roles;
+
+ private RolesPolicy rolesPolicy;
+
// private NetworkAddress consensusAddress;
private NetworkAddress initializerAddress;
@@ -321,6 +434,22 @@ public class LedgerInitProperties {
this.address = AddressEncoding.generateAddress(pubKey);
}
+ public String[] getRoles() {
+ return roles;
+ }
+
+ public void setRoles(String[] roles) {
+ this.roles = roles;
+ }
+
+ public RolesPolicy getRolesPolicy() {
+ return rolesPolicy;
+ }
+
+ public void setRolesPolicy(RolesPolicy rolesPolicy) {
+ this.rolesPolicy = rolesPolicy;
+ }
+
}
}
diff --git a/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java
index 3e0a004e..6e890a52 100644
--- a/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java
+++ b/source/tools/tools-initializer/src/test/java/test/com/jd/blockchain/tools/initializer/LedgerInitPropertiesTest.java
@@ -1,12 +1,18 @@
package test.com.jd.blockchain.tools.initializer;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
import java.util.TimeZone;
import org.junit.Test;
@@ -14,6 +20,10 @@ import org.springframework.core.io.ClassPathResource;
import com.jd.blockchain.crypto.AddressEncoding;
import com.jd.blockchain.crypto.PubKey;
+import com.jd.blockchain.ledger.LedgerPermission;
+import com.jd.blockchain.ledger.RoleInitData;
+import com.jd.blockchain.ledger.RolesPolicy;
+import com.jd.blockchain.ledger.TransactionPermission;
import com.jd.blockchain.tools.initializer.LedgerInitProperties;
import com.jd.blockchain.tools.initializer.LedgerInitProperties.ConsensusParticipantConfig;
import com.jd.blockchain.tools.keygen.KeyGenCommand;
@@ -22,19 +32,20 @@ import com.jd.blockchain.utils.codec.HexUtils;
public class LedgerInitPropertiesTest {
private static String expectedCreatedTimeStr = "2019-08-01 14:26:58.069+0800";
-
+
private static String expectedCreatedTimeStr1 = "2019-08-01 13:26:58.069+0700";
-
+
@Test
public void testTimeFormat() throws ParseException {
SimpleDateFormat timeFormat = new SimpleDateFormat(LedgerInitProperties.CREATED_TIME_FORMAT);
-// timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
- TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00"));
-
+ timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
+ // 或者设置全局的默认时区;
+ // TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00"));
+
Date time = timeFormat.parse(expectedCreatedTimeStr);
String actualTimeStr = timeFormat.format(time);
assertEquals(expectedCreatedTimeStr, actualTimeStr);
-
+
Date time1 = timeFormat.parse(expectedCreatedTimeStr1);
String actualTimeStr1 = timeFormat.format(time1);
assertEquals(expectedCreatedTimeStr, actualTimeStr1);
@@ -42,11 +53,13 @@ public class LedgerInitPropertiesTest {
@Test
public void testProperties() throws IOException, ParseException {
+ // 加载用于测试的账本初始化配置;
ClassPathResource ledgerInitSettingResource = new ClassPathResource("ledger.init");
InputStream in = ledgerInitSettingResource.getInputStream();
try {
LedgerInitProperties initProps = LedgerInitProperties.resolve(in);
- assertEquals(4, initProps.getConsensusParticipantCount());
+
+ // 验证账本信息;
String expectedLedgerSeed = "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe"
.replace("-", "");
String actualLedgerSeed = HexUtils.encode(initProps.getLedgerSeed());
@@ -56,10 +69,54 @@ public class LedgerInitPropertiesTest {
timeFormat.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
long expectedTs = timeFormat.parse(expectedCreatedTimeStr).getTime();
assertEquals(expectedTs, initProps.getCreatedTime());
-
+
String createdTimeStr = timeFormat.format(new Date(initProps.getCreatedTime()));
assertEquals(expectedCreatedTimeStr, createdTimeStr);
+ // 验证角色配置;
+ RoleInitData[] roles = initProps.getRoles();
+ assertEquals(4, roles.length);
+ Map rolesInitDatas = new HashMap();
+ for (RoleInitData r : roles) {
+ rolesInitDatas.put(r.getRoleName(), r);
+ }
+ // 初始化配置的角色最终也是有序排列的,按照角色名称的自然顺序;
+ String[] expectedRolesNames = { "DEFAULT", "ADMIN", "MANAGER", "GUEST" };
+ Arrays.sort(expectedRolesNames);
+ assertEquals(expectedRolesNames[0], roles[0].getRoleName());
+ assertEquals(expectedRolesNames[1], roles[1].getRoleName());
+ assertEquals(expectedRolesNames[2], roles[2].getRoleName());
+ assertEquals(expectedRolesNames[3], roles[3].getRoleName());
+
+ RoleInitData roleDefault = rolesInitDatas.get("DEFAULT");
+ assertArrayEquals(
+ new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT },
+ roleDefault.getLedgerPermissions());
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION }, roleDefault.getTransactionPermissions());
+
+ RoleInitData roleAdmin = rolesInitDatas.get("ADMIN");
+ assertArrayEquals(new LedgerPermission[] { LedgerPermission.AUTHORIZE_ROLES, LedgerPermission.SET_CONSENSUS,
+ LedgerPermission.SET_CRYPTO, LedgerPermission.REGISTER_PARTICIPANT,
+ LedgerPermission.REGISTER_USER }, roleAdmin.getLedgerPermissions());
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION },
+ roleAdmin.getTransactionPermissions());
+
+ RoleInitData roleManager = rolesInitDatas.get("MANAGER");
+ assertArrayEquals(
+ new LedgerPermission[] { LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT,
+ LedgerPermission.REGISTER_CONTRACT, LedgerPermission.UPGRADE_CONTRACT,
+ LedgerPermission.SET_USER_ATTRIBUTES, LedgerPermission.WRITE_DATA_ACCOUNT },
+ roleManager.getLedgerPermissions());
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.DIRECT_OPERATION,
+ TransactionPermission.CONTRACT_OPERATION }, roleManager.getTransactionPermissions());
+
+ RoleInitData roleGuest = rolesInitDatas.get("GUEST");
+ assertTrue(roleGuest.getLedgerPermissions() == null || roleGuest.getLedgerPermissions().length == 0);
+ assertArrayEquals(new TransactionPermission[] { TransactionPermission.CONTRACT_OPERATION },
+ roleGuest.getTransactionPermissions());
+
+ // 验证共识和密码配置;
assertEquals("com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider",
initProps.getConsensusProvider());
@@ -68,6 +125,9 @@ public class LedgerInitPropertiesTest {
assertEquals("com.jd.blockchain.crypto.service.classic.ClassicCryptoService", cryptoProviders[0]);
assertEquals("com.jd.blockchain.crypto.service.sm.SMCryptoService", cryptoProviders[1]);
+ // 验证参与方信息;
+ assertEquals(4, initProps.getConsensusParticipantCount());
+
ConsensusParticipantConfig part0 = initProps.getConsensusParticipant(0);
assertEquals("jd.com", part0.getName());
PubKey pubKey0 = KeyGenCommand.decodePubKey("3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9");
@@ -75,14 +135,27 @@ public class LedgerInitPropertiesTest {
assertEquals("127.0.0.1", part0.getInitializerAddress().getHost());
assertEquals(8800, part0.getInitializerAddress().getPort());
assertEquals(true, part0.getInitializerAddress().isSecure());
+ assertArrayEquals(new String[] {"ADMIN", "MANAGER"}, part0.getRoles());
+ assertEquals(RolesPolicy.UNION, part0.getRolesPolicy());
+
ConsensusParticipantConfig part1 = initProps.getConsensusParticipant(1);
assertEquals(false, part1.getInitializerAddress().isSecure());
PubKey pubKey1 = KeyGenCommand.decodePubKey("3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX");
assertEquals(pubKey1, part1.getPubKey());
+ assertArrayEquals(new String[] { "MANAGER"}, part1.getRoles());
+ assertEquals(RolesPolicy.UNION, part1.getRolesPolicy());
ConsensusParticipantConfig part2 = initProps.getConsensusParticipant(2);
assertEquals("7VeRAr3dSbi1xatq11ZcF7sEPkaMmtZhV9shonGJWk9T4pLe", part2.getPubKey().toBase58());
+ assertArrayEquals(new String[] { "MANAGER"}, part2.getRoles());
+ assertEquals(RolesPolicy.UNION, part2.getRolesPolicy());
+
+ ConsensusParticipantConfig part3 = initProps.getConsensusParticipant(3);
+ PubKey pubKey3 = KeyGenCommand.decodePubKey("3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk");
+ assertEquals(pubKey3, part3.getPubKey());
+ assertArrayEquals(new String[] { "GUEST"}, part3.getRoles());
+ assertEquals(RolesPolicy.INTERSECT, part3.getRolesPolicy());
} finally {
in.close();
diff --git a/source/tools/tools-initializer/src/test/resources/ledger.init b/source/tools/tools-initializer/src/test/resources/ledger.init
index 2d574f93..275778b7 100644
--- a/source/tools/tools-initializer/src/test/resources/ledger.init
+++ b/source/tools/tools-initializer/src/test/resources/ledger.init
@@ -5,9 +5,52 @@ ledger.seed=932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323
#账本的描述名称;此属性不参与共识,仅仅在当前参与方的本地节点用于描述用途;
ledger.name=test
-#声明的账本创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区
+#声明账本的创建时间;格式为 “yyyy-MM-dd HH:mm:ss.SSSZ”,表示”年-月-日 时:分:秒:毫秒时区“;例如:“2019-08-01 14:26:58.069+0800”,其中,+0800 表示时区是东8区
created-time=2019-08-01 14:26:58.069+0800
+
+#-----------------------------------------------
+# 初始的角色名称列表;可选项;
+# 角色名称不区分大小写,最长不超过20个字符;多个角色名称之间用半角的逗点“,”分隔;
+# 系统会预置一个默认角色“DEFAULT”,所有未指定角色的用户都以赋予该角色的权限;若初始化时未配置默认角色的权限,则为默认角色分配所有权限;
+#
+# 注:如果声明了角色,但未声明角色对应的权限清单,这会忽略该角色的初始化;
+#
+security.roles=DEFAULT, ADMIN, MANAGER, GUEST
+
+# 赋予角色的账本权限清单;可选项;
+# 可选的权限如下;
+# AUTHORIZE_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT,
+# REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT,
+# SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT,
+# APPROVE_TX, CONSENSUS_TX
+# 多项权限之间用逗点“,”分隔;
+#
+security.role.DEFAULT.ledger-privileges=REGISTER_USER, REGISTER_DATA_ACCOUNT
+
+# 赋予角色的交易权限清单;可选项;
+# 可选的权限如下;
+# DIRECT_OPERATION, CONTRACT_OPERATION
+# 多项权限之间用逗点“,”分隔;
+#
+security.role.DEFAULT.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION
+
+# 其它角色的配置示例;
+# 系统管理员角色:只能操作全局性的参数配置和用户注册,只能执行直接操作指令;
+security.role.ADMIN.ledger-privileges=AUTHORIZE_ROLES, SET_CONSENSUS, SET_CRYPTO, REGISTER_PARTICIPANT, REGISTER_USER
+security.role.ADMIN.tx-privileges=DIRECT_OPERATION
+
+# 业务主管角色:只能够执行账本数据相关的操作,包括注册用户、注册数据账户、注册合约、升级合约、写入数据等;能够执行直接操作指令和调用合约;
+security.role.MANAGER.ledger-privileges=REGISTER_USER, REGISTER_DATA_ACCOUNT, REGISTER_CONTRACT, UPGRADE_CONTRACT, SET_USER_ATTRIBUTES, WRITE_DATA_ACCOUNT,
+security.role.MANAGER.tx-privileges=DIRECT_OPERATION, CONTRACT_OPERATION
+
+# 访客角色:不具备任何的账本权限,只有数据读取的操作;也只能够通过调用合约来读取数据;
+security.role.GUEST.ledger-privileges=
+security.role.GUEST.tx-privileges=CONTRACT_OPERATION
+
+
+
+#-----------------------------------------------
#共识服务提供者;必须;
consensus.service-provider=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider
@@ -28,6 +71,10 @@ cons_parti.0.name=jd.com
cons_parti.0.pubkey-path=keys/jd-com.pub
#第0个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.0.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9
+#第0个参与方的角色清单;可选项;
+cons_parti.0.roles=ADMIN, MANAGER
+#第0个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.0.roles-policy=UNION
#第0个参与方的共识服务的主机地址;
cons_parti.0.consensus.host=127.0.0.1
#第0个参与方的共识服务的端口;
@@ -47,6 +94,10 @@ cons_parti.1.name=at.com
cons_parti.1.pubkey-path=keys/at-com.pub
#第1个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.1.pubkey=3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX
+#第1个参与方的角色清单;可选项;
+cons_parti.1.roles=MANAGER
+#第1个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.1.roles-policy=UNION
#第1个参与方的共识服务的主机地址;
cons_parti.1.consensus.host=127.0.0.1
#第1个参与方的共识服务的端口;
@@ -66,6 +117,10 @@ cons_parti.2.name=bt.com
cons_parti.2.pubkey-path=classpath:keys/parti2.pub
#第2个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.2.pubkey=
+#第2个参与方的角色清单;可选项;
+cons_parti.2.roles=MANAGER
+#第2个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.2.roles-policy=UNION
#第2个参与方的共识服务的主机地址;
cons_parti.2.consensus.host=127.0.0.1
#第2个参与方的共识服务的端口;
@@ -85,6 +140,10 @@ cons_parti.3.name=xt.com
cons_parti.3.pubkey-path=keys/xt-com.pub
#第3个参与方的公钥内容(由keygen工具生成);此参数优先于 pubkey-path 参数;
cons_parti.3.pubkey=3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk
+#第3个参与方的角色清单;可选项;
+cons_parti.3.roles=GUEST
+#第3个参与方的角色权限策略,可选值有:UNION(并集),INTERSECT(交集);可选项;
+cons_parti.3.roles-policy=INTERSECT
#第3个参与方的共识服务的主机地址;
cons_parti.3.consensus.host=127.0.0.1
#第3个参与方的共识服务的端口;
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java
index 994272b0..f1fba9b1 100644
--- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java
@@ -263,6 +263,10 @@ public abstract class PropertiesUtils {
public static String getRequiredProperty(Properties props, String key) {
return getProperty(props, key, true);
}
+
+ public static String getOptionalProperty(Properties props, String key) {
+ return getProperty(props, key, false);
+ }
/**
* 返回指定的属性;
diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java
index 5ae1a856..fea16ace 100644
--- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java
+++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/StringUtils.java
@@ -1,24 +1,75 @@
package com.jd.blockchain.utils;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
import java.util.regex.Pattern;
/**
- * @Author zhaogw
- * date 2018/11/26 20:46
+ * @Author zhaogw date 2018/11/26 20:46
*/
public class StringUtils {
- public static boolean isEmpty(Object str) {
- return str == null || "".equals(str);
- }
-
- /*
- * 判断是否为整数
- * @param str 传入的字符串
- * @return 是整数返回true,否则返回false
- */
-
- public static boolean isNumber(String str) {
- Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
- return pattern.matcher(str).matches();
- }
+
+ public static final String[] EMPTY_ARRAY = {};
+
+ public static boolean isEmpty(Object str) {
+ return str == null || "".equals(str);
+ }
+
+ /*
+ * 判断是否为整数
+ *
+ * @param str 传入的字符串
+ *
+ * @return 是整数返回true,否则返回false
+ */
+
+ public static boolean isNumber(String str) {
+ Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
+ return pattern.matcher(str).matches();
+ }
+
+ /**
+ * 按照指定的分隔符把字符串分解为字符数组,同时截掉每一个元素两端的空白字符,并忽略掉空字符元素;
+ *
+ * @param str 要被截断的字符串;
+ * @param delimiter 分隔符;
+ * @return
+ */
+ public static String[] splitToArray(String str, String delimiter) {
+ return splitToArray(str, delimiter, true, true);
+ }
+
+ /**
+ * 按照指定的分隔符把字符串分解为字符数组
+ *
+ * @param str 要被截断的字符串;
+ * @param delimiter 分隔符;
+ * @param trimElement 是否截断元素两端的空白字符;
+ * @param ignoreEmptyElement 是否忽略空字符元素;
+ * @return
+ */
+ public static String[] splitToArray(String str, String delimiter, boolean trimElement, boolean ignoreEmptyElement) {
+ if (str == null) {
+ return null;
+ }
+ if (trimElement) {
+ str = str.trim();
+ }
+ if (str.length() == 0) {
+ return EMPTY_ARRAY;
+ }
+ StringTokenizer tokenizer = new StringTokenizer(str, delimiter);
+ List tokens = new ArrayList<>();
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (trimElement) {
+ token = token.trim();
+ }
+ if ((!ignoreEmptyElement) || token.length() > 0) {
+ tokens.add(token);
+ }
+ }
+ return tokens.toArray(new String[tokens.size()]);
+ }
}
\ No newline at end of file