112 lines
2.8 KiB
Go
112 lines
2.8 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"sync"
|
|
|
|
"code.tczkiot.com/wlw/ai-agent/identity"
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/enums"
|
|
"code.tczkiot.com/wlw/ai-agent/internal/pkg/openidentity"
|
|
)
|
|
|
|
var SubjectService = &subjectService{}
|
|
|
|
type subjectService struct {
|
|
mu sync.RWMutex
|
|
query identity.QuerySubjectsFunc
|
|
authorize identity.AuthorizeFunc
|
|
}
|
|
|
|
func SetQuerySubjects(query identity.QuerySubjectsFunc) {
|
|
SubjectService.mu.Lock()
|
|
defer SubjectService.mu.Unlock()
|
|
SubjectService.query = query
|
|
}
|
|
|
|
func SetAuthorize(authorize identity.AuthorizeFunc) {
|
|
SubjectService.mu.Lock()
|
|
defer SubjectService.mu.Unlock()
|
|
SubjectService.authorize = authorize
|
|
}
|
|
|
|
func (s *subjectService) Authorize(ctx context.Context, operation string) error {
|
|
s.mu.RLock()
|
|
fn := s.authorize
|
|
s.mu.RUnlock()
|
|
if fn == nil {
|
|
return errors.New("ai-agent: Authorize is not initialized")
|
|
}
|
|
return fn(ctx, operation)
|
|
}
|
|
|
|
func (s *subjectService) Query(ctx context.Context, query identity.Query) ([]identity.Subject, error) {
|
|
s.mu.RLock()
|
|
fn := s.query
|
|
s.mu.RUnlock()
|
|
if fn == nil {
|
|
return nil, errors.New("ai-agent: QuerySubjects is not initialized")
|
|
}
|
|
return fn(ctx, query)
|
|
}
|
|
|
|
func (s *subjectService) Current(ctx context.Context) (*identity.Subject, error) {
|
|
items, err := s.Query(ctx, identity.Query{Current: true, EnabledOnly: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(items) == 0 {
|
|
return nil, errors.New("ai-agent: current subject not found")
|
|
}
|
|
return &items[0], nil
|
|
}
|
|
|
|
func (s *subjectService) CurrentExternal(ctx context.Context) (*openidentity.ExternalUser, error) {
|
|
subject, err := s.Current(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if subject.Category != identity.CategoryUser || !subject.Enabled {
|
|
return nil, errors.New("ai-agent: current subject is not a customer identity")
|
|
}
|
|
return &openidentity.ExternalUser{
|
|
ExternalSource: enums.ExternalSourceUser,
|
|
ExternalID: fmt.Sprintf("%s:%d", subject.Type, subject.ID),
|
|
ExternalName: subject.Name,
|
|
}, nil
|
|
}
|
|
|
|
func (s *subjectService) Get(id int64) *identity.Subject {
|
|
items, err := s.Query(context.Background(), identity.Query{
|
|
Types: []identity.SubjectType{identity.SubjectAgent},
|
|
IDs: []int64{id},
|
|
EnabledOnly: true,
|
|
})
|
|
if err != nil {
|
|
slog.Warn("query external subject failed", "id", id, "error", err)
|
|
return nil
|
|
}
|
|
if len(items) == 0 {
|
|
return nil
|
|
}
|
|
return &items[0]
|
|
}
|
|
|
|
func (s *subjectService) FindByIDs(ids []int64) []identity.Subject {
|
|
if len(ids) == 0 {
|
|
return nil
|
|
}
|
|
items, err := s.Query(context.Background(), identity.Query{
|
|
Types: []identity.SubjectType{identity.SubjectAgent},
|
|
IDs: ids,
|
|
EnabledOnly: true,
|
|
})
|
|
if err != nil {
|
|
slog.Warn("query external subjects failed", "error", err)
|
|
return nil
|
|
}
|
|
return items
|
|
}
|