第十章 Fisco Bcos 权限控制下的数据上链实操演练

 

想了解相关区块链开发,技术提问,请加QQ群:538327407

 

1、目的

 

前面已经完成fisco bcos 相关底层搭建、sdk使用、控制台、webase中间件平台等系列实战开发,

本次进行最后一个部分,体系化管理区块链底层,创建有序的底层控管制度,实现权限化管理。html

完成:链管理、系统管理、数据上链操做等。java

其中数据上链分为:合约版本上链、crudService 版本上链等操做。git


2、准备工做:

 

在进行以前,咱们首先要了解一下,fisco bcos 的底层权限系统介绍。github

https://mp.weixin.qq.com/s/QJNk71w4o_cGX2O-1aW29Qweb

 

3、设计理念差别

 

一、底层默认是能够部署合约,只有一旦操做 grantDeployAndCreateManager 命令,才开始限制用户部署合约权限spring

ps:一开始权限基本开放,而不是像常规系统设计那样,一开始权限为无,等到分配好权限才能够相应的的操做。sql

二、底层默认是写表操做,写表操做就有了CRUD等操做,常规的区块链体系是在不断区块打包过程当中附加数据,Fisco Bcos 提供写表操做,实质上业务数据能够有修改的权限,数据库

因此在链搭建好后,就必须限制Update等操做权限,而且在业务设计时候,须要多方去验证修改数据等过程,才能够防止区块链底层数据让高权限的人的篡改。ubuntu

ps:与官方人员交谈,提供的例子api

好比官方给出的存证的例子,一个证据X,须要A,B机构确认。先是证据X上链(一笔交易),而后机构A看到证据,
确认有效(又一笔交易),机构B演的证据,确认有效(又一笔交易)。三笔交易完成业务共识的逻辑。
别人取证X的时候,读区块链,查看是否A,B都确认过,确认过了,证据X才有效。

 

4、场景构想搭建

 

咱们在底层完成各类系统化的搭建,如今要使用多种方式进行权限管控,以及数据上链等操做。

一、咱们首先要创建链管理员、系统管理员、普通用户。

二、其次咱们要使用控制台 或sdk进行管理员等设定。

三、对合约的部署权限、以及数据权限更新操做作受权。

四、在sdk 中配置受权用户的pem、p12密钥的使用。

五、使用合约操做,进行合约部署,合约CRUD操做。

六、使用CRUDService 进行数据操做。

七、使用PermissionService 进行权限控制。

最后根据咱们设定好的权限,完成多个不一样身份用户进行的数据操做,这样咱们就完成生产环境下的数据上链操做。

 

备注:如下操做,能够参考web3sdk单元测试。官方github web3sdk 地址:https://github.com/FISCO-BCOS/web3sdk

 

5、实操演练

 

(一)建立和管理用户

建立用户,用于后续的管理员设置,进行权限管理设置。

官方资料:https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/tutorial/account.html

fisco bcos 底层 支持控制台建立帐户、sdk 建立帐户

 

先采用控制台进行基础用户建立,以及基本全是设置

在console 目录下 使用bash get_account.sh、bash get_account.sh -p 建立不一样的帐户

Usage: ./get_account.sh

default generate account and store private key in PEM format file(默认生成pem格式用户)
-p generate account and store private key in PKCS12 format file(默认生成p12格式用户)
-k [FILE] calculate address of PEM format [FILE](经过pem 私钥文件生成帐户地址)
-P [FILE] calculate address of PKCS12 format [FILE](经过p12 私钥文件生成帐户地址)
-h Help

 

建立链管理员 ,pem 格式

ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh
[INFO] Account Address : 0x83a37766067ea59eea78135b20a4afc251246e88
[INFO] Private Key (pem) : accounts/0x83a37766067ea59eea78135b20a4afc251246e88.pem

 

建立三个用户

一、具备 发布合约权限的用户

ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh -p
Enter Export Password:123456
Verifying - Enter Export Password:123456
[INFO] Account Address : 0xb93bb9276d97f5f75ea574965beab99f72310e45
[INFO] Private Key (p12) : accounts/0xb93bb9276d97f5f75ea574965beab99f72310e45.p12

 

二、系统管理员

ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh -p
Enter Export Password:
Verifying - Enter Export Password:
[INFO] Account Address : 0xca96eb0e7c70c9117a2b5bda65cbcfc1b37a35c2
[INFO] Private Key (p12) : accounts/0xca96eb0e7c70c9117a2b5bda65cbcfc1b37a35c2.p12

 

