init
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user