Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
7cce1d2
feat(): 1、新增log模块
Zany2 Nov 17, 2025
e58e35b
feat(): 1、新增顶人下线部分方法实现 2、删除冗余代码
Zany2 Nov 19, 2025
9f7af46
feat(): 1、新增stputil方法
Zany2 Nov 19, 2025
32af60b
Merge branch 'daixk' into daixk_log
Zany2 Nov 19, 2025
5cd0d40
feat(): 1、去掉多余调试打印
Zany2 Nov 19, 2025
0fadeef
feat(): 1、去掉多余调试打印
Zany2 Nov 20, 2025
1575551
feat(): 1、修改权限角色Set方法逻辑新增去重逻辑
Zany2 Nov 20, 2025
45e4067
feat(): 1、新增删除角色与权限的方法
Zany2 Nov 20, 2025
dca7d6a
Merge branch 'daixk' into daixk_log
Zany2 Nov 20, 2025
02a275a
feat(): 1、添加日志和序列化(待测试)
Zany2 Nov 25, 2025
b8a9f4d
feat(): 1、添加日志和序列化
Zany2 Nov 28, 2025
83e7150
feat(): 1、添加日志和序列化
Zany2 Dec 3, 2025
6193acf
Merge remote-tracking branch 'upstream/main' into daixk_log
Zany2 Dec 4, 2025
7dfdcc5
feat(): 1、更新代码逻辑
Zany2 Dec 7, 2025
c094e08
feat(): 1、更新代码逻辑
Zany2 Dec 8, 2025
21265e2
feat(): 1、更新代码逻辑
Zany2 Dec 9, 2025
5f02958
feat(): 1、更新与session相关方法参数
Zany2 Dec 9, 2025
d483318
feat(): 1、修改部分代码
Zany2 Dec 16, 2025
8b2f2b6
feat(): 1、完成manager核心逻辑修改
Zany2 Dec 16, 2025
76dce05
feat(): 1、完成manager核心逻辑修改
Zany2 Dec 17, 2025
0034458
feat(): 1、完善stputil相关方法逻辑
Zany2 Dec 18, 2025
f0c632b
feat(): 1、完善gf独立包
Zany2 Dec 22, 2025
4fa5d8e
feat(): 1、提取独立包
Zany2 Dec 23, 2025
af54c0d
feat(): 1、修改gf和gin的独立依赖
Zany2 Dec 24, 2025
ce8ede8
feat(): 1、更新manager方法参数 2、提取部分统一err
Zany2 Dec 25, 2025
5834d87
feat(): 1、更新manager方法参数 2、提取部分统一err
Zany2 Dec 25, 2025
4f5840f
feat(): 1、更新manager方法参数 2、提取部分统一err
Zany2 Dec 25, 2025
6f02815
feat(): 1、完善manager以及gf
Zany2 Dec 26, 2025
eee6339
feat(): 1、完善gin
Zany2 Dec 26, 2025
c65fbbc
feat(): 1、完善slog
Zany2 Dec 26, 2025
1080b03
feat(): 1、完善pool以及sgenerator
Zany2 Dec 26, 2025
aa44204
feat(): 1、完善oauth2模块方法
Zany2 Dec 27, 2025
2bbd92e
feat(): 1、完善gf与gin
Zany2 Dec 27, 2025
263eed3
feat(): 1、完善gf与gin
Zany2 Dec 28, 2025
e665db0
feat(): 1、优化示例代码
Zany2 Dec 28, 2025
013a522
feat(): 1、优化示例代码
Zany2 Dec 29, 2025
d5ecd60
feat(): 1、优化config检测以及框架适配
Zany2 Dec 31, 2025
046b2bb
feat(): 1、优化config检测以及框架适配
Zany2 Dec 31, 2025
c19c0ad
feat(): 1、修改0.1.7版本 2、修改examples
Zany2 Jan 4, 2026
c4bba8e
feat(): 1、完善部分逻辑
Zany2 Jan 5, 2026
196d215
feat(): 1、完善部分逻辑
Zany2 Jan 6, 2026
07178ca
feat(): 1、完善quick-start逻辑
Zany2 Jan 6, 2026
42d656e
feat(): 1、新增gf包创建GoFrame日志适配器方法 2、新增gf包基于路径的权限校验中间件
Zany2 Jan 6, 2026
0eba7af
fix(): 1、修改gf包中中间件CheckLoginWithState方法
Zany2 Jan 6, 2026
b2872ee
feat(): 1、更新
Zany2 Jan 7, 2026
224e3ed
feat(): 1、修改构建manager中日志与续期池的初始化逻辑
Zany2 Jan 8, 2026
e4d12bb
feat(): 1、更新gf以及gin包中的ctx
Zany2 Jan 9, 2026
c12dc50
feat(): 1、完善gf包中间件以及示例
Zany2 Jan 9, 2026
3c81920
feat(): 1、完善gf包中间件以及示例
Zany2 Jan 9, 2026
f654142
feat(): 1、完善stputil方法 2、创建go-zero适配包
Zany2 Jan 9, 2026
72b18e1
feat(): 1、修改manager的Islogin方法 2、修改stputil统一方法 3、添加config提示信息 4、添加buil…
Zany2 Jan 11, 2026
ec35f2a
feat(): 1、修改manager续期方法 2、添加存储的测试方法
Zany2 Jan 11, 2026
d99af38
feat(): 1、修改manager续期方法 2、添加存储的测试方法
Zany2 Jan 12, 2026
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
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func init() {

```go
func main() {
// Use StpUtil directly without passing manager
// Use StpUtil directly without passing manager-example
token, _ := stputil.Login(1000)
println("Login successful, Token:", token)

Expand Down Expand Up @@ -183,13 +183,13 @@ hasAny := stputil.HasPermissionsOr(1000, []string{"admin", "super"}) /

```go
// Set roles
stputil.SetRoles(1000, []string{"admin", "manager"})
stputil.SetRoles(1000, []string{"admin", "manager-example"})

// Check role
hasRole := stputil.HasRole(1000, "admin")

// Check multiple roles
hasAll := stputil.HasRolesAnd(1000, []string{"admin", "manager"})
hasAll := stputil.HasRolesAnd(1000, []string{"admin", "manager-example"})
hasAny := stputil.HasRolesOr(1000, []string{"admin", "super"})
```

Expand Down Expand Up @@ -266,7 +266,7 @@ func main() {
r.GET("/public", sagin.Ignore(), publicHandler) // Public access
r.GET("/user", sagin.CheckLogin(), userHandler) // Login required
r.GET("/admin", sagin.CheckPermission("admin:*"), adminHandler) // Permission required
r.GET("/manager", sagin.CheckRole("manager"), managerHandler) // Role required
r.GET("/manager-example", sagin.CheckRole("manager-example"), managerHandler) // Role required
r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler) // Check if disabled

r.Run(":8080")
Expand Down Expand Up @@ -308,7 +308,7 @@ func main() {
userOrAdminHandler)

// Admin role required
r.GET("/manager", sagin.CheckRole("admin"), managerHandler)
r.GET("/manager-example", sagin.CheckRole("admin"), managerHandler)

// Check if account is disabled
r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler)
Expand Down Expand Up @@ -349,7 +349,7 @@ func main() {
s.BindHandler("GET:/public", sagf.Ignore(), publicHandler) // Public access
s.BindHandler("GET:/user", sagf.CheckLogin(), userHandler) // Login required
s.BindHandler("GET:/admin", sagf.CheckPermission("admin:*"), adminHandler) // Permission required
s.BindHandler("GET:/manager", sagf.CheckRole("manager"), managerHandler) // Role required
s.BindHandler("GET:/manager-example", sagf.CheckRole("manager-example"), managerHandler) // Role required
s.BindHandler("GET:/sensitive", sagf.CheckDisable(), sensitiveHandler) // Check if disabled

s.SetPort(8080)
Expand Down Expand Up @@ -506,7 +506,7 @@ manager.RegisterFunc(core.EventAll, func(data *core.EventData) {
// Access advanced controls via the underlying EventManager
manager.GetEventManager().SetPanicHandler(customPanicHandler)

// Use the manager globally
// Use the manager-example globally
stputil.SetManager(manager)
```

Expand Down
10 changes: 5 additions & 5 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ hasAny := stputil.HasPermissionsOr(1000, []string{"admin", "super"}) /

```go
// 设置角色
stputil.SetRoles(1000, []string{"admin", "manager"})
stputil.SetRoles(1000, []string{"admin", "manager-example"})

// 检查角色
hasRole := stputil.HasRole(1000, "admin")

// 多角色检查
hasAll := stputil.HasRolesAnd(1000, []string{"admin", "manager"})
hasAll := stputil.HasRolesAnd(1000, []string{"admin", "manager-example"})
hasAny := stputil.HasRolesOr(1000, []string{"admin", "super"})
```

Expand Down Expand Up @@ -266,7 +266,7 @@ func main() {
r.GET("/public", sagin.Ignore(), publicHandler) // 公开访问
r.GET("/user", sagin.CheckLogin(), userHandler) // 需要登录
r.GET("/admin", sagin.CheckPermission("admin:*"), adminHandler) // 需要权限
r.GET("/manager", sagin.CheckRole("manager"), managerHandler) // 需要角色
r.GET("/manager-example", sagin.CheckRole("manager-example"), managerHandler) // 需要角色
r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler) // 检查封禁

r.Run(":8080")
Expand Down Expand Up @@ -308,7 +308,7 @@ func main() {
userOrAdminHandler)

// 需要管理员角色
r.GET("/manager", sagin.CheckRole("admin"), managerHandler)
r.GET("/manager-example", sagin.CheckRole("admin"), managerHandler)

// 检查账号是否被封禁
r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler)
Expand Down Expand Up @@ -349,7 +349,7 @@ func main() {
s.BindHandler("GET:/public", sagf.Ignore(), publicHandler) // 公开访问
s.BindHandler("GET:/user", sagf.CheckLogin(), userHandler) // 需要登录
s.BindHandler("GET:/admin", sagf.CheckPermission("admin:*"), adminHandler) // 需要权限
s.BindHandler("GET:/manager", sagf.CheckRole("manager"), managerHandler) // 需要角色
s.BindHandler("GET:/manager-example", sagf.CheckRole("manager-example"), managerHandler) // 需要角色
s.BindHandler("GET:/sensitive", sagf.CheckDisable(), sensitiveHandler) // 检查是否禁用

s.SetPort(8080)
Expand Down
22 changes: 22 additions & 0 deletions codec/json/codec_adaper_json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @Author daixk 2025/11/27 20:57:00
package json

import (
"encoding/json"
)

type JSONSerializer struct{}

func (s *JSONSerializer) Encode(v any) ([]byte, error) {
return json.Marshal(v)
}

func (s *JSONSerializer) Decode(data []byte, v any) error {
return json.Unmarshal(data, v)
}

func (s *JSONSerializer) Name() string { return "json" }

func NewJSONSerializer() *JSONSerializer {
return &JSONSerializer{}
}
3 changes: 3 additions & 0 deletions codec/json/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/click33/sa-token-go/codec/json

go 1.25.0
22 changes: 22 additions & 0 deletions codec/msgpack/codec_adaper_msgpack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @Author daixk 2025/11/27 20:58:00
package msgpack

import (
"github.com/vmihailenco/msgpack/v5"
)

type MsgPackSerializer struct{}

func (s *MsgPackSerializer) Encode(v any) ([]byte, error) {
return msgpack.Marshal(v)
}

func (s *MsgPackSerializer) Decode(data []byte, v any) error {
return msgpack.Unmarshal(data, v)
}

func (s *MsgPackSerializer) Name() string { return "msgpack" }

func NewMsgPackSerializer() *MsgPackSerializer {
return &MsgPackSerializer{}
}
12 changes: 12 additions & 0 deletions codec/msgpack/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/click33/sa-token-go/codec/msgpack

go 1.25.0

require github.com/vmihailenco/msgpack/v5 v5.4.1

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
)
6 changes: 6 additions & 0 deletions codec/msgpack/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
9 changes: 9 additions & 0 deletions core/adapter/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @Author daixk 2025/12/12 10:46:00
package adapter

