设计一个系统,提供不同的资源访问权限给免费用户和 VIP 用户,这里将分别介绍下整体设计思路和数据库设计,并用 GORM 的方式说明。
整体设计思路
- 用户注册和登录模块。
- 资源模块,可以是文件、视频、API 调用等。
- 订阅模块,有免费和 VIP 两种订阅。
- 权限控制模块,根据用户订阅类型控制资源访问权限。
数据库设计
我们需要设计几个主要的数据表:
- users 表(用户表)
- subscriptions 表(订阅表)
- resources 表(资源表)
- user_resources 表(用户资源表,用于跟踪免费用户使用资源)
users 表
1
2
3
4
5
6
7
|
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
subscription_id INT REFERENCES subscriptions(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
|
subscriptions 表
1
2
3
4
5
|
CREATE TABLE subscriptions (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL, -- 'free' 或者 'vip'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
|
resources 表
1
2
3
4
5
6
|
CREATE TABLE resources (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
resource_type VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
|
user_resources 表
1
2
3
4
5
6
|
CREATE TABLE user_resources (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
resource_id INT REFERENCES resources(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
|
GORM 实现
下面是如何使用 GORM 来实现这些表结构的定义,并编写相关的权限控制逻辑。
首先,定义模型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package main
import (
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primaryKey"`
Username string
Password string
SubscriptionID uint
Subscription Subscription
CreatedAt time.Time
}
type Subscription struct {
ID uint `gorm:"primaryKey"`
Name string
CreatedAt time.Time
}
type Resource struct {
ID uint `gorm:"primaryKey"`
Name string
ResourceType string
CreatedAt time.Time
}
type UserResource struct {
ID uint `gorm:"primaryKey"`
UserID uint
ResourceID uint
CreatedAt time.Time
}
|
初始化数据库连接并迁移表结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
func main() {
dsn := "host=localhost user=gorm dbname=gorm password=gorm sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自动迁移表结构
db.AutoMigrate(&User{}, &Subscription{}, &Resource{}, &UserResource{})
// 添加示例数据
freeSub := Subscription{Name: "free"}
vipSub := Subscription{Name: "vip"}
db.Create(&freeSub)
db.Create(&vipSub)
user := User{Username: "test_user", Password: "password", SubscriptionID: freeSub.ID}
db.Create(&user)
resource := Resource{Name: "sample_resource", ResourceType: "file"}
db.Create(&resource)
}
|
权限控制逻辑示例(伪代码):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
func CanAccessResource(user User, resource Resource) bool {
var userResource UserResource
db.First(&userResource, "user_id = ? AND resource_id = ?", user.ID, resource.ID)
if user.Subscription.Name == "vip" {
return true
} else if user.Subscription.Name == "free" && userResource.ID == 0 {
// 免费用户且未使用过该资源
newUserResource := UserResource{UserID: user.ID, ResourceID: resource.ID}
db.Create(&newUserResource)
return true
}
return false // 免费用户已经使用过该资源
}
|
此逻辑假设当免费用户第一次访问某个资源时,会在 user_resources
表中记录此访问。免费用户只能访问一次,VIP 用户则可以无限访问。