授权服务端API

xjg c99a7b65fd v1.0.0-beta.6 2 months ago
.idea 792e56b44b v1.0.0-beta.6 2 months ago
config 792e56b44b v1.0.0-beta.6 2 months ago
domain 792e56b44b v1.0.0-beta.6 2 months ago
handler 792e56b44b v1.0.0-beta.6 2 months ago
k8s 792e56b44b v1.0.0-beta.6 2 months ago
key 792e56b44b v1.0.0-beta.6 2 months ago
proto c99a7b65fd v1.0.0-beta.6 2 months ago
test 792e56b44b v1.0.0-beta.6 2 months ago
utils 792e56b44b v1.0.0-beta.6 2 months ago
.drone.yml 792e56b44b v1.0.0-beta.6 2 months ago
.gitignore 792e56b44b v1.0.0-beta.6 2 months ago
Dockerfile 792e56b44b v1.0.0-beta.6 2 months ago
Makefile 792e56b44b v1.0.0-beta.6 2 months ago
README.md 792e56b44b v1.0.0-beta.6 2 months ago
go.mod 792e56b44b v1.0.0-beta.6 2 months ago
go.sum 792e56b44b v1.0.0-beta.6 2 months ago
install.sh 6b17d812bc v1.0.0-beta.3 3 months ago
main.go 792e56b44b v1.0.0-beta.6 2 months ago

README.md

type NodePermission struct {
  NodeID       int64 `gorm:"primaryKey;autoIncrement:false"`
  PermissionID int64 `gorm:"primaryKey;autoIncrement:false"`
}

在上述示例中,我们使用 primaryKey 标签将 NodeID 和 PermissionID 设置为联合主键,并且通过 autoIncrement:false 来禁止自增。这样,NodePermission 表就能够记录节点和权限的关联关系,而不需要额外的独立的 ID。 // 在关联表中添加联合主键约束 db.AutoMigrate(&NodePermission{})

# 假设要删除 RoleID 为 1 且 PermissionID 为 2 的记录
result := db.Where("role_id = ? AND permission_id = ?", 1, 2).Delete(&RolePermission{})
if result.Error != nil {
    // 处理错误
} else {
    // 处理成功
}

Clauses

Clauses 是 Gorm 中用于添加查询子句(Clauses)的方法。在这个上下文中,Clauses(clause.OnConflict{UpdateAll: true}) 是为了使用 Gorm 的 Upsert(插入或更新)功能。 具体来说,clause.OnConflict{UpdateAll: true} 表示当发生冲突(即主键或唯一索引冲突)时,使用更新所有字段的方式进行更新。这意味着如果数据库中已经存在具有相同主键或唯一索引的记录,那么会更新已存在记录的所有字段,而不是报错或忽略。 在示例中,Create(&defaultUser) 会尝试向数据库插入一条记录,如果该记录已经存在(主键冲突),则会根据 clause.OnConflict{UpdateAll: true} 中定义的规则进行更新。这样可以保证在执行初始化操作时,如果默认用户已经存在,就更新用户信息而不是报错。 总体来说,Clauses 允许您在 Gorm 中添加灵活的查询子句,而这里特别使用了 Upsert 功能。

package main