// Codec defines serialization behavior abstraction | 序列化行为抽象接口
type Codec interface {
Encode(v any) ([]byte, error) // Encode value to byte slice | 将对象编码为字节数组
Decode(data []byte, v any) error // Decode byte slice to target value | 将字节数组解码到目标对象
Name() string // Return codec implementation name | 返回序列化器名称
}
44 changes: 44 additions & 0 deletions core/adapter/generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// @Author daixk 2025/12/5 15:52:00
package adapter

// TokenStyle Token generation style | Token生成风格
type TokenStyle string

const (
// TokenStyleUUID UUID style | UUID风格
TokenStyleUUID TokenStyle = "uuid"
// TokenStyleSimple Simple random string | 简单随机字符串
TokenStyleSimple TokenStyle = "simple"
// TokenStyleRandom32 32-bit random string | 32位随机字符串
TokenStyleRandom32 TokenStyle = "random32"
// TokenStyleRandom64 64-bit random string | 64位随机字符串
TokenStyleRandom64 TokenStyle = "random64"
// TokenStyleRandom128 128-bit random string | 128位随机字符串
TokenStyleRandom128 TokenStyle = "random128"
// TokenStyleJWT JWT style | JWT风格
TokenStyleJWT TokenStyle = "jwt"
// TokenStyleHash SHA256 hash-based style | SHA256哈希风格
TokenStyleHash TokenStyle = "hash"
// TokenStyleTimestamp Timestamp-based style | 时间戳风格
TokenStyleTimestamp TokenStyle = "timestamp"
// TokenStyleTik Short ID style (like TikTok) | Tik风格短ID(类似抖音)
TokenStyleTik TokenStyle = "tik"
)

