Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP:Write a business demo code use Hertz #75

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions bizdemo/hertz_casbin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
*.o
*.a
*.so
_obj
_test
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.exe~
*.test
*.prof
*.rar
*.zip
*.gz
*.psd
*.bmd
*.cfg
*.pptx
*.log
*nohup.out
*settings.pyc
*.sublime-project
*.sublime-workspace
!.gitkeep
.DS_Store
/.idea
/.vscode
/output
*.local.yml
dumped_hertz_remote_config.json

3 changes: 3 additions & 0 deletions bizdemo/hertz_casbin/.hz
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Code generated by hz. DO NOT EDIT.

hz version: v0.5.1
61 changes: 61 additions & 0 deletions bizdemo/hertz_casbin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# hertz_casbin

## Introduce

A demo with `Hertz` and `Casbin`, this demo aims to understand the application of rbac.

Casbin is a powerful and efficient open-source access control library for Golang projects. It provides support for enforcing authorization based on various access control models.

- Use `thrift` IDL to define `HTTP` interface
- Use `hz` to generate code
- Use `casbin` to judgment authority
- Use `Gorm` and `MySQL`
- Use `JWT` to complete login and authentication


## casbin

Simplistic Example of role-based HTTP Authorization with [casbin](https://github.com/casbin/casbin) using [scs](https://github.com/alexedwards/scs) for session handling.

## IDL

This demo use `thrift` IDL to define `HTTP` interface. The specific interface define in [user.thrift](idl/casbin.thrift)

## Code generation tool

This demo use `hz` to generate code. The use of `hz` refers to [hz](https://www.cloudwego.io/docs/hertz/tutorials/toolkit/toolkit/)

The `hz` commands used can be found in [Makefile](Makefile)

## Binding and Validate

The use of binding and Validate refers
to [Binding and Validate](https://www.cloudwego.io/docs/hertz/tutorials/basic-feature/binding-and-validate/)

## Gorm

This demo use `Gorm` to operate `MySQL` and refers to [Gorm](https://gorm.io/)


## How to run

### Run MySQL

```bash
cd bizdemo/hertz_casbin && docker-compose up
```

### Generate MySQL table

Connect MySQL and execute [casbin.sql](biz/model/sql/casbin.sql)

### Run demo

```bash
cd bizdemo/hertz_casbin
go run .

```



24 changes: 24 additions & 0 deletions bizdemo/hertz_casbin/biz/dal/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dal

import "github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/dal/mysql"

func Init() {
mysql.Init()

}
46 changes: 46 additions & 0 deletions bizdemo/hertz_casbin/biz/dal/mysql/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package mysql

import (
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/model/casbin"
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/consts"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)

var DB *gorm.DB

func Init() {
var err error
DB, err = gorm.Open(mysql.Open(consts.MysqlDSN), &gorm.Config{
SkipDefaultTransaction: true,
PrepareStmt: true,
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
panic(err)
}
m := DB.Migrator()
if m.HasTable(&casbin.User{}) {
return
}
if err = m.CreateTable(&casbin.User{}, &casbin.Role{}, &casbin.Permission{}, &casbin.UserRole{}, &casbin.PermissionRole{}); err != nil {
panic(err)
}
}
55 changes: 55 additions & 0 deletions bizdemo/hertz_casbin/biz/dal/mysql/permission.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package mysql

import "github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/model/casbin"

func CreatePermission(permission *casbin.Permission) error {
return DB.Create(permission).Error
}

func BindPermissionRole(permissionRole *casbin.PermissionRole) error {
return DB.Create(permissionRole).Error
}

func QueryPermissionById(id int) (*casbin.Permission, error) {
var permission casbin.Permission
DB.First(&permission, id)
return &permission, nil
}

func QueryPermissionByV(v1 string, v2 string) (*casbin.Permission, error) {
var permission casbin.Permission
DB.Where("v1= ? AND v2 =?", v1, v2).First(&permission)
return &permission, nil
}

func QuerypermissionRoleByIds(pid, rid int) []casbin.PermissionRole {

var permissionRole []casbin.PermissionRole
tx := DB.Model(new(casbin.PermissionRole))
if pid != 0 {
tx.Where("pid= ?", pid)
}
if rid != 0 {
tx.Where("rid= ?", rid)
}

tx.Select("pid,rid,id").Find(&permissionRole)

return permissionRole
}
69 changes: 69 additions & 0 deletions bizdemo/hertz_casbin/biz/dal/mysql/role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package mysql

import (
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/model/casbin"
)

func CreateRole(role *casbin.Role) error {
return DB.Create(role).Error
}

func BindRole(userRole *casbin.UserRole) error {
return DB.Create(userRole).Error
}

func QueryRoleById(id int) (*casbin.Role, error) {
var role casbin.Role
DB.First(&role, id)
return &role, nil
}

func QueryRoleByName(name string) (*casbin.Role, error) {
var role casbin.Role
DB.Where("name= ?", name).First(&role)
return &role, nil
}

func QueryUserRoleByIds(uid, rid int) []casbin.UserRole {

var userRole []casbin.UserRole
tx := DB.Model(new(casbin.UserRole))
if uid != 0 {
tx.Where("uid= ?", uid)
}
if rid != 0 {
tx.Where("rid= ?", rid)
}

tx.Select("rid,uid,id").Find(&userRole)

return userRole
}

func QueryRolesByUid(uid int) []casbin.Role {

var userRole []casbin.Role
_ = DB.Model(new(casbin.UserRole)).
Joins("LEFT JOIN roles on roles.id=user_roles.rid ").
Select("roles.id,roles.name").
Where("user_roles.uid=?", uid).
Scan(&userRole)

return userRole
}
42 changes: 42 additions & 0 deletions bizdemo/hertz_casbin/biz/dal/mysql/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package mysql

import "github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/model/casbin"

func CreateUser(user *casbin.User) error {
return DB.Create(user).Error

}

func QueryUser(username, password string) (*casbin.User, error) {
var user casbin.User
DB.Where("username=? AND password =? ", username, password).First(&user)
return &user, nil
}

func QueryUserByUsername(username string) (*casbin.User, error) {
var user casbin.User
DB.Where("username = ?", username).First(&user)
return &user, nil
}

func QueryUserById(id int) (*casbin.User, error) {
var user casbin.User
DB.First(&user, id)
return &user, nil
}
151 changes: 151 additions & 0 deletions bizdemo/hertz_casbin/biz/handler/casbin/permission_service.go
92 changes: 92 additions & 0 deletions bizdemo/hertz_casbin/biz/handler/casbin/role_service.go
74 changes: 74 additions & 0 deletions bizdemo/hertz_casbin/biz/handler/casbin/user_service.go
33 changes: 33 additions & 0 deletions bizdemo/hertz_casbin/biz/handler/ping.go
5,319 changes: 5,319 additions & 0 deletions bizdemo/hertz_casbin/biz/model/casbin/casbin.go

Large diffs are not rendered by default.

151 changes: 151 additions & 0 deletions bizdemo/hertz_casbin/biz/model/sql/casbin.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
Navicat Premium Data Transfer
Source Server : 9912
Source Server Type : MySQL
Source Server Version : 80032
Source Host : localhost:9912
Source Schema : casbin
Target Server Type : MySQL
Target Server Version : 80032
File Encoding : 65001
Date: 03/02/2023 12:19:00
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for casbin_rule
-- ----------------------------
DROP TABLE IF EXISTS `casbin_rule`;
CREATE TABLE `casbin_rule` (
`p_type` varchar(100) DEFAULT NULL,
`v0` varchar(100) DEFAULT NULL,
`v1` varchar(100) DEFAULT NULL,
`v2` varchar(100) DEFAULT NULL,
`v3` varchar(100) DEFAULT NULL,
`v4` varchar(100) DEFAULT NULL,
`v5` varchar(100) DEFAULT NULL,
KEY `IDX_casbin_rule_v5` (`v5`),
KEY `IDX_casbin_rule_p_type` (`p_type`),
KEY `IDX_casbin_rule_v0` (`v0`),
KEY `IDX_casbin_rule_v1` (`v1`),
KEY `IDX_casbin_rule_v2` (`v2`),
KEY `IDX_casbin_rule_v3` (`v3`),
KEY `IDX_casbin_rule_v4` (`v4`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of casbin_rule
-- ----------------------------
BEGIN;
INSERT INTO `casbin_rule` (`p_type`, `v0`, `v1`, `v2`, `v3`, `v4`, `v5`) VALUES ('p', 'admin', '/*', '*', '', '', '');
INSERT INTO `casbin_rule` (`p_type`, `v0`, `v1`, `v2`, `v3`, `v4`, `v5`) VALUES ('p', 'role', '/v1/role/create/', 'POST', NULL, NULL, NULL);
INSERT INTO `casbin_rule` (`p_type`, `v0`, `v1`, `v2`, `v3`, `v4`, `v5`) VALUES ('p', 'permission', '/v1/permission/create/', 'POST', NULL, NULL, NULL);
COMMIT;

-- ----------------------------
-- Table structure for permission_roles
-- ----------------------------
DROP TABLE IF EXISTS `permission_roles`;
CREATE TABLE `permission_roles` (
`id` bigint NOT NULL AUTO_INCREMENT,
`rid` bigint DEFAULT NULL,
`pid` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of permission_roles
-- ----------------------------
BEGIN;
INSERT INTO `permission_roles` (`id`, `rid`, `pid`) VALUES (6, 1, 1);
INSERT INTO `permission_roles` (`id`, `rid`, `pid`) VALUES (7, 2, 2);
INSERT INTO `permission_roles` (`id`, `rid`, `pid`) VALUES (8, 3, 3);
COMMIT;

-- ----------------------------
-- Table structure for permissions
-- ----------------------------
DROP TABLE IF EXISTS `permissions`;
CREATE TABLE `permissions` (
`id` bigint NOT NULL AUTO_INCREMENT,
`v1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`v2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of permissions
-- ----------------------------
BEGIN;
INSERT INTO `permissions` (`id`, `v1`, `v2`) VALUES (1, '/*', '*');
INSERT INTO `permissions` (`id`, `v1`, `v2`) VALUES (2, '/v1/role/create/', 'POST');
INSERT INTO `permissions` (`id`, `v1`, `v2`) VALUES (3, '/v1/permission/create/', 'POST');
COMMIT;

-- ----------------------------
-- Table structure for roles
-- ----------------------------
DROP TABLE IF EXISTS `roles`;
CREATE TABLE `roles` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` longtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of roles
-- ----------------------------
BEGIN;
INSERT INTO `roles` (`id`, `name`) VALUES (1, 'admin');
INSERT INTO `roles` (`id`, `name`) VALUES (2, 'role');
INSERT INTO `roles` (`id`, `name`) VALUES (3, 'permission');
INSERT INTO `roles` (`id`, `name`) VALUES (7, 'admin123');
COMMIT;

-- ----------------------------
-- Table structure for user_roles
-- ----------------------------
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (
`id` bigint NOT NULL AUTO_INCREMENT,
`rid` bigint DEFAULT NULL,
`uid` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of user_roles
-- ----------------------------
BEGIN;
INSERT INTO `user_roles` (`id`, `rid`, `uid`) VALUES (1, 1, 5);
INSERT INTO `user_roles` (`id`, `rid`, `uid`) VALUES (5, 2, 6);
INSERT INTO `user_roles` (`id`, `rid`, `uid`) VALUES (6, 3, 7);
COMMIT;

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of users
-- ----------------------------
BEGIN;
INSERT INTO `users` (`id`, `username`, `password`) VALUES (5, 'admin', '202cb962ac59075b964b07152d234b70');
INSERT INTO `users` (`id`, `username`, `password`) VALUES (6, 'role_user', '202cb962ac59075b964b07152d234b70');
INSERT INTO `users` (`id`, `username`, `password`) VALUES (7, 'permission_user', '202cb962ac59075b964b07152d234b70');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
39 changes: 39 additions & 0 deletions bizdemo/hertz_casbin/biz/mw/casbin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package mw

import (
"github.com/casbin/casbin"
xormadapter "github.com/casbin/xorm-adapter"
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/consts"
)

var AuthEnforcer *casbin.Enforcer

func InitCasbin() {
adapter := xormadapter.NewAdapter("mysql", consts.MysqlDSN, true)

enforcer := casbin.NewEnforcer("conf/auth_model.conf", adapter)

AuthEnforcer = enforcer
}

func Authorize(rvals ...interface{}) (result bool, err error) {
// casbin enforce
res, err1 := AuthEnforcer.EnforceSafe(rvals[0], rvals[1], rvals[2])
return res, err1
}
66 changes: 66 additions & 0 deletions bizdemo/hertz_casbin/biz/router/casbin/casbin.go
188 changes: 188 additions & 0 deletions bizdemo/hertz_casbin/biz/router/casbin/middleware.go
31 changes: 31 additions & 0 deletions bizdemo/hertz_casbin/biz/router/register.go
13 changes: 13 additions & 0 deletions bizdemo/hertz_casbin/conf/auth_model.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#request input
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

11 changes: 11 additions & 0 deletions bizdemo/hertz_casbin/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: '3'

services:
mysql:
image: 'mysql:latest'
ports:
- 9912:3306
environment:
- MYSQL_DATABASE=casbin
- MYSQL_ROOT_PASSWORD=casbin

44 changes: 44 additions & 0 deletions bizdemo/hertz_casbin/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin

go 1.19

replace github.com/apache/thrift => github.com/apache/thrift v0.13.0

require (
github.com/apache/thrift v0.12.0
github.com/casbin/casbin v1.9.1
github.com/casbin/xorm-adapter v1.0.0
github.com/cloudwego/hertz v0.5.1
github.com/golang-jwt/jwt/v4 v4.4.3
gorm.io/driver/mysql v1.4.5
gorm.io/gorm v1.24.3
)

require (
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/bytedance/go-tagexpr/v2 v2.9.2 // indirect
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 // indirect
github.com/bytedance/sonic v1.5.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect
github.com/cloudwego/netpoll v0.3.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/go-xorm/xorm v0.7.9 // indirect
github.com/golang/protobuf v1.5.0 // indirect
github.com/henrylee2cn/ameda v1.4.10 // indirect
github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/nyaruka/phonenumbers v1.0.55 // indirect
github.com/tidwall/gjson v1.13.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
google.golang.org/protobuf v1.27.1 // indirect
xorm.io/builder v0.3.6 // indirect
xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb // indirect
)
221 changes: 221 additions & 0 deletions bizdemo/hertz_casbin/go.sum

Large diffs are not rendered by default.

135 changes: 135 additions & 0 deletions bizdemo/hertz_casbin/idl/casbin.thrift
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@

namespace go casbin

enum Code {
Success = 1
ParamInvalid = 2
DBErr = 3
}



struct BasicResponse{
1: Code code
2: string msg
}



/***********Permission***************/
struct Permission {
1: i64 id
2: string v1
3: string v2
}

struct PermissionRole {
1: i64 id
2: i64 rid
3: i64 pid
}


struct CreatePermissionRequest{
1: string v1 (api.body="v1", api.form="v1",api.vd="(len($) > 0 && len($) < 100)")
2: string v2 (api.body="v2", api.form="v2",api.vd="(len($) > 0 && len($) < 100)")
}


struct CreatePermissionResponse{
1: Code code
2: string msg
3: Permission permission
}



struct BindPermissionRoleRequest{
1: string pid (api.body="pid", api.form="pid",api.vd="($ > 0 && $ < 100)")
2: string rid (api.body="rid", api.form="rid",api.vd="($ > 0 && $ < 100)")
}


struct BindPermissionRoleResponse{
1: Code code
2: string msg
3: PermissionRole permissionRole
}


service PermissionService {
CreatePermissionResponse CreatePermission(1:CreatePermissionRequest req)(api.post="/v1/permission/create/")
BindPermissionRoleResponse BindPermissionRole(1:BindPermissionRoleRequest req)(api.post="/v1/permissionrole/bind/")
}



/***********Role***************/
struct Role {
1: i64 id
2: string name
}

struct CreateRoleRequest{
1: string name (api.body="name", api.form="name",api.vd="(len($) > 0 && len($) < 100)")
}


struct CreateRoleResponse{
1: Code code
2: string msg
3: Role role
}


struct BindRoleRequest{
1: i64 uid (api.body="uid", api.form="uid",api.vd="($ > 0)")
2: i64 rid (api.body="rid", api.form="rid",api.vd="($ > 0)")
}

struct BindRoleResponse{
1: Code code
2: string msg
}




service RoleService {
CreateRoleResponse CreateRole(1:CreateRoleRequest req)(api.post="/v1/role/create/")
BindRoleResponse BindRole(1:BindRoleRequest req)(api.post="/v1/role/bind/")

}



/***********user***************/
struct User {
1: i64 id
2: string username
3: string password
}

struct UserRole {
1: i64 id
2: i64 rid
3: i64 uid
}



struct LoginRequest{
1: string username (api.body="username", api.form="username",api.vd="(len($) > 0 && len($) < 100)")
2: string password (api.body="password", api.form="password",api.vd="(len($) > 0 && len($) < 100)")
}

struct QueryUserResponse{
1: Code code
2: string msg
3: string token
}

service UserService {
QueryUserResponse Login(1: LoginRequest req)(api.post="/v1/login")
}

38 changes: 38 additions & 0 deletions bizdemo/hertz_casbin/main.go
41 changes: 41 additions & 0 deletions bizdemo/hertz_casbin/pkg/consts/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package consts

import (
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/model/casbin"
"github.com/golang-jwt/jwt/v4"
)

var (
MysqlDSN = "root:casbin@tcp(localhost:9912)/casbin?charset=utf8&parseTime=True&loc=Local"
EmqxKey = "1f9c5b734fe27865"
EmqxSecret = "lV9C2iefOp9Cr9BeiB5rr3N9CBolJjKk3HruhqEpHQxsuVD"
)

type M map[string]interface{}

type UserClaim struct {
Id uint `json:"id"`
Username string `json:"username"`
Roles []casbin.Role `json:"rids"`
jwt.RegisteredClaims
}

var (
JwtKey = "darren"
)
142 changes: 142 additions & 0 deletions bizdemo/hertz_casbin/pkg/utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package utils

import (
"bytes"
"crypto/md5"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"

"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/biz/model/casbin"
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/consts"
"github.com/golang-jwt/jwt/v4"
)

// MD5 use md5 to encrypt strings
func Md5(s string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}

func If(condition bool, trueValue, falseValue interface{}) interface{} {
if condition {
return trueValue
}
return falseValue
}

// generate token if username and password is correct
func GenerateToken(id uint, roles []casbin.Role, username string, second int) (string, error) {

uc := consts.UserClaim{
Id: id,
Username: username,
Roles: roles,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Second * time.Duration(second))),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, uc)
tokenString, err := token.SignedString([]byte(consts.JwtKey))
if err != nil {
return "", err
}

return tokenString, nil
}

// Verify the token
func AnalyzeToken(token string) (*consts.UserClaim, error) {
uc := new(consts.UserClaim)
claims, err := jwt.ParseWithClaims(token, uc, func(token *jwt.Token) (interface{}, error) {
return []byte(consts.JwtKey), nil
})

if err != nil {
return nil, err
}
if !claims.Valid {
return uc, errors.New("token is invalid")
}

return uc, err
}

// call httpRequest
func httpRequest(url, method string, data, header []byte) ([]byte, error) {
var err error
reader := bytes.NewBuffer(data)
request, err := http.NewRequest(method, url, reader)
if err != nil {
return nil, err
}
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
// 处理 header
if len(header) > 0 {
headerMap := new(map[string]interface{})
err = json.Unmarshal(header, headerMap)

if err != nil {
return nil, err
}
for k, v := range *headerMap {
if k == "" || v == "" {
continue
}
request.Header.Set(k, v.(string))
}
}
request.SetBasicAuth(consts.EmqxKey, consts.EmqxSecret)

client := http.Client{}
resp, err := client.Do(request)
if err != nil {
return nil, err
}
defer resp.Body.Close()

respBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

return respBytes, nil
}

// Request in "delete" mode
func HttpDelete(url string, data []byte, header ...byte) ([]byte, error) {
return httpRequest(url, "DELETE", data, header)
}

// Request in "put" mode
func HttpPut(url string, data []byte, header ...byte) ([]byte, error) {
return httpRequest(url, "PUT", data, header)
}

// Request in "post" mode
func HttpPost(url string, data []byte, header ...byte) ([]byte, error) {
return httpRequest(url, "POST", data, header)
}

// Request in "get" mode
func HttpGet(url string, header ...byte) ([]byte, error) {
return httpRequest(url, "GET", []byte{}, header)
}
31 changes: 31 additions & 0 deletions bizdemo/hertz_casbin/router.go
32 changes: 32 additions & 0 deletions bizdemo/hertz_casbin/router_gen.go
32 changes: 32 additions & 0 deletions bizdemo/hertz_casbin/test/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package test

const userServiceAddr = "http://127.0.0.1:8888"

var m1 = map[string]string{
"token": "",
}

var rolem1 = map[string]string{
"token": "",
}

var permissionm1 = map[string]string{
"token": "",
}
var header []byte
60 changes: 60 additions & 0 deletions bizdemo/hertz_casbin/test/permission_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package test

import (
"encoding/json"
"fmt"
"testing"

"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/consts"
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/utils"
)

// Test add permission
func TestPermissionAdd(t *testing.T) {

header, _ = json.Marshal(rolem1)
m := consts.M{
"v1": "/v1/permission/create/",
"v2": "POST",
}

data, _ := json.Marshal(m)
rep, err := utils.HttpPost(userServiceAddr+"/v1/permission/create", data, header...)
if err != nil {
t.Fatal(err)
}

fmt.Println(string(rep))
}

// Test bind permission
func TestPermissionBind(t *testing.T) {
m := consts.M{
"pid": "1",
"rid": "1",
}

data, _ := json.Marshal(m)
rep, err := utils.HttpPost(userServiceAddr+"/v1/permissionrole/bind/", data, header...)
if err != nil {
t.Fatal(err)
}

fmt.Println(string(rep))
}
44 changes: 44 additions & 0 deletions bizdemo/hertz_casbin/test/role_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package test

import (
"encoding/json"
"fmt"
"testing"

"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/consts"
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/utils"
)

// Test add role
func TestRoleAdd(t *testing.T) {

header, _ = json.Marshal(rolem1)

m := consts.M{
"name": "admin",
}

data, _ := json.Marshal(m)
rep, err := utils.HttpPost(userServiceAddr+"/v1/role/create", data, header...)
if err != nil {
t.Fatal(err)
}

fmt.Println(string(rep))
}
74 changes: 74 additions & 0 deletions bizdemo/hertz_casbin/test/user_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package test

import (
"encoding/json"
"fmt"
"testing"

"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/consts"
"github.com/cloudwego/hertz-examples/bizdemo/hertz_casbin/pkg/utils"
)

// Test the login of the admin user to get the token
func TestUserLogin(t *testing.T) {
m := consts.M{
"username": "admin",
"password": "123",
}

data, _ := json.Marshal(m)
rep, err := utils.HttpPost(userServiceAddr+"/v1/login", data)
if err != nil {
t.Fatal(err)
}

fmt.Println(string(rep))
}

// Test the login of the role user to get the token
func TestRoleUserLogin(t *testing.T) {
m := consts.M{
"username": "role_user",
"password": "123",
}

data, _ := json.Marshal(m)
rep, err := utils.HttpPost(userServiceAddr+"/v1/login", data)
if err != nil {
t.Fatal(err)
}

fmt.Println(string(rep))
}

// Test the login of the permission user to get the token
func TestPermissionUserLogin(t *testing.T) {
m := consts.M{
"username": "permission_user",
"password": "123",
}

data, _ := json.Marshal(m)
rep, err := utils.HttpPost(userServiceAddr+"/v1/login", data)
if err != nil {
t.Fatal(err)
}

fmt.Println(string(rep))
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ require (
github.com/alibaba/sentinel-golang v1.0.4
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1764 // indirect
github.com/apache/thrift v0.13.0
github.com/choleraehyq/pid v0.0.16 // indirect
github.com/cloudwego/hertz v0.4.2
github.com/cloudwego/kitex v0.3.1
github.com/go-errors/errors v1.4.2 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -107,6 +107,8 @@ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F
github.com/choleraehyq/pid v0.0.12/go.mod h1:uhzeFgxJZWQsZulelVQZwdASxQ9TIPZYL4TPkQMtL/U=
github.com/choleraehyq/pid v0.0.13 h1:Tc/jYjHC50SDCxSX+DWHfMmFqtwGR8EiQ08qJ/EK8zs=
github.com/choleraehyq/pid v0.0.13/go.mod h1:uhzeFgxJZWQsZulelVQZwdASxQ9TIPZYL4TPkQMtL/U=
github.com/choleraehyq/pid v0.0.16 h1:1/714sMH9IBlE/aK6xM0acTagGKSzpiR0bDt7l0cG7o=
github.com/choleraehyq/pid v0.0.16/go.mod h1:uhzeFgxJZWQsZulelVQZwdASxQ9TIPZYL4TPkQMtL/U=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=