import (
	"fmt"
	"time"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// 数据模型定义

type User struct {
	ID        int64  `gorm:"primary_key;not_null;auto_increment" json:"id"`
	Username  string `json:"username"`
	Nickname  string `json:"nickname"`
	Email     string `json:"email"`
	Phone     string `json:"phone"` // 新增手机号字段
	Password  string `json:"-"`     // 这里使用 "-" 表示在 JSON 输出时不包含密码字段
	Teams     []Team `gorm:"many2many:user_teams;" json:"teams"`
	Roles     []Role `gorm:"many2many:user_roles;" json:"roles"`
	CreatedBy int64  `json:"created_by"`
}

type Role struct {
	ID   int64  `gorm:"primary_key;not_null;auto_increment" json:"id"`
	Name string `json:"name"`
}

type Node struct {
	ID       int64  `gorm:"primary_key;not_null;auto_increment" json:"id"`
	ParentID int64  `json:"parent_id"` // 父节点ID,根节点为0
	Name     string `json:"name"`      // 节点名称
}

type Permission struct {
	ID   int64  `gorm:"primary_key;not_null;auto_increment" json:"id"`
	Name string `json:"name"`
}

type Team struct {
	ID          int64        `gorm:"primary_key;not_null;auto_increment" json:"id"`
	Name        string       `json:"name"`        // 团队名称
	Description string       `json:"description"` // 团队描述
	LeaderID    int64        `json:"leader_id"`   // 团队领导的用户 ID
	CreatedBy   string       `json:"created_by"`  // 创建团队的用户
	CreateTime  int64        `json:"create_time"` // 团队创建时间
	Leader      User         `gorm:"foreignkey:LeaderID" json:"leader"`
	Members     []User       `gorm:"many2many:user_teams;" json:"members"`
	Roles       []Role       `gorm:"many2many:team_roles;" json:"roles"`
	Permissions []Permission `gorm:"many2many:team_permissions;" json:"permissions"`
	Website     string       `json:"website"`     // 团队网站
	MaxMembers  int          `json:"max_members"` // 团队最大成员数
}

// 关联表

type UserTeam struct {
	UserID int64 `gorm:"index"`
	TeamID int64 `gorm:"index"`
}

type UserRole struct {
	UserID int64 `gorm:"index"`
	RoleID int64 `gorm:"index"`
}

type NodePermission struct {
	NodeID       int64 `gorm:"index"`
	PermissionID int64 `gorm:"index"`
}

type TeamPermission struct {
	TeamID       int64 `gorm:"index"`
	PermissionID int64 `gorm:"index"`
}

// 权限常量

const (
	// 用户权限
	UserRead   = "user:read"
	UserWrite  = "user:write"
	UserDelete = "user:delete"

	// 团队权限
	TeamRead   = "team:read"
	TeamWrite  = "team:write"
	TeamDelete = "team:delete"

	// 角色权限
	RoleRead   = "role:read"
	RoleWrite  = "role:write"
	RoleDelete = "role:delete"

	// 通用权限
	ManageAll = "*:manage"
	ViewAll   = "*:view"

	// 节点权限
	NodeRead   = "node:read"
	NodeWrite  = "node:write"
	NodeDelete = "node:delete"
)

// 数据填充函数

func seedData(db *gorm.DB) {
	// 创建用户、角色、节点、权限、团队
	user1 := User{Username: "user1", Nickname: "User 1", Email: "user1@example.com", Phone: "123456789", CreatedBy: 1}
	user2 := User{Username: "user2", Nickname: "User 2", Email: "user2@example.com", Phone: "987654321", CreatedBy: 1}
	user3 := User{Username: "user3", Nickname: "User 3", Email: "user3@example.com", Phone: "111222333", CreatedBy: 2}

	role1 := Role{Name: "Admin"}
	role2 := Role{Name: "Member"}

	node1 := Node{Name: "Node 1"}
	node2 := Node{Name: "Node 2"}
	node3 := Node{Name: "Node 3"}

	permission1 := Permission{Name: "Permission 1"}
	permission2 := Permission{Name: "Permission 2"}
	permission3 := Permission{Name: "Permission 3"}

	team1 := Team{Name: "Team 1", Description: "Description 1", LeaderID: 1, CreatedBy: "Admin", CreateTime: 1637190745}
	team2 := Team{Name: "Team 2", Description: "Description 2", LeaderID: 2, CreatedBy: "Admin", CreateTime: 1637190745}
	team3 := Team{Name: "Team 3", Description: "Description 3", LeaderID: 3, CreatedBy: "User2", CreateTime: 1637190745}

	// 创建关联关系
	db.Create(&user1)
	db.Create(&user2)
	db.Create(&user3)

	db.Create(&role1)
	db.Create(&role2)

	db.Create(&node1)
	db.Create(&node2)
	db.Create(&node3)

	db.Create(&permission1)
	db.Create(&permission2)
	db.Create(&permission3)

	db.Create(&team1)
	db.Create(&team2)
	db.Create(&team3)

	db.Create(&UserTeam{UserID: user1.ID, TeamID: team1.ID})
	db.Create(&UserTeam{UserID: user2.ID, TeamID: team2.ID})
	db.Create(&UserTeam{UserID: user3.ID, TeamID: team3.ID})

	db.Create(&UserRole{UserID: user1.ID, RoleID: role1.ID})
	db.Create(&UserRole{UserID: user2.ID, RoleID: role2.ID})
	db.Create(&UserRole{UserID: user3.ID, RoleID: role2.ID})

	db.Create(&NodePermission{NodeID: node1.ID, PermissionID: permission1.ID})
	db.Create(&NodePermission{NodeID: node2.ID, PermissionID: permission2.ID})
	db.Create(&NodePermission{NodeID: node3.ID, PermissionID: permission3.ID})

	db.Create(&TeamPermission{TeamID: team1.ID, PermissionID: permission1.ID})
	db.Create(&TeamPermission{TeamID: team2.ID, PermissionID: permission2.ID})
	db.Create(&TeamPermission{TeamID: team3.ID, PermissionID: permission3.ID})
}

func main() {
	// 连接数据库
	dsn := "test.db"
	db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	// 自动迁移模型
	err = db.AutoMigrate(&User{}, &Role{}, &Node{}, &Permission{}, &Team{}, &UserTeam{}, &UserRole{}, &NodePermission{}, &TeamPermission{})
	if err != nil {
		panic("failed to migrate database")
	}

	// 数据填充
	seedData(db)

	fmt.Println("Database seeded successfully.")
}

下面是关于 Permission, Role, 和 RolePermission 的基本流程:

# Permission 模型
type Permission struct {
    ID          int64       `gorm:"primary_key;not_null;auto_increment" json:"id"`
    Name        string      `json:"name"`
    Description string      `json:"description"`
    Roles       []Role      `gorm:"many2many:role_permissions;" json:"roles"`
    CreatedAt   time.Time   `json:"created_at"`
    UpdatedAt   time.Time   `json:"updated_at"`
}

# Role 模型
type Role struct {
    ID          int64        `gorm:"primary_key;not_null;auto_increment" json:"id"`
    Name        string       `json:"name"`
    Description string       `json:"description"`
    Permissions []Permission `gorm:"many2many:role_permissions;" json:"permissions"`
    CreatedAt   time.Time    `json:"created_at"`
    UpdatedAt   time.Time    `json:"updated_at"`
}

# RolePermission 模型
type RolePermission struct {
    RoleID       int64 `gorm:"index"`
    PermissionID int64 `gorm:"index"`
    Grant        bool  `json:"grant"` // 表示角色是否被授予相应的权限
}

关联模型:

Permission 和 Role 通过 many2many 关联表 RolePermission 关联。 RolePermission 中有 Grant 字段,表示角色是否被授予相应的权限。

创建和查询流程:

# 创建权限
permission := Permission{
    Name:        "ReadUser",
    Description: "Permission to read user information",
}
db.Create(&permission)

# 创建角色
role := Role{
    Name:        "Admin",
    Description: "Administrator role",
}
db.Create(&role)

# 关联权限和角色
rolePermission := RolePermission{
    RoleID:       role.ID,
    PermissionID: permission.ID,
    Grant:        true, // 授予角色相应权限
}
db.Create(&rolePermission)

# 查询角色的所有权限
db.Preload("Permissions").Find(&role)

# 查询权限的所有角色
db.Preload("Roles").Find(&permission)

更新和删除流程:

# 更新权限信息
db.Model(&permission).Update("Description", "Updated description")

# 更新角色信息
db.Model(&role).Update("Description", "Updated description")

# 撤销角色的权限
db.Where("RoleID = ? AND PermissionID = ?", role.ID, permission.ID).Delete(&RolePermission{})

# 删除权限
db.Delete(&permission)

# 删除角色
db.Delete(&role)

这个流程展示了如何创建、关联、查询、更新和删除 Permission, Role, 和 RolePermission 的基本操作。请根据你的具体需求和系统设计进行调整。

在 GORM 中,如果你的 Team 模型有一个名为 Members 的字段,表示与 User 模型之间的多对多关系,你可以使用以下方式来向团队添加成员。 通过关联模型创建:

// 假设 teamID 为团队的 ID,userID 为要添加的用户的 ID

// 首先查询要添加的用户和团队
var team Team
var user User

if err := db.First(&team, teamID).Error; err != nil {
    // 处理团队不存在的情况
}

if err := db.First(&user, userID).Error; err != nil {
    // 处理用户不存在的情况
}

// 将用户添加到团队的 Members 中
db.Model(&team).Association("Members").Append(&user)

上述代码首先通过团队 ID 和用户 ID 查询相应的团队和用户,然后使用 Association 和 Append 方法将用户添加到团队的 Members 中。

直接更新模型字段:

// 假设 teamID 为团队的 ID,userID 为要添加的用户的 ID

// 查询要添加的用户和团队
var team Team
var user User

if err := db.First(&team, teamID).Error; err != nil {
    // 处理团队不存在的情况
}

if err := db.First(&user, userID).Error; err != nil {
    // 处理用户不存在的情况
}

// 直接将用户添加到团队的 Members 中
db.Model(&team).Update("Members", gorm.Expr("ARRAY_APPEND(members, ?)", userID))

这种方法通过直接更新模型字段来添加用户到团队的 Members 中,使用了 ARRAY_APPEND 函数。 你可以根据你的具体需求选择其中的一种方法。如果你使用的是 PostgreSQL,ARRAY_APPEND 函数是合适的。确保替换代码中的数据库查询和错误处理,以适应你的应用程序逻辑。

team 下有多少角色:

// 假设 teamID 为团队的 ID

var team Team

if err := db.Preload("Roles").First(&team, teamID).Error; err != nil {
    // 处理团队不存在的情况
}

// 现在你可以访问 team.Roles,这是一个包含团队下所有角色的切片

team 下有多少用户:

// 假设 teamID 为团队的 ID

var team Team

if err := db.Preload("Members").First(&team, teamID).Error; err != nil {
// 处理团队不存在的情况
}

// 现在你可以访问 team.Members,这是一个包含团队下所有用户的切片

如果在创建角色时,关联的权限已经存在,您可以首先查询权限,然后再关联到角色。以下是一个示例:

// 假设您已经有一个名为 "Admin" 的权限存在,并且知道它的 PermissionID

// 查询权限
var adminPermission Permission
db.Where("name = ?", "Admin").First(&adminPermission)

// 创建角色并关联权限
adminRole := Role{
Name:        "Admin",
Description: "Administrator role",
Permissions: []Permission{adminPermission},
}

db.Create(&adminRole)
// 获取以 "Employee:" 前缀开头的权限
var employeePermissions []Permission
db.Where("name LIKE ?", "Employee:%").Find(&employeePermissions)

Mysql 设置字符集

ALTER DATABASE paas CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

SHOW VARIABLES LIKE 'character_set_database';