// IsValid checks if the TokenStyle is valid | 检查TokenStyle是否有效
func (ts TokenStyle) IsValid() bool {
switch ts {
case TokenStyleUUID, TokenStyleSimple, TokenStyleRandom32,
TokenStyleRandom64, TokenStyleRandom128, TokenStyleJWT,
TokenStyleHash, TokenStyleTimestamp, TokenStyleTik:
return true
default:
return false
}
}

// Generator token generation interface | Token生成接口
type Generator interface {
// Generate generates token based on implementation | 生成Token(由实现决定具体规则)
Generate(loginID, device string) (string, error)
}
64 changes: 64 additions & 0 deletions core/adapter/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// @Author daixk 2025/12/12 10:45:00
package adapter

// LogLevel defines log severity level | 日志级别定义
type LogLevel int

const (
LogLevelDebug LogLevel = iota + 1 // Debug level | 调试级别
LogLevelInfo // Info level | 信息级别
LogLevelWarn // Warn level | 警告级别
LogLevelError // Error level | 错误级别(最高)
)

// String returns the string representation of log level | 返回日志级别的字符串表示
func (l LogLevel) String() string {
switch l {
case LogLevelDebug:
return "DEBUG"
case LogLevelInfo:
return "INFO"
case LogLevelWarn:
return "WARN"
case LogLevelError:
return "ERROR"
default:
return "UNKNOWN"
}
}

