Skip to content

Commit ce79bc1

Browse files
authored
Merge branch 'main' into fix-677-node-selection
2 parents f99cd52 + ae81505 commit ce79bc1

File tree

13 files changed

+285
-98
lines changed

13 files changed

+285
-98
lines changed

src/api-engine/api/lib/peer/chaincode.py

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,15 @@ def lifecycle_query_installed(self, timeout):
6363
"""
6464

6565
try:
66-
res = subprocess.Popen("{} lifecycle chaincode queryinstalled --output json --connTimeout {}"
67-
.format(self.peer, timeout), shell=True,
68-
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
66+
command = [
67+
self.peer,
68+
"lifecycle", "chaincode", "queryinstalled",
69+
"--output", "json",
70+
"--connTimeout", timeout
71+
]
72+
LOG.info(" ".join(command))
73+
res = subprocess.Popen(command, shell=False,
74+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
6975

7076
stdout, stderr = res.communicate()
7177
return_code = res.returncode
@@ -106,8 +112,8 @@ def lifecycle_get_installed_package(self, timeout):
106112
raise Exception(err_msg)
107113
return res_return
108114

109-
def lifecycle_approve_for_my_org(self, orderer_url, orderer_tls_rootcert, channel_name, cc_name,
110-
chaincode_version, policy, sequence=1):
115+
def lifecycle_approve_for_my_org(self, orderer_url, channel_name, cc_name,
116+
chaincode_version, sequence, policy, init_flag):
111117
"""
112118
The administrator can use the peer lifecycle chaincode approveformyorg subcommand to approve the chain code on
113119
behalf of the organization.
@@ -116,8 +122,9 @@ def lifecycle_approve_for_my_org(self, orderer_url, orderer_tls_rootcert, channe
116122
:param channel_name: channel name
117123
:param cc_name: chaincode name
118124
:param chaincode_version: chaincode version
119-
:param policy: chaincode policy
120125
:param sequence: The channel chain code defines the serial number. The default value is 1
126+
:param policy: chaincode policy
127+
:param init_flag: if the chaincode is first init.
121128
:return:
122129
"""
123130
try:
@@ -131,18 +138,43 @@ def lifecycle_approve_for_my_org(self, orderer_url, orderer_tls_rootcert, channe
131138
if package_id == "":
132139
return 1, "not exist the chaincode, please check chaincode_name and chaincode_version"
133140

141+
command = []
134142
if os.getenv("CORE_PEER_TLS_ENABLED") == "false" or os.getenv("CORE_PEER_TLS_ENABLED") is None:
135-
res = subprocess.Popen("{} lifecycle chaincode approveformyorg -o {} - --channelID {} --name {} "
136-
"--version {} --init-required --package-id {} --sequence {} --signature-policy {}"
137-
.format(self.peer, orderer_url, channel_name, cc_name, chaincode_version, package_id,
138-
sequence, policy), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
143+
command = [
144+
self.peer,
145+
"lifecycle", "chaincode", "approveformyorg",
146+
"-o", orderer_url,
147+
"--channelID", channel_name,
148+
"--name", cc_name,
149+
"--version", chaincode_version,
150+
"--package-id", package_id,
151+
"--sequence", str(sequence)
152+
]
139153
else:
140-
res = subprocess.Popen("{} lifecycle chaincode approveformyorg -o {} --tls --cafile {} --channelID {} "
141-
"--name {} --version {} --init-required --package-id {} --sequence {} "
142-
"--signature-policy {}"
143-
.format(self.peer, orderer_url, orderer_tls_rootcert, channel_name,
144-
cc_name, chaincode_version, package_id, sequence, policy), shell=True,
145-
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
154+
ORDERER_CA = os.getenv("ORDERER_CA")
155+
command = [
156+
self.peer,
157+
"lifecycle", "chaincode", "approveformyorg",
158+
"-o", orderer_url,
159+
"--ordererTLSHostnameOverride", orderer_url.split(":")[0],
160+
"--channelID", channel_name,
161+
"--name", cc_name,
162+
"--version", chaincode_version,
163+
"--package-id", package_id,
164+
"--sequence", str(sequence),
165+
"--tls",
166+
"--cafile", ORDERER_CA
167+
]
168+
169+
if init_flag:
170+
command.append("--init-required")
171+
if policy:
172+
command.append("--signature-policy")
173+
command.append(policy)
174+
175+
LOG.info(" ".join(command))
176+
res = subprocess.Popen(command, shell=False,
177+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
146178
stdout, stderr = res.communicate()
147179
return_code = res.returncode
148180

src/api-engine/api/routes/chaincode/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ class ChainCodeApproveForMyOrgBody(serializers.Serializer):
6262
channel_name = serializers.CharField(max_length=128, required=True)
6363
chaincode_name = serializers.CharField(max_length=128, required=True)
6464
chaincode_version = serializers.CharField(max_length=128, required=True)
65-
policy = serializers.CharField(max_length=128, required=True)
66-
orderer_url = serializers.CharField(max_length=128, required=True)
6765
sequence = serializers.IntegerField(min_value=1, required=True)
66+
policy = serializers.CharField(max_length=128, required=False, allow_blank=True)
67+
init_flag = serializers.BooleanField(required=False)
6868

6969

7070
class ChainCodeCommitBody(ChainCodeApproveForMyOrgBody):

src/api-engine/api/routes/chaincode/views.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -361,35 +361,27 @@ def approve_for_my_org(self, request):
361361
try:
362362
channel_name = serializer.validated_data.get("channel_name")
363363
chaincode_name = serializer.validated_data.get("chaincode_name")
364-
chaincode_version = serializer.validated_data.get(
365-
"chaincode_version")
366-
policy = serializer.validated_data.get("policy")
367-
# Perhaps the orderer's port is best stored in the database
368-
orderer_url = serializer.validated_data.get("orderer_url")
364+
chaincode_version = serializer.validated_data.get("chaincode_version")
365+
policy = serializer.validated_data.get("policy", "")
369366
sequence = serializer.validated_data.get("sequence")
367+
init_flag = serializer.validated_data.get("init_flag", False)
370368

371369
org = request.user.organization
372370
qs = Node.objects.filter(type="orderer", organization=org)
373371
if not qs.exists():
374372
raise ResourceNotFound
375373
orderer_node = qs.first()
374+
orderer_url = orderer_node.name + "." + org.name.split(".", 1)[1] + ":" + str(7050)
376375

377-
orderer_tls_dir = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/msp/tlscacerts" \
378-
.format(CELLO_HOME, org.name, org.name.split(".", 1)[1], orderer_node.name + "." +
379-
org.name.split(".", 1)[1])
380-
orderer_tls_root_cert = ""
381-
for _, _, files in os.walk(orderer_tls_dir):
382-
orderer_tls_root_cert = orderer_tls_dir + "/" + files[0]
383-
break
384376
qs = Node.objects.filter(type="peer", organization=org)
385377
if not qs.exists():
386378
raise ResourceNotFound
387379
peer_node = qs.first()
388380
envs = init_env_vars(peer_node, org)
389381

390382
peer_channel_cli = PeerChainCode(**envs)
391-
code, content = peer_channel_cli.lifecycle_approve_for_my_org(orderer_url, orderer_tls_root_cert, channel_name,
392-
chaincode_name, chaincode_version, policy, sequence)
383+
code, content = peer_channel_cli.lifecycle_approve_for_my_org(orderer_url, channel_name,
384+
chaincode_name, chaincode_version, sequence, policy, init_flag)
393385
if code != 0:
394386
return Response(err(" lifecycle_approve_for_my_org failed. err: " + content), status=status.HTTP_400_BAD_REQUEST)
395387
except Exception as e:

src/dashboard/config/config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ export default {
1111
antd: {},
1212
locale: {
1313
default: 'en-US',
14-
antd: false,
15-
title: false,
16-
baseNavigator: true,
14+
antd: true,
15+
title: true,
16+
baseNavigator: false,
1717
baseSeparator: '-',
1818
},
1919
pwa: false,

src/dashboard/src/components/SelectLang/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import styles from './index.less';
99
class SelectLang extends PureComponent {
1010
changeLang = ({ key }) => {
1111
setLocale(key);
12+
localStorage.setItem('umi_locale', key);
1213
};
1314

1415
render() {

src/dashboard/src/layouts/BasicLayout.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/*
22
SPDX-License-Identifier: Apache-2.0
33
*/
4-
import React from 'react';
4+
import React, { Component } from 'react';
55
import { Layout } from 'antd';
66
import DocumentTitle from 'react-document-title';
7-
import { connect } from 'umi';
7+
import { connect, setLocale, getLocale } from 'umi';
88
import { ContainerQuery } from 'react-container-query';
99
import classNames from 'classnames';
1010
import Media from 'react-media';
@@ -46,7 +46,7 @@ const query = {
4646
},
4747
};
4848

49-
class BasicLayout extends React.Component {
49+
class BasicLayout extends Component {
5050
componentDidMount() {
5151
const {
5252
dispatch,
@@ -62,6 +62,17 @@ class BasicLayout extends React.Component {
6262
type: 'menu/getMenuData',
6363
payload: { routes, path, authority },
6464
});
65+
66+
// Initialize language from localStorage or default to English
67+
const savedLocale = localStorage.getItem('umi_locale');
68+
const currentLocale = getLocale();
69+
70+
if (savedLocale && savedLocale !== currentLocale) {
71+
setLocale(savedLocale);
72+
} else if (!savedLocale) {
73+
setLocale('en-US');
74+
localStorage.setItem('umi_locale', 'en-US');
75+
}
6576
}
6677

6778
getContext() {

src/dashboard/src/locales/en-US.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,29 @@ export default {
2626
'app.forms.basic.title': 'Basic form',
2727
'app.forms.basic.description':
2828
'Form pages are used to collect or verify information to users, and basic forms are common in scenarios where there are fewer data items.',
29+
30+
// Error messages
31+
'error.request.200': 'Server successfully returned requested data.',
32+
'error.request.201': 'Created or modified data successfully.',
33+
'error.request.202': 'A request has entered the background queue.',
34+
'error.request.204': 'Data deleted successfully.',
35+
'error.request.400': 'Bad request, server did not create or modify data.',
36+
'error.request.401': 'User does not have permission (token, username, password error).',
37+
'error.request.403': 'User is authorized but access is forbidden.',
38+
'error.request.404': 'Request made to non-existent record, server did not operate.',
39+
'error.request.406': 'Requested format not available.',
40+
'error.request.410': 'Requested resource permanently deleted and will not be available again.',
41+
'error.request.422': 'Validation error occurred while creating an object.',
42+
'error.request.500': 'Server error, please check server.',
43+
'error.request.502': 'Gateway error.',
44+
'error.request.503': 'Service unavailable, server temporarily overloaded or maintaining.',
45+
'error.request.504': 'Gateway timeout.',
46+
'error.network': 'Network error, please check your connection.',
47+
'error.login.invalidCredentials': 'Invalid username or password.',
48+
'error.login.expired': 'Not logged in or session expired. Please log in again.',
49+
'error.register.duplicate': 'Email address or organization name already exists.',
50+
'error.request.generic': 'Request error: {status}',
51+
2952
...exception,
3053
...globalHeader,
3154
...login,

src/dashboard/src/locales/zh-CN.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,29 @@ export default {
2626
'app.forms.basic.title': '基础表单',
2727
'app.forms.basic.description':
2828
'表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。',
29+
30+
// Error messages
31+
'error.request.200': '服务器成功返回请求的数据。',
32+
'error.request.201': '新建或修改数据成功。',
33+
'error.request.202': '一个请求已经进入后台排队(异步任务)。',
34+
'error.request.204': '删除数据成功。',
35+
'error.request.400': '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
36+
'error.request.401': '用户没有权限(令牌、用户名、密码错误)。',
37+
'error.request.403': '用户得到授权,但是访问是被禁止的。',
38+
'error.request.404': '发出的请求针对的是不存在的记录,服务器没有进行操作。',
39+
'error.request.406': '请求的格式不可得。',
40+
'error.request.410': '请求的资源被永久删除,且不会再得到的。',
41+
'error.request.422': '当创建一个对象时,发生一个验证错误。',
42+
'error.request.500': '服务器发生错误,请检查服务器。',
43+
'error.request.502': '网关错误。',
44+
'error.request.503': '服务不可用,服务器暂时过载或维护。',
45+
'error.request.504': '网关超时。',
46+
'error.network': '网络错误,请检查您的网络连接。',
47+
'error.login.invalidCredentials': '用户名或密码错误。',
48+
'error.login.expired': '未登录或登录已过期,请重新登录。',
49+
'error.register.duplicate': '邮箱地址或组织名已存在。',
50+
'error.request.generic': '请求错误:{status}',
51+
2952
...exception,
3053
...globalHeader,
3154
...login,

src/dashboard/src/models/chaincode.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { listChainCode, uploadChainCode, installChainCode } from '@/services/chaincode';
1+
import {
2+
listChainCode,
3+
uploadChainCode,
4+
installChainCode,
5+
approveChainCode,
6+
} from '@/services/chaincode';
27

38
export default {
49
namespace: 'chainCode',
@@ -42,6 +47,12 @@ export default {
4247
callback(response);
4348
}
4449
},
50+
*approveChainCode({ payload, callback }, { call }) {
51+
const response = yield call(approveChainCode, payload);
52+
if (callback) {
53+
callback(response);
54+
}
55+
},
4556
},
4657
reducers: {
4758
save(state, { payload }) {

src/dashboard/src/pages/ChainCode/ChainCode.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,25 @@ class ChainCode extends PureComponent {
123123
});
124124
};
125125

126+
handleApprove = (values, callback) => {
127+
const { dispatch } = this.props;
128+
129+
const payload = {
130+
channel_name: values.channel,
131+
chaincode_name: values.name,
132+
chaincode_version: values.version,
133+
sequence: parseInt(values.sequence, 10),
134+
policy: values.policy,
135+
init_flag: !!values.initFlag,
136+
};
137+
138+
dispatch({
139+
type: 'chainCode/approveChainCode',
140+
payload,
141+
callback,
142+
});
143+
};
144+
126145
handleUpload = (values, callback) => {
127146
const { dispatch } = this.props;
128147
const formData = new FormData();
@@ -194,8 +213,13 @@ class ChainCode extends PureComponent {
194213
approveModalVisible,
195214
handleApproveModalVisible: this.handleApproveModalVisible,
196215
fetchChainCodes: this.fetchChainCodes,
216+
handleApprove: this.handleApprove,
197217
approving,
198218
selectedRows: [],
219+
initFlagChange: e => {
220+
// this can be used to handle the initFlag change, currently only for demo
221+
console.log('initFlag changed:', e.target.checked);
222+
},
199223
intl,
200224
};
201225

0 commit comments

Comments
 (0)