init: 提交 files 服务初始代码

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zxr
2026-08-03 23:51:21 +08:00
commit d29693343b
33 changed files with 2067 additions and 0 deletions

46
internal/auth/actor.go Normal file
View File

@@ -0,0 +1,46 @@
package auth
import (
"git.apinb.com/bsm-sdk/core/middleware"
"github.com/gin-gonic/gin"
)
const (
ActorTypeUser = "user"
ActorTypeService = "service"
actorContextKey = "files.auth.actor"
)
type Actor struct {
Type string
ID uint
Identity string
}
func FromContext(ctx *gin.Context) (Actor, bool) {
if actor, ok := ctx.Get(actorContextKey); ok {
serviceActor, ok := actor.(Actor)
if ok && serviceActor.Type == ActorTypeService && serviceActor.ID == 0 && serviceActor.Identity != "" {
return serviceActor, true
}
}
claims, err := middleware.ParseAuth(ctx)
if err != nil || claims == nil || claims.ID == 0 || claims.Identity == "" {
return Actor{}, false
}
return Actor{
Type: ActorTypeUser,
ID: claims.ID,
Identity: claims.Identity,
}, true
}
func withActor(ctx *gin.Context, actor Actor) {
if actor.Type != ActorTypeService || actor.ID != 0 || actor.Identity == "" {
return
}
ctx.Set(actorContextKey, actor)
}

31
internal/auth/service.go Normal file
View File

@@ -0,0 +1,31 @@
package auth
import (
"crypto/subtle"
"log"
"net/http"
"strings"
"git.apinb.com/ops/files/internal/config"
"github.com/gin-gonic/gin"
)
func ServiceAuth() gin.HandlerFunc {
return func(ctx *gin.Context) {
serviceName := strings.TrimSpace(ctx.GetHeader("Service-Name"))
secretKey := strings.TrimSpace(ctx.GetHeader("Secret-Key"))
serviceSecret, exists := config.Spec.ServiceClients[serviceName]
if serviceName == "" || secretKey == "" || !exists || strings.TrimSpace(serviceSecret) == "" || subtle.ConstantTimeCompare([]byte(serviceSecret), []byte(secretKey)) != 1 {
log.Printf("服务鉴权失败: service=%q", serviceName)
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
ctx.Abort()
return
}
withActor(ctx, Actor{
Type: ActorTypeService,
Identity: serviceName,
})
ctx.Next()
}
}