// Log defines logging behavior abstraction | 日志行为抽象接口
type Log interface {
Print(v ...any) // Print log without level | 无级别日志输出
Printf(format string, v ...any) // Print formatted log without level | 无级别格式化日志输出

Debug(v ...any) // Print debug level log | 输出调试级别日志
Debugf(format string, v ...any) // Print formatted debug level log | 输出调试级别格式化日志

Info(v ...any) // Print info level log | 输出信息级别日志
Infof(format string, v ...any) // Print formatted info level log | 输出信息级别格式化日志

Warn(v ...any) // Print warn level log | 输出警告级别日志
Warnf(format string, v ...any) // Print formatted warn level log | 输出警告级别格式化日志

Error(v ...any) // Print error level log | 输出错误级别日志
Errorf(format string, v ...any) // Print formatted error level log | 输出错误级别格式化日志
}

// LogControl defines runtime control methods for loggers | 日志运行时控制接口
type LogControl interface {
Log

// ---- Lifecycle | 生命周期 ----
Close() // Close the logger and release resources | 关闭日志并释放资源
Flush() // Flush buffered logs to output | 刷新缓冲区

// ---- Runtime Config | 运行时配置 ----
SetLevel(level LogLevel) // Update minimum log level | 动态更新日志级别
SetPrefix(prefix string) // Update log prefix | 动态更新日志前缀
SetStdout(enable bool) // Enable/disable stdout output | 开关控制台输出

// ---- Status Query | 状态查询 ----
LogPath() string // Get log directory path | 获取日志目录
DropCount() uint64 // Get dropped log count (queue full) | 获取丢弃的日志数量
}
8 changes: 8 additions & 0 deletions core/adapter/pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @Author daixk 2025/12/12 11:56:00
package adapter

