Files
server/app/console/commands/create_token.go
T
2026-01-16 15:49:34 +08:00

188 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package commands
import (
"errors"
"strconv"
"strings"
"time"
"github.com/goravel/framework/contracts/console"
"github.com/goravel/framework/contracts/console/command"
"github.com/goravel/framework/facades"
"goravel/app/models"
"goravel/app/services"
"goravel/app/utils"
)
// # Admin用户 - 1小时后过期
// go run . artisan token:create 1 --expires=1h
// # 7天后过期
// go run . artisan token:create 1 --expires=7d
// # 使用简写
// go run . artisan token:create 1 -e=1h
// # 指定token名称
// go run . artisan token:create 1 --expires=7d --name=api-token
// # 创建永久token(不设置expires
// go run . artisan token:create 1
type CreateToken struct {
}
// Signature The name and signature of the console command.
func (receiver *CreateToken) Signature() string {
return "token:create"
}
// Description The console command description.
func (receiver *CreateToken) Description() string {
return "为指定管理员创建token(永久或指定过期时间)"
}
// Extend The console command extend.
func (receiver *CreateToken) Extend() command.Extend {
return command.Extend{
Category: "token",
Flags: []command.Flag{
&command.StringFlag{
Name: "expires",
Aliases: []string{"e"},
Usage: "过期时间,格式:1h(1小时)、24h(24小时)、7d(7天)等,不设置则创建永久token",
},
&command.StringFlag{
Name: "name",
Aliases: []string{"n"},
Value: "console-token",
Usage: "token名称",
},
},
}
}
// Handle Execute the console command.
func (receiver *CreateToken) Handle(ctx console.Context) error {
// 获取用户标识(ID或用户名)
userIdentifier := ctx.Argument(0)
if userIdentifier == "" {
return errors.New("请提供用户ID或用户名")
}
// 用户类型固定为 admin
userType := "admin"
// 获取过期时间选项
expiresStr := ctx.Option("expires")
var expiresAt *time.Time
if expiresStr != "" {
// 解析过期时间
duration, err := parseDuration(expiresStr)
if err != nil {
return errors.New("过期时间格式错误,请使用:1h(1小时)、24h(24小时)、7d(7天)等格式")
}
exp := time.Now().Add(duration)
expiresAt = &exp
}
// 如果 expiresStr 为空,expiresAt 为 nil,表示永久token
// 获取token名称
tokenName := ctx.Option("name")
if tokenName == "" {
tokenName = "console-token"
}
// 查询管理员
var admin models.Admin
var err error
// 尝试作为ID解析
if id, parseErr := strconv.ParseUint(userIdentifier, 10, 32); parseErr == nil {
// 作为ID查询
err = facades.Orm().Query().Where("id", uint(id)).First(&admin)
} else {
// 作为用户名查询
err = facades.Orm().Query().Where("username", userIdentifier).First(&admin)
}
if err != nil {
return errors.New("管理员不存在")
}
userID := admin.ID
username := admin.Username
// 创建token
tokenService := services.NewTokenServiceImpl()
// 命令行创建token时,浏览器、IP、操作系统信息为空
plainToken, accessToken, err := tokenService.CreateToken(userType, userID, tokenName, expiresAt, "", "", "", "")
if err != nil {
return errors.New("创建token失败: " + err.Error())
}
// 输出结果
ctx.Info("Token创建成功!")
ctx.Line("")
ctx.Info("用户信息:")
ctx.Line(" 类型: " + userType)
ctx.Line(" ID: " + strconv.FormatUint(uint64(userID), 10))
ctx.Line(" 用户名: " + username)
ctx.Line("")
ctx.Info("Token信息:")
ctx.Line(" 名称: " + accessToken.Name)
if accessToken.ExpiresAt != nil {
ctx.Line(" 过期时间: " + accessToken.ExpiresAt.Format(utils.DateTimeFormat))
} else {
ctx.Line(" 过期时间: 永久有效")
}
ctx.Line(" 创建时间: " + accessToken.CreatedAt.Format(utils.DateTimeFormat))
ctx.Line("")
ctx.Warning("请妥善保管以下token,它只会显示一次:")
ctx.Line("")
ctx.Line(plainToken)
ctx.Line("")
return nil
}
// parseDuration 解析时间字符串,支持 h(小时)、d(天)、m(分钟)等格式
func parseDuration(s string) (time.Duration, error) {
// 移除空格
s = strings.TrimSpace(s)
if len(s) == 0 {
return 0, errors.New("时间字符串为空")
}
// 获取最后一个字符作为单位
unit := s[len(s)-1:]
valueStr := s[:len(s)-1]
// 解析数值
value, err := strconv.ParseFloat(valueStr, 64)
if err != nil {
return 0, err
}
// 根据单位转换为duration
switch unit {
case "m", "M":
// 分钟
return time.Duration(value) * time.Minute, nil
case "h", "H":
// 小时
return time.Duration(value) * time.Hour, nil
case "d", "D":
// 天
return time.Duration(value) * 24 * time.Hour, nil
case "w", "W":
// 周
return time.Duration(value) * 7 * 24 * time.Hour, nil
default:
// 尝试直接解析为duration(如 "1h30m"
return time.ParseDuration(s)
}
}