# 练习 2: 权限管理

## 练习目的
在这个练习中，您将会学习管理用户的权限并且创建角色，将角色赋予用户。

## 先决条件
+ 注意，您的练习环境（包括 IP，端口号，用户名，密码和目录）可能和练习不同。
+ 可以连接到练习用虚拟机。
+ TiDB 数据库已经部署完毕。


1. 以 root 用户登录 TiDB，创建 `test` 数据库中的表 `emp`.
```sql
> CREATE TABLE emp(id int, name varchar(20));
```
```sql
> INSERT INTO emp VALUES(1,'tom');
```

```sql
> INSERT INTO emp VALUES(2,'jack');
```

2. 创建新用户 `'jack'@'120.131.9.24'` ，密码为 `pingcap`.
```sql
> CREATE USER 'jack'@'120.131.9.24' IDENTIFIED BY 'pingcap';
```


3. 创建新的角色 `r_mgr` 和 `r_emp`.
```sql
> CREATE ROLE r_mgr, r_emp;
```


4. 将 `test` 数据库中的表 `emp` 的读权限赋权给角色 `r_emp`.
```sql
> GRANT SELECT ON test.emp TO r_emp;
```


5. 将 `test` 数据库中的所有表的 `INSERT`, `UPDATE` 和 `DELETE` 权限赋权给角色 `r_mgr`.
```sql
> GRANT INSERT, UPDATE, DELETE ON test.* TO r_mgr;
```


6. 将角色 `r_emp` 赋予角色 `r_mgr` 和用户 `'jack'@'120.131.9.24’`.
```sql
> GRANT r_emp TO r_mgr, 'jack'@'120.131.9.24';
```


7. 以 root 用户登录，创建 `test` 数据库中的表 `dept`.
```sql
> CREATE TABLE dept(id int, dname varchar(20));
```

```sql
> INSERT INTO dept VALUES(1, 'dev');
```

```sql
> INSERT INTO dept VALUES(2, 'sales');
```

8. 将 `test` 数据库中的 `dept` 表的 `SELECT` 权限赋予用户 `'jack'@'120.131.9.24'`.
```sql
> GRANT SELECT ON test.dept TO 'jack'@'120.131.9.24';
```


9. 开启新的会话，以用户 `'jack'@'120.131.9.24'` 连接数据库（请根据自己实验环境输入密码）.
```
$ mysql -h120.131.9.24 -P4000 -ujack -ppingcap
```


10. 切换当前数据库到 `test`，之后查询表 `emp` 的第一行和表 `dept` 的第一行. 发现: 1. 用户 `'jack'@'120.131.9.24'` 无法查询表 `emp`, 因为权限是通过角色 `r_emp` 赋予的,但是这个角色并没有在会话中开启. 2. 用户 `'jack'@'120.131.9.24'` 可以查询表 `dept`, 因为权限是直接赋予用户的.
```sql
> USE test;
```

```sql
> SELECT * FROM emp LIMIT 1;
```

```sql
> SELECT * FROM dept LIMIT 1;
```


11. 检查用户 `'jack'@'120.131.9.24'` 所在会话的权限. 发现: 1.会话没有开启任何角色. 2.用户虽然被赋予了角色 `r_emp`, 但是这个角色并没有开启.
```sql
> SELECT current_role();
```

```sql
> SHOW GRANTS;
```


12. 我们接下来为用户 `'jack'@'120.131.9.24'` 开启角色 `r_emp`, 发现：当开启角色后，`SHOW GRANTs;` 的结果显示了用户 `'jack'@'120.131.9.24'` 所有的权限，包括通过角色赋予的权限.
```sql
> SET ROLE ALL;
```

```sql
> SELECT current_role();
```

```sql
> SHOW GRANTs;
```


13. 接下来继续查询 `test` 数据库中的表 `emp` 的第一行. 发现用户 `'jack'@'120.131.9.24'` 通过角色 `r_emp` 赋予了查询 `test` 数据库下面的表 `emp` 的第一行的权限。
```sql
> SELECT * FROM emp LIMIT 1 ;
```


14. 尝试删除 `test` 数据库下的表 `emp` 的第一行. 发现用户 `'jack'@'120.131.9.24'` 并没有删除权限.
```sql
> DELETE FROM emp WHERE id=1;
```

## 步骤 10 输出样例
```sql
> SELECT * FROM emp LIMIT 1;
ERROR 1142 (42000): SELECT command denied TO user 'jack'@'120.131.9.24' for TABLE 'emp'
```

```sql
> SELECT * FROM dept LIMIT 1;
+------+-------+
| id   | dname |
+------+-------+
|    1 | dev   |
+------+-------+
1 row in set (0.00 sec)
```


## 步骤 11 输出样例
```sql
> SELECT current_role();
+----------------+
| current_role() |
+----------------+
| NONE           |
+----------------+
1 row in set (0.00 sec)
```
```sql
> SHOW GRANTs;
+----------------------------------------------------+
| GRANTs for User                                    |
+----------------------------------------------------+
| GRANT USAGE ON *.* TO 'jack'@'120.131.9.24'        |
| GRANT SELECT ON test.dept TO 'jack'@'120.131.9.24' |
| GRANT 'r_emp'@'%' TO 'jack'@'120.131.9.24'         |
+----------------------------------------------------+
3 rows in set (0.00 sec)
```


## 步骤 12 输出样例
```sql
> SELECT current_role();
+----------------+
| current_role() |
+----------------+
| `r_emp`@`%`    |
+----------------+
1 row in set (0.01 sec)
```
```sql
> SHOW GRANTs;
+----------------------------------------------------+
| GRANTs for User                                    |
+----------------------------------------------------+
| GRANT USAGE ON *.* TO 'jack'@'120.131.9.24'        |
| GRANT SELECT ON test.dept TO 'jack'@'120.131.9.24' |
| GRANT SELECT ON test.emp TO 'jack'@'120.131.9.24'  |
| GRANT 'r_emp'@'%' TO 'jack'@'120.131.9.24'         |
+----------------------------------------------------+
4 rows in set (0.00 sec)
```


步骤 13 输出样例
```sql
> SELECT * FROM emp LIMIT 1 ;
+------+------+
| id   | name |
+------+------+
|    1 | tom  |
+------+------+
1 row in set (0.01 sec)
```