type Pool interface {
Submit(task func()) error
Stop()
Stats() (running, capacity int, usage float64)
}
28 changes: 17 additions & 11 deletions core/adapter/storage.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
package adapter

import "time"
import (
"context"
"time"
)

// Storage defines storage interface for Token and Session data | 定义存储接口,用于存储Token和Session数据
type Storage interface {
// ============== Basic Operations | 基本操作 ==============

// Set sets key-value pair with optional expiration time (0 means never expire) | 设置键值对,可选过期时间(0表示永不过期)
Set(key string, value any, expiration time.Duration) error
Set(ctx context.Context, key string, value any, expiration time.Duration) error

// SetKeepTTL sets key-value pair but keeps the original TTL unchanged | 设置键值但保持原有TTL不变
SetKeepTTL(key string, value any) error
SetKeepTTL(ctx context.Context, key string, value any) error

// Get gets value by key, returns nil if key doesn't exist | 获取键对应的值,键不存在时返回nil
Get(key string) (any, error)
Get(ctx context.Context, key string) (any, error)

// GetAndDelete atomically gets the value and deletes the key | 原子获取并删除键
GetAndDelete(ctx context.Context, key string) (any, error)

// Delete deletes one or more keys | 删除一个或多个键
Delete(keys ...string) error
Delete(ctx context.Context, keys ...string) error

// Exists checks if key exists | 检查键是否存在
Exists(key string) bool
Exists(ctx context.Context, key string) bool

// ============== Key Management | 键管理 ==============

// Keys gets all keys matching pattern (e.g., "user:*") | 获取匹配模式的所有键(如:"user:*")
Keys(pattern string) ([]string, error)
Keys(ctx context.Context, pattern string) ([]string, error)

// Expire sets expiration time for key | 设置键的过期时间
Expire(key string, expiration time.Duration) error
Expire(ctx context.Context, key string, expiration time.Duration) error

// TTL gets remaining time to live (-1 if no expiration, -2 if key doesn't exist) | 获取键的剩余生存时间(-1表示永不过期,-2表示键不存在)
TTL(key string) (time.Duration, error)
TTL(ctx context.Context, key string) (time.Duration, error)

// ============== Utility Methods | 工具方法 ==============

// Clear clears all data (use with caution, mainly for testing) | 清空所有数据(谨慎使用,主要用于测试)
Clear() error
Clear(ctx context.Context) error

// Ping checks if storage is accessible | 检查存储是否可访问
Ping() error
Ping(ctx context.Context) error
}
Loading