zero-ppanel/apps/api/internal/logic/auth/deviceLoginLogic.go
shanshanzhong 3b4429bdd9
All checks were successful
Build docker and publish / prepare (20.15.1) (push) Successful in 11s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.admin image_name:ppanel-admin name:admin]) (push) Successful in 4m32s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.api image_name:ppanel-api name:api]) (push) Successful in 8m6s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.node image_name:ppanel-node name:node]) (push) Successful in 4m26s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.queue image_name:ppanel-queue name:queue]) (push) Successful in 3m55s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.rpc-core image_name:ppanel-rpc-core name:rpc-core]) (push) Successful in 8m23s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.scheduler image_name:ppanel-scheduler name:scheduler]) (push) Successful in 4m1s
Build docker and publish / deploy (push) Successful in 45s
Build docker and publish / notify (push) Successful in 3s
feat: 新增设备登录功能,包括API接口、RPC服务、逻辑处理和相关数据类型及错误码。
2026-03-01 18:51:12 -08:00

88 lines
2.2 KiB
Go

// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2
package auth
import (
"context"
"fmt"
"time"
"github.com/google/uuid"
"github.com/zero-ppanel/zero-ppanel/apps/api/internal/svc"
"github.com/zero-ppanel/zero-ppanel/apps/api/internal/types"
"github.com/zero-ppanel/zero-ppanel/apps/rpc/core/core"
"github.com/zero-ppanel/zero-ppanel/pkg/jwtx"
"github.com/zero-ppanel/zero-ppanel/pkg/xerr"
"github.com/zeromicro/go-zero/core/logx"
)
type DeviceLoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 设备登录
func NewDeviceLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeviceLoginLogic {
return &DeviceLoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *DeviceLoginLogic) DeviceLogin(req *types.DeviceLoginReq) (resp *types.LoginResp, err error) {
// 1. 调用 Core RPC 设备登录
rpcResp, err := l.svcCtx.CoreRpc.DeviceLogin(l.ctx, &core.DeviceLoginReq{
Identifier: req.Identifier,
UserAgent: req.UserAgent,
Ip: req.IP,
ShortCode: req.ShortCode,
})
if err != nil {
return nil, err
}
// 2. 检查用户是否禁用
if rpcResp.IsDisabled {
return nil, xerr.NewErrCode(xerr.UserDisabled)
}
// 3. 生成 session ID
sessionId := uuid.New().String()
// 4. 生成 JWT Token
token, err := jwtx.GenerateToken(
l.svcCtx.Config.JwtAuth.AccessSecret,
rpcResp.UserId,
"device",
rpcResp.IsAdmin,
l.svcCtx.Config.JwtAuth.AccessExpire,
)
if err != nil {
l.Errorf("GenerateToken error: %v", err)
return nil, xerr.NewErrCode(xerr.ServerError)
}
// 5. 写入 Redis session
expireDuration := time.Duration(l.svcCtx.Config.JwtAuth.AccessExpire) * time.Second
// session:{sessionId} → userId
sessionKey := fmt.Sprintf("session:%s", sessionId)
if err := l.svcCtx.Redis.SetexCtx(l.ctx, sessionKey, fmt.Sprintf("%d", rpcResp.UserId), int(expireDuration.Seconds())); err != nil {
l.Errorf("Redis set session error: %v", err)
}
// device:{identifier} → sessionId
deviceKey := fmt.Sprintf("device:%s", req.Identifier)
if err := l.svcCtx.Redis.SetexCtx(l.ctx, deviceKey, sessionId, int(expireDuration.Seconds())); err != nil {
l.Errorf("Redis set device session error: %v", err)
}
return &types.LoginResp{
Token: token,
}, nil
}