diff --git a/src/common/common.js b/src/common/common.js
index bc7cceb..6b563a9 100644
--- a/src/common/common.js
+++ b/src/common/common.js
@@ -57,6 +57,8 @@ Common.LOGIN_PEER_SSL_TARGET = 'Peer SSL Target';
Common.LOGIN_ORDERER_SSL_TARGET = 'Orderer SSL Target';
Common.LOGIN_CA_SERVER_URL = 'CA Server Url';
+// user register page
+Common.REGISTER_USERNAME = 'User Name';
Common.WARN = {
chaincodeName: 'chaincode name can not be null!',
diff --git a/src/common/common_cn.js b/src/common/common_cn.js
index 094069e..89776d6 100644
--- a/src/common/common_cn.js
+++ b/src/common/common_cn.js
@@ -55,6 +55,8 @@ Common.LOGIN_PEER_SSL_TARGET = '组织节点SSL域名';
Common.LOGIN_ORDERER_SSL_TARGET = '排序节点SSL域名';
Common.LOGIN_CA_SERVER_URL = 'CA节点地址';
+// user register page
+Common.REGISTER_USERNAME = '用户名';
Common.WARN = {
chaincodeName: '链码名称不能为空!',
diff --git a/src/components/BasicLayout.jsx b/src/components/BasicLayout.jsx
index ec04848..6b50fb7 100644
--- a/src/components/BasicLayout.jsx
+++ b/src/components/BasicLayout.jsx
@@ -6,6 +6,7 @@ import { Layout, Menu, Icon } from 'antd';
import DataContent from './content/DataContent';
import ChaincodeInvokeContent from './content/ChaincodeInvokeContent';
import ChaincodeInstallContent from './content/ChaincodeInstallContent';
+import CARegisterContent from './content/CARegisterContent';
import { deleteFabricClientSingleton } from '../util/fabric';
import { getConfigDBSingleton, getInvokeDBSingleton, getChaincodeDBSingleton } from '../util/createDB';
@@ -35,6 +36,8 @@ function ContentRoute(props) {
return ;
} else if (props.contentKey === 4) {
return ;
+ } else if (props.contentKey === 5) {
+ return ;
}
return
The sidebar button is not bound to corresponding content
;
}
@@ -123,6 +126,10 @@ export default class BasicLayout extends React.Component {
{this.state.language === 'cn' ? '通道管理' : 'Channel Management' }
+ this.switchContent(5)}>
+
+ {this.state.language === 'cn' ? 'CA注册' : 'CA Register' }
+
diff --git a/src/components/UserLayout.jsx b/src/components/UserLayout.jsx
index e6632c0..f7ca116 100644
--- a/src/components/UserLayout.jsx
+++ b/src/components/UserLayout.jsx
@@ -85,24 +85,22 @@ export default class UserLayout extends React.Component {
tlsOrdererPath: this.state.tlsOrdererPath,
peerSSLTarget: this.state.peerSSLTarget,
ordererSSLTarget: this.state.ordererSSLTarget,
+ caServerUrl: this.state.caServerUrl,
+ keyPath: this.state.keyPath,
+ certPath: this.state.certPath,
path: 'resources/key/users/' } },
{},
() => {
- getFabricClientSingleton().then((fabricClient) => {
- fabricClient.importCer(this.state.keyPath, this.state.certPath).then((result) => {
- db.update({ id: 0 },
- { $set: { isSign: 2 } },
- {}, () => {
- });
- this.props.onGetChildMessage(2);
- logger.info('result', result);
- }, () => {
- message.error(this.state.Common.ERROR.certificateFailed);
- });
+ getFabricClientSingleton().then(() => {
+ db.update({ id: 0 },
+ { $set: { isSign: 2 } },
+ {}, () => {
+ });
+ this.props.onGetChildMessage(2);
+ }, () => {
+ message.error(this.state.Common.ERROR.certificateFailed);
});
});
-
- logger.info(this.state.certPath);
}
peerGrpcUrlChange(event) {
this.setState({ peerGrpcUrl: event.target.value });
diff --git a/src/components/content/CARegisterContent.jsx b/src/components/content/CARegisterContent.jsx
new file mode 100644
index 0000000..1591c28
--- /dev/null
+++ b/src/components/content/CARegisterContent.jsx
@@ -0,0 +1,212 @@
+// Copyright 2018 The hyperledger-fabric-desktop Authors. All rights reserved.
+
+// main feature: CA register and enroll
+import React from 'react';
+import { Button, Input } from 'antd';
+import { getFabricClientSingleton } from '../../util/fabric';
+
+const logger = require('electron-log');
+
+/**
+ * register参数:用户名、affiliation, role等等
+ * enroll参数:用户名、密码
+ */
+
+export default class CARegisterContent extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ Common: localStorage.getItem('language') === 'cn' ? require('../../common/common_cn') : require('../../common/common'),
+
+ registerUserName: '',
+ registerAffiliation: '',
+ registerRole: '',
+ registerOptional: '',
+
+ enrollUserName: '',
+ enrollUserPassword: '',
+ enrollOptional: '',
+ };
+
+ this.onChangeRegisterUserName = this.onChangeRegisterUserName.bind(this);
+ this.onChangeRegisterAffiliation = this.onChangeRegisterAffiliation.bind(this);
+ this.onChangeRegisterRole = this.onChangeRegisterRole.bind(this);
+ this.onChangeRegisterOptional = this.onChangeRegisterOptional.bind(this);
+ this.onChangeEnrollUserName = this.onChangeEnrollUserName.bind(this);
+ this.onChangeEnrollUserPassword = this.onChangeEnrollUserPassword.bind(this);
+ this.onChangeEnrollOptional = this.onChangeEnrollOptional.bind(this);
+
+ this.handleRegister = this.handleRegister.bind(this);
+ this.handleEnroll = this.handleEnroll.bind(this);
+ }
+
+ onChangeRegisterUserName(event) {
+ this.setState({ registerUserName: event.target.value });
+ }
+ onChangeRegisterAffiliation(event) {
+ this.setState({ registerAffiliation: event.target.value });
+ }
+ onChangeRegisterRole(event) {
+ this.setState({ registerRole: event.target.value });
+ }
+ onChangeRegisterOptional(event) {
+ this.setState({ registerOptional: event.target.value });
+ }
+ onChangeEnrollUserName(event) {
+ this.setState({ enrollUserName: event.target.value });
+ }
+ onChangeEnrollUserPassword(event) {
+ this.setState({ enrollUserPassword: event.target.value });
+ }
+ onChangeEnrollOptional(event) {
+ this.setState({ enrollOptional: event.target.value });
+ }
+
+ handleRegister() {
+ // FIXME: Object.assign is shallow copy. Be careful.
+ const tmpReq = {
+ enrollmentID: this.state.registerUserName,
+ affiliation: this.state.registerAffiliation,
+ role: this.state.role,
+ };
+ let req = tmpReq;
+ if (this.state.registerOptional) {
+ req = Object.assign({}, tmpReq, JSON.parse(this.state.registerOptional));
+ }
+
+ logger.info('start to register user, RegisterRequest: ', req);
+ getFabricClientSingleton()
+ .then((client) => {
+ logger.info('client: ', client.toString());
+ return client.register(req);
+ })
+ .then((enrollment) => {
+ // TODO: 输出密码,到页面上。
+ logger.info('register successfully, enrollment: ', enrollment);
+ })
+ .catch((err) => {
+ logger.info('fail to register user, err: ', err);
+ throw err;
+ });
+ }
+
+ handleEnroll() {
+
+ }
+
+ render() {
+ const outerDivStyle = {
+ padding: '24px',
+ };
+ const spanStyle = {
+ marginRight: '10px',
+ display: 'inline-block',
+ width: '100px',
+ };
+ const SpanStyle = {
+ marginTop: '30px',
+ };
+ const fileStyle = {
+ width: '0.1px',
+ height: '0.1px',
+ opacity: 0,
+ overflow: 'hidden',
+ position: 'absolute',
+ zIndex: -1,
+ };
+ const labelStyle = {
+ fontSize: '1.1em',
+ border: '1px solid rgb(217, 217, 217)',
+ borderRadius: '4px',
+ display: 'block',
+ width: '60%',
+ height: '32px',
+ verticalAlign: 'middle',
+ textAlign: 'center',
+ lineHeight: '30px',
+ cursor: 'pointer',
+ whiteSpace: 'nowrap',
+ textOverflow: 'ellipsis',
+ overflow: 'hidden',
+ marginLeft: '146px',
+ marginTop: '-25px',
+ };
+ const configInputStyle = {
+ marginLeft: '30px',
+ width: '60%',
+ };
+ const CreateInputStyle = {
+ marginLeft: '36px',
+ width: '40%',
+ };
+ const AddInputStyle = {
+ marginLeft: '36px',
+ width: '40%',
+ };
+ const DivStyle = {
+ width: '560px',
+ marginBottom: '30px',
+ };
+ const ButtonStyle = {
+ marginLeft: '20px',
+ width: '15%',
+ };
+ const TipDivStyle = {
+ display: 'inline-block',
+ float: 'right',
+ marginRight: '20px',
+ };
+ const asteriskStyle = {
+ float: 'left',
+ color: '#ff0000',
+ };
+ return (
+
+
+
注册
+
+ *
+ {this.state.Common.REGISTER_USERNAME}
+
+
+
+ *
+ 组织归属
+
+
+
+ *
+ 角色类型
+
+
+
+ 其他属性
+
+
+
+
+
+
+
证书私钥领取
+
+ *
+ 用户名
+
+
+
+ *
+ 密码
+
+
+
+ 其他属性
+
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/src/util/fabric.js b/src/util/fabric.js
index 8a8f3a8..3caf677 100644
--- a/src/util/fabric.js
+++ b/src/util/fabric.js
@@ -83,27 +83,11 @@ class FabricClient {
const self = this;
const usrName = self.config.mspid;
logger.info('start to load member user.', ' store_path: ', self.store_path);
- return FabricClientSDK.newDefaultKeyValueStore({ path: self.store_path,
- }).then((stateStore) => {
- logger.info('get stateStore: ', stateStore);
-
- // assign the store to the fabric client
- self.fabricClient.setStateStore(stateStore);
- const cryptoSuite = FabricClientSDK.newCryptoSuite();
-
- // use the same location for the state store (where the users' certificate are kept)
- // and the crypto store (where the users' keys are kept)
- const cryptoStore = FabricClientSDK.newCryptoKeyStore({ path: self.store_path });
- cryptoSuite.setCryptoKeyStore(cryptoStore);
- self.fabricClient.setCryptoSuite(cryptoSuite);
-
- logger.info('almost done');
- return self.fabricClient.getUserContext(usrName, true) // FIXME: usernaem和mspid可能要分开
- .then((user) => {
- self.user = user;
- return Promise.resolve(user);
- });
- });
+ return self.fabricClient.getUserContext(usrName, true)
+ .then((user) => {
+ self.user = user;
+ return Promise.resolve(user);
+ });
}
/**
@@ -497,31 +481,55 @@ class FabricClient {
* 生成证书私钥
* @returns {Promise}
*/
- importCer(keyPath, certPath) {
+ importCer() {
+ const keyPath = this.config.keyPath;
+ const certPath = this.config.certPath;
+ const mspid = this.config.mspid;
+
+ const self = this;
+ logger.debug('keyPath: ', keyPath);
+ logger.debug('certPath: ', certPath);
// -------------------- admin start ---------
- logger.info('start to create admin user.');
- return this.fabricClient.createUser({
- username: this.config.mspid,
- mspid: this.config.mspid,
- cryptoContent: {
- privateKey: keyPath,
- signedCert: certPath,
- },
- })
- .then((user) => {
- if (user && user.isEnrolled()) {
- logger.info('Successfully loaded user1 from persistence, user:', user.toString());
- } else {
- logger.error('Failed to get user1.... run registerUser.js');
- return Promise.reject(new Error('Failed to get user1.... run registerUser.js'));
- }
- logger.info('create fabric client success');
- return Promise.resolve('success');
+ logger.info('start to create user, namely importing certificate and privkey.');
+ return FabricClientSDK.newDefaultKeyValueStore({ path: self.store_path,
+ }).then((stateStore) => {
+ logger.info('get stateStore: ', stateStore);
+
+ // assign the store to the fabric client
+ self.fabricClient.setStateStore(stateStore);
+ const cryptoSuite = FabricClientSDK.newCryptoSuite();
+
+ // use the same location for the state store (where the users' certificate are kept)
+ // and the crypto store (where the users' keys are kept)
+ const cryptoStore = FabricClientSDK.newCryptoKeyStore({ path: self.store_path });
+ cryptoSuite.setCryptoKeyStore(cryptoStore);
+ self.fabricClient.setCryptoSuite(cryptoSuite);
+
+ logger.info('almost done');
+
+ return this.fabricClient.createUser({
+ mspid,
+ username: mspid,
+ cryptoContent: {
+ privateKey: keyPath,
+ signedCert: certPath,
+ },
})
- .catch((err) => {
- logger.error(`Fail to instantiate chaincode. Error message: ${err.stack}` ? err.stack : err);
- return Promise.reject('fail');
- });
+ .then((user) => {
+ if (user && user.isEnrolled()) {
+ logger.info('Successfully loaded user1 from persistence, user:', user.toString());
+ } else {
+ logger.error('Failed to get user1.... run registerUser.js');
+ return Promise.reject(new Error('Failed to get user1.... run registerUser.js'));
+ }
+ logger.info('create fabric client success');
+ return Promise.resolve('success');
+ })
+ .catch((err) => {
+ logger.error(`Fail to instantiate chaincode. Error message: ${err.stack}` ? err.stack : err);
+ return Promise.reject('fail');
+ });
+ });
// ---------------admin finish ---------------
}
@@ -828,6 +836,7 @@ export function getFabricClientSingletonHelper(dbConfig) {
__fabricClient = new FabricClient();
return __fabricClient._getConfig(dbConfig)
.then(input => __fabricClient._config(input))
+ .then(() => __fabricClient.importCer())
.then(() => __fabricClient._loginUser())
.then(() => Promise.resolve(__fabricClient));
}