三、普通用户

ubuntu@VM-16-14-ubuntu:~/generator/console$ bash get_account.sh -p
Enter Export Password:
Verifying - Enter Export Password:
[INFO] Account Address : 0x190b5d0a7ed4754c9226ee96c50cd125ec5720bf
[INFO] Private Key (p12) : accounts/0x190b5d0a7ed4754c9226ee96c50cd125ec5720bf.p12

 

pem登陆方式:

bash ./start.sh 1 -pem accounts/0x83a37766067ea59eea78135b20a4afc251246e88.pem

 

p12 登陆方式:(须要输入密码)

bash ./start.sh 1 -p12 accounts/0xb93bb9276d97f5f75ea574965beab99f72310e45.p12

 

 

(二)控制台基本权限设置

设定帐户1为链管理员帐户,帐户2为系统管理员帐户,帐户3为普通帐户。


一、链管理员帐户拥有权限管理的权限,即能分配权限。

[group:1]> grantDeployAndCreateManager 0x83a37766067ea59eea78135b20a4afc251246e88
{
"code":0,
"msg":"success"
}

二、系统管理员帐户能够管理系统相关功能的权限,每一种系统功能权限都须要单独分配,
具体包括部署合约和建立用户表的权限、管理节点的权限、利用CNS部署合约的权限以及修改系统参数的权限。
链管理员帐户能够受权其余帐户为链管理员帐户或系统管理员帐户,

 

[group:1]> grantDeployAndCreateManager 0xb93bb9276d97f5f75ea574965beab99f72310e45
{
"code":0,
"msg":"success"
}

 

 

三、也能够受权指定帐号能够写指定的用户表,即普通帐户。

用某个用户登陆后,使用命令赋予权限,前提是他拥有该权限操做

权限命令:https://fisco-bcos-documentation.readthedocs.io/zh_CN/release-2.0/docs/manual/permission_control.html


(三)Sdk下配置

一、将控制台生成account 目录下的文件copy sdk中。

 

 

 applicationContext.xml 文件配置修改,其中包括密钥文件的配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="encryptType" class="org.fisco.bcos.web3j.crypto.EncryptType">
        <constructor-arg value="0"/> <!-- 0:standard 1:guomi -->
    </bean>

    <bean id="groupChannelConnectionsConfig" class="org.fisco.bcos.channel.handler.GroupChannelConnectionsConfig">
        <property name="allChannelConnections">
            <list>  <!-- 每一个群组须要配置一个bean,每一个群组能够配置多个节点 -->
                <bean id="group1"  class="org.fisco.bcos.channel.handler.ChannelConnections">
                    <property name="groupId" value="1" /> <!-- 群组的groupID -->
                    <property name="connectionsStr">
                        <list>
                      
                            <value>对应的节点ip:20201</value>
                            <value>对接节点ip:20200</value>  <!-- IP:channel_port -->
                        
                        </list>
                    </property>
                </bean>
                <bean id="group2"  class="org.fisco.bcos.channel.handler.ChannelConnections">
                    <property name="groupId" value="2" /> <!-- 群组的groupID -->
                    <property name="connectionsStr">
                        <list>
                            <value>127.0.0.1:20202</value>
                            <value>127.0.0.1:20203</value>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>

<bean id="channelService" class="org.fisco.bcos.channel.client.Service" depends-on="groupChannelConnectionsConfig"> <property name="groupId" value="1" /> <!-- 配置链接群组1 --> <property name="agencyName" value="fisco" /> <!-- 配置机构名 --> <property name="allChannelConnections" ref="groupChannelConnectionsConfig"></property> </bean> <bean id="p12" class="org.fisco.bcos.channel.client.P12Manager" init-method="load" > <property name="password" value="123456" /> <property name="p12File" value="classpath:0xb93bb9276d97f5f75ea574965beab99f72310e45.p12" /> </bean> <bean id="pem" class="org.fisco.bcos.channel.client.PEMManager" init-method="load" > <property name="pemFile" value="classpath:0x83a37766067ea59eea78135b20a4afc251246e88.pem" /> </bean> </beans>

若是要写单元测试

也要把相关配置copy 过去,详情见图

 

 (四)单元测试 合约部署,CRUD操做

