2026-04-09 10:01:23 +08:00
|
|
|
package services
|
|
|
|
|
|
|
|
|
|
import (
|
2026-08-21 00:41:07 +08:00
|
|
|
"code.tczkiot.com/wlw/ai-agent/identity"
|
|
|
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/constants"
|
|
|
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/dto"
|
|
|
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
|
|
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/errorsx"
|
2026-04-09 10:01:23 +08:00
|
|
|
|
2026-05-23 22:10:20 +08:00
|
|
|
"github.com/gin-gonic/gin"
|
2026-04-09 10:01:23 +08:00
|
|
|
)
|
|
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
const authPrincipalContextKey = "externalAuthPrincipal"
|
2026-04-09 10:01:23 +08:00
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
// AuthService adapts identity data authenticated by the host application and
|
|
|
|
|
// delegates every operation authorization back to that host.
|
|
|
|
|
var AuthService = &externalPrincipalService{}
|
2026-04-09 10:01:23 +08:00
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
type externalPrincipalService struct{}
|
2026-04-09 10:01:23 +08:00
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
func (s *externalPrincipalService) GetAuthPrincipal(ctx *gin.Context) *dto.AuthPrincipal {
|
2026-04-09 10:01:23 +08:00
|
|
|
if ctx == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2026-08-21 00:41:07 +08:00
|
|
|
value, _ := ctx.Get(authPrincipalContextKey)
|
|
|
|
|
principal, _ := value.(*dto.AuthPrincipal)
|
2026-04-09 10:01:23 +08:00
|
|
|
return principal
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
func (s *externalPrincipalService) Authenticate(ctx *gin.Context) (*dto.AuthPrincipal, error) {
|
2026-04-09 10:01:23 +08:00
|
|
|
if principal := s.GetAuthPrincipal(ctx); principal != nil {
|
|
|
|
|
return principal, nil
|
|
|
|
|
}
|
2026-08-21 00:41:07 +08:00
|
|
|
if ctx == nil || ctx.Request == nil {
|
2026-06-02 20:51:13 +08:00
|
|
|
return nil, errorsx.UnauthorizedI18n("error.auth.expired")
|
2026-04-09 10:01:23 +08:00
|
|
|
}
|
|
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
subject, err := SubjectService.Current(ctx.Request.Context())
|
2026-08-28 22:23:13 +08:00
|
|
|
if err != nil || subject == nil || subject.Type != identity.SubjectAdmin ||
|
|
|
|
|
subject.Category != identity.CategorySystem || !subject.Enabled {
|
2026-08-21 00:41:07 +08:00
|
|
|
return nil, errorsx.UnauthorizedI18n("error.auth.expired")
|
2026-04-09 10:01:23 +08:00
|
|
|
}
|
|
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
principal := &dto.AuthPrincipal{
|
|
|
|
|
SubjectType: subject.Type,
|
|
|
|
|
UserID: subject.ID,
|
|
|
|
|
Username: subject.Username,
|
|
|
|
|
Nickname: subject.Name,
|
|
|
|
|
Avatar: subject.Avatar,
|
|
|
|
|
Status: enums.StatusOk,
|
|
|
|
|
Roles: []string{string(subject.Type)},
|
2026-04-09 10:01:23 +08:00
|
|
|
}
|
2026-08-21 00:41:07 +08:00
|
|
|
ctx.Set(authPrincipalContextKey, principal)
|
2026-04-09 10:01:23 +08:00
|
|
|
return principal, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
func (s *externalPrincipalService) RequirePermission(ctx *gin.Context, permission constants.Permission) (*dto.AuthPrincipal, error) {
|
2026-04-09 10:01:23 +08:00
|
|
|
principal, err := s.Authenticate(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2026-08-21 00:41:07 +08:00
|
|
|
if err := SubjectService.Authorize(ctx.Request.Context(), permission.Code); err != nil {
|
|
|
|
|
return nil, errorsx.ForbiddenI18n("error.auth.forbidden")
|
2026-04-09 10:01:23 +08:00
|
|
|
}
|
2026-08-21 00:41:07 +08:00
|
|
|
return principal, nil
|
2026-04-09 10:01:23 +08:00
|
|
|
}
|
|
|
|
|
|
2026-08-21 00:41:07 +08:00
|
|
|
func (s *externalPrincipalService) HasPermission(ctx *gin.Context, operation string) bool {
|
|
|
|
|
if _, err := s.Authenticate(ctx); err != nil {
|
2026-04-30 17:48:58 +08:00
|
|
|
return false
|
2026-04-30 17:42:24 +08:00
|
|
|
}
|
2026-08-21 00:41:07 +08:00
|
|
|
return SubjectService.Authorize(ctx.Request.Context(), operation) == nil
|
2026-04-09 10:01:23 +08:00
|
|
|
}
|