一、基础设置,包括具备部署合约权限用户设置

  private Credentials credentials;
    private static BigInteger gasPrice = new BigInteger("300000000");
    private static BigInteger gasLimit = new BigInteger("300000000");
    @Autowired
    Web3j web3j;
    protected String tempDirPath =  new File("src/main/resources/").getAbsolutePath();
    //这很重要,没有这个没法经过
    @Before
    public void setUp() throws Exception {
        ApplicationContext context =
                new ClassPathXmlApplicationContext(
                        "classpath:applicationContext-keystore-sample.xml");
        // test p12
        P12Manager p12 = context.getBean(P12Manager.class);
        ECKeyPair p12KeyPair = p12.getECKeyPair();

        System.out.println("p12KeyPair.getPrivateKey() = " + p12KeyPair.getPrivateKey().toString(16));
        System.out.println("p12KeyPair.getPublicKey() = " + p12KeyPair.getPublicKey().toString(16));


        ECPublicKey publicKey = (ECPublicKey) p12.getPublicKey();
        byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
        BigInteger publicKeyValue =
                new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));

        System.out.println("publicKeyValue = " + publicKeyValue.toString(16));

        credentials = Credentials.create(p12KeyPair);//这里将具备合约部署权限的用户设置进去,当前操做对象

        System.out.println("credentials  getAddress= " + credentials.getAddress());
    }

    @After
    public void tearDown() {
    }

二、部署合约

 @Test
    //一、部署合约
    public void DeployTable() throws Exception {
        // 部署合约
        TableTemp tableTemp = TableTemp.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send();

        if (tableTemp != null) {
            System.out.println("TableTemp address is: " + tableTemp.getContractAddress());
        }

    }

三、建立表合约操做,此时,须要用到部署合约时候生成的地址

 //二、建立表操做
    @Test
    public void CreateTableTest()throws Exception  {
        String contractAddress = "0xb4245b7b6cc33f8f65d8bf37f084dec3e31ca573";//合约部署时候的生成的地址
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
        TransactionReceipt receipt = tableTemp.create().send();
        System.out.println("AssetTest.AssetTransfer receipt="+receipt.toString());
    }

 

四、插入表操做(合约地址改成本身测试的,笔者因为屡次单元测试,合约地址不一样)

 

 //3.一、插入表操做 无返回值操做
    @Test
    public void InsertTableTest()throws Exception  {
        String contractAddress = "0x215ac9f7af5766ff45d80082091856b54fcf4308";
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));

        String name = "wq";
        int item_id = Integer.parseInt("2");
        String item_name ="aaa";
        String item_address ="ddd";
        tableTemp.insert(name, BigInteger.valueOf(item_id), item_name,item_address).send();
      
    }

    //3.二、插入表操做
    @Test
    public void InsertTableByReturnTest()throws Exception  {
        String contractAddress = "0xb4245b7b6cc33f8f65d8bf37f084dec3e31ca573";
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));

        String name = "ak";
        int item_id = Integer.parseInt("1");
        String item_name ="tempUser";
        String item_address ="北京";


        TransactionReceipt send = tableTemp.insert(name, BigInteger.valueOf(item_id), item_name, item_address).send();
        System.out.println(" send= "+send.toString());
     
    }

 

五、删除表操做

 //4.1删除表数据操做
    @Test
    public void DeleteTableTest()throws Exception  {
        String contractAddress = "0x215ac9f7af5766ff45d80082091856b54fcf4308";
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
        TransactionReceipt send=  tableTemp.remove("ak",BigInteger.valueOf(1)).send();

        System.out.println("send.toString() = " + send.toString());
        System.out.println("send.getContractAddress() = " + send.getContractAddress());
        System.out.println("send.getBlockHash() = " + send.getBlockHash());
        System.out.println("send.getBlockNumber() = " + send.getBlockNumber());

    }
    //4.2删除表数据操做
    @Test
    public void DeleteTableByReturnTest()throws Exception  {
        String contractAddress = "0xb4245b7b6cc33f8f65d8bf37f084dec3e31ca573";
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));

        int item_id = Integer.parseInt("1");
        String name="ak";
        RemoteCall<TransactionReceipt> remove =
                (RemoteCall<TransactionReceipt>) tableTemp.remove(name,BigInteger.valueOf(item_id));

        TransactionReceipt transactionReceipt = remove.send();
        List<TableTemp.RemoveResultEventResponse> removeResultEvents =
                tableTemp.getRemoveResultEvents(transactionReceipt);
        if (removeResultEvents.size() > 0) {
            TableTemp.RemoveResultEventResponse reomveResultEventResponse = removeResultEvents.get(0);
            System.out.println(
                    "removeCount = " + reomveResultEventResponse.count.intValue());
        } else {
            System.out.println("tableTemp table does not exist.");
        }


    }

六、查询表操做,因为合约返回字段有限,最好不要超过三个,有可能会报错。若是使用返回strust是能够解决该问题的。

开头加上这个:pragma experimental ABIEncoderV2;
返回值能够用struct

 

  //五、表查询
    @Test
    public void SelectTableTest() throws  Exception{
        String contractAddress = "0xa94c07af700bf2e435a3051b0a98f2f75eca0298";
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
        Tuple3<List<byte[]>, List<BigInteger>, List<byte[]>> lists = tableTemp.select("ak").send();
        //这个只是返回合约执行的结果,不会返回自己数据库表数据
     //   System.out.println("send.toString() = " + send.toString());
        List<byte[]> value1 = lists.getValue1();
        List<BigInteger> value2 = lists.getValue2();
        List<byte[]> value3 = lists.getValue3();

        for (int i = 0; i < value1.size(); i++) {
            String name = new String(value1.get(i));

            System.out.println("name = " + name);
            int item_id = value2.get(i).intValue();

            System.out.println("item_id = " + item_id);
            String item_name = new String(value3.get(i));

            System.out.println("item_name = " + item_name);
        }

    }

七、更新表操做,当前笔者还没设置更新操做权限,因此该方法是能够修改表数据

//六、表更新
    @Test
    public void UpateTableTest() throws  Exception{
        String contractAddress = "0xb940c1966a6ce94484f0fdabd3bb8cb38edc9dfd";
        // 加载合约地址
        TableTemp tableTemp = TableTemp.load(contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
        TransactionReceipt ak=  tableTemp.update("ak",BigInteger.valueOf(1),"121","wew").send();
        System.out.println("ak.toString() = " + ak.toString());
    }

 

ps:因为合约操做在实际中返回值等问题,可能存在许多不肯定等坑,因此和官方聊以后,可使用crudService进行表的操做。

 

(五) 采用CrudService 进行表数据操做

CrudService 自己就是对表的操做的服务封装。

这里的单元测试须要用到 基础设置TestBase,主要配置具备表操做权限的用户。

package customTest;

import java.math.BigInteger;
import java.util.Arrays;

import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.fisco.bcos.channel.client.P12Manager;
import org.fisco.bcos.channel.client.Service;
import org.fisco.bcos.web3j.crypto.Credentials;
import org.fisco.bcos.web3j.crypto.ECKeyPair;
import org.fisco.bcos.web3j.protocol.Web3j;
import org.fisco.bcos.web3j.protocol.channel.ChannelEthereumService;
import org.fisco.bcos.web3j.tx.gas.StaticGasProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBase {
  public static ApplicationContext context = null;
  public static Credentials credentials;

  protected static Web3j web3j;
  protected static BigInteger gasPrice = new BigInteger("30000000");
  protected static BigInteger gasLimit = new BigInteger("30000000");
  protected static String address;
  protected static BigInteger blockNumber;
  protected static String blockHash;
  protected static String txHash;

  @BeforeClass
  public static void setUpBeforeClass() throws Exception {

      context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

    Service service = context.getBean(Service.class);
    service.run();

    ChannelEthereumService channelEthereumService = new ChannelEthereumService();
    channelEthereumService.setChannelService(service);

    web3j = Web3j.build(channelEthereumService, service.getGroupId());

    ApplicationContext context =
            new ClassPathXmlApplicationContext(
                    "classpath:applicationContext-keystore-sample.xml");
    // test p12
    P12Manager p12 = context.getBean(P12Manager.class);
    ECKeyPair p12KeyPair = p12.getECKeyPair();

    System.out.println("p12KeyPair.getPrivateKey() = " + p12KeyPair.getPrivateKey().toString(16));
    System.out.println("p12KeyPair.getPublicKey() = " + p12KeyPair.getPublicKey().toString(16));


    ECPublicKey publicKey = (ECPublicKey) p12.getPublicKey();
    byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
    BigInteger publicKeyValue =
            new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));

    System.out.println("publicKeyValue = " + publicKeyValue.toString(16));

    credentials = Credentials.create(p12KeyPair);

    System.out.println("credentials  getAddress= " + credentials.getAddress());
  }

  @AfterClass
  public static void setUpAfterClass() throws Exception {
    ((ClassPathXmlApplicationContext) context).destroy();
  }
}

 

如下是crudservice 的单元测试全过程操做,依法操做就能够了,关键地方已经有了注释。

package customTest;

import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.fisco.bcos.Application;
import org.fisco.bcos.channel.client.P12Manager;
import org.fisco.bcos.temp.TableTemp;
import org.fisco.bcos.web3j.crypto.Credentials;
import org.fisco.bcos.web3j.crypto.ECKeyPair;
import org.fisco.bcos.web3j.precompile.crud.CRUDService;
import org.fisco.bcos.web3j.precompile.crud.Condition;
import org.fisco.bcos.web3j.precompile.crud.Entry;
import org.fisco.bcos.web3j.precompile.crud.Table;
import org.fisco.bcos.web3j.protocol.Web3j;
import org.fisco.bcos.web3j.tx.gas.StaticGasProvider;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertEquals;


/*
* 一、继承 TestBase,配置文件在main的java的resources中applicationContext.xml
* */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class CRUDServiceTest extends TestBase{
    //这里若是设置了权限,那么必须权限用户才可使用,请看TestBase 中的改造,credentials
    private CRUDService crudSerivce = new CRUDService(web3j, credentials);

    @SuppressWarnings("unchecked")
    @Test
    public void CreateTest() throws Exception {

        String tableName = "t_item2";
        String key = "name";
        String valueFields  = "item_id, item_name,item_address,item_count";
        Table table = new Table(tableName, key, valueFields);

        // create table
        int resultCreate = crudSerivce.createTable(table);
        Assert.assertEquals(resultCreate, 0);


    }
    @SuppressWarnings("unchecked")
    @Test
    public  void Insert()throws Exception{

        String tableName = "t_item2";
        String key = "name";

        Table table = new Table(tableName, key);
        int insertResult = 0;
        int num = 5;
        for(int i = 1; i <= num; i++)
        {
            Entry insertEntry = table.getEntry();
            insertEntry.put("item_id", "q");
            insertEntry.put("item_name", "q"+i);
            insertEntry.put("item_address", "q"+i);
            insertEntry.put( "item_count",BigInteger.valueOf(i).toString());
            table.setKey("q");
            insertResult += crudSerivce.insert(table, insertEntry);
        }
        Assert.assertEquals(insertResult, num);

    }
    @SuppressWarnings("unchecked")
    @Test
    public  void  Select()throws Exception{
        String tableName = "t_item2";
        String key = "name";
        Table table = new Table(tableName, key);
        // select records
        Condition condition1 = table.getCondition();
        condition1.EQ("name", "q");
        condition1.EQ("item_id", "q");
       // condition1.Limit(1);
        table.setKey("q");//查询记录sql语句必须在where子句中提供表的主键字段值。

        List<Map<String, String>> resultSelect1 = crudSerivce.select(table, condition1);
        Assert.assertEquals(resultSelect1.get(0).get("name"), "q");
        Assert.assertEquals(resultSelect1.get(0).get("item_id"), "q");
        Assert.assertEquals(resultSelect1.get(0).get("item_name"), "q1");
    }
    @SuppressWarnings("unchecked")
    @Test
    public void Update() throws Exception{
        String tableName = "t_item2";
        String key = "name";
        Table table = new Table(tableName, key);
        int num = 5;
        table.setKey("q");//查询记录sql语句必须在where子句中提供表的主键字段值。
        Entry updateEntry = table.getEntry();
        updateEntry.put("item_id", "徐徐吹v下次v");
        updateEntry.put("item_name", "121212");
        Condition updateCondition = table.getCondition();
        updateCondition.EQ("name", "q");
        updateCondition.EQ("item_id", "aaaaa");
        int updateResult = crudSerivce.update(table, updateEntry, updateCondition);
        Assert.assertEquals(updateResult, num);
    }
}

 

ps:上述操做除了建立表有权限用户须要操做,其余的操做任意用户都可以操做。

(六)进行权限操做

 

本例子,就是经过第一次建立表操做,无受权和有受权等模式屡次测试,从而进行验证当咱们设置表更新权限后,没有表更新权限的用户是没法进行更新表操做的,赋予这个用户更新表操做的权限后,就能够进行表更新操做。

package customTest;

import org.fisco.bcos.channel.client.PEMManager;
import org.fisco.bcos.temp.TableTemp;
import org.fisco.bcos.web3j.crypto.Credentials;
import org.fisco.bcos.web3j.crypto.ECKeyPair;
import org.fisco.bcos.web3j.precompile.crud.CRUDService;
import org.fisco.bcos.web3j.precompile.crud.Condition;
import org.fisco.bcos.web3j.precompile.crud.Entry;
import org.fisco.bcos.web3j.precompile.crud.Table;
import org.fisco.bcos.web3j.precompile.permission.PermissionService;
import org.fisco.bcos.web3j.tx.gas.StaticGasProvider;
import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class PermissionTest extends TestBase {



    @Test
    // 受权新建立用户的权限,测试它部署合约的权限,正常不受权没法部署
    public void PermissionDeploy() throws Exception {

        //一、初始化建立一个用户,没有在底层注册过的
        String tempAddress="0x80e3c3f1f1140fbc550fbfdaa318073af373141d";
        String tempPriKey="9265efb6b860ef244f4fbe3dd445f7829e86d11226573190c026323f77ebcd22";
        String tempPublicKey="1f9c09a4df7e336961c06e1f2373fb2ef6a1b642c444652a7a5a84b04bdc668431bbddab4a1665cb382d6a94aee9ff18bf88210bae7a2388315b2bc5253bcaa";


        //pem  链管理员进行操做,对新用户进行合约部署权限受权
        PEMManager pem = context.getBean(PEMManager.class);
        ECKeyPair pemKeyPair = pem.getECKeyPair();

        //一、链管理员操做 受权新用户的能够发布和部署合约
        credentials = Credentials.create(pemKeyPair);
         PermissionService permissionService = new PermissionService(web3j, credentials);
        String s = permissionService.grantDeployAndCreateManager(tempAddress);
        System.out.println("s = " + s);//这个是受权状态

        //二、使用新用户新合约部署测试
        Credentials userCredentials=Credentials.create(tempPriKey,tempPublicKey);
        // 部署合约
        TableTemp tableTemp = TableTemp.deploy(web3j, userCredentials, new StaticGasProvider(gasPrice, gasLimit)).send();

        if (tableTemp != null) {
            System.out.println("TableTemp address is: " + tableTemp.getContractAddress());
        }

    }
    @Test
    // 受权新建立用户的权限,用户表操做修改权限
    public void PermissionGrantUserTable() throws Exception {

        //一、初始化建立一个用户,没有在底层注册过的
        String tempAddress="0x80e3c3f1f1140fbc550fbfdaa318073af373141d";
        String tempPriKey="9265efb6b860ef244f4fbe3dd445f7829e86d11226573190c026323f77ebcd22";
        String tempPublicKey="1f9c09a4df7e336961c06e1f2373fb2ef6a1b642c444652a7a5a84b04bdc668431bbddab4a1665cb382d6a94aee9ff18bf88210bae7a2388315b2bc5253bcaa";


        //pem  链管理员进行操做,对新用户进行合约部署权限受权
        PEMManager pem = context.getBean(PEMManager.class);
        ECKeyPair pemKeyPair = pem.getECKeyPair();

        //一、链管理员操做 受权新用户的能够发布和部署合约
        credentials = Credentials.create(pemKeyPair);
        PermissionService permissionService = new PermissionService(web3j, credentials);
        String s = permissionService.grantUserTableManager("t_item2",tempAddress);
        System.out.println("s = " + s);//这个是受权状态

        //二、使用新用户进行表更新 操做
        Credentials userCredentials=Credentials.create(tempPriKey,tempPublicKey);
         //完成后,测试表操做中update操做看看是否能够成功
        CRUDService crudSerivce = new CRUDService(web3j, userCredentials);
        String tableName = "t_item2";
        String key = "name";
        Table table = new Table(tableName, key);
        int num = 5;
        table.setKey("q");//查询记录sql语句必须在where子句中提供表的主键字段值。
        Entry updateEntry = table.getEntry();
        updateEntry.put("item_id", "徐徐吹v下次v");
        updateEntry.put("item_name", "121212");
        Condition updateCondition = table.getCondition();
        updateCondition.EQ("name", "q");
        updateCondition.EQ("item_id", "aaaaa");
        int updateResult = crudSerivce.update(table, updateEntry, updateCondition);
        Assert.assertEquals(updateResult, num);

        //结果测试成功,使用受权用户操做的表,能够进行更新操做;不然,不具有这个权限的用户,是没法操做的
    }

}

 

6、总结

根据本篇教程,能够完成底层权限设置、以及sdk实际权限控制操做、最后实现数据上链等等。读者能够根据本身的业务需求修改表结构,依照上述流程能够在生产环境中大体进行业务开发。

系列教程到此,暂时告一段落,基本从头至尾能够按照每一章节对Fisco Bcos 流程从头至尾进行一次模拟生产环境的实践。