fleet/server/service/translator.go
Victor Lyuboslavsky 3d2171d2d9
Moved common endpointer packages to platform dir. (#37780)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #37192

- Move /server/service/middleware/endpoint_utils to
/server/platform/endpointer
- Move /server/service/middleware/authzcheck to
/server/platform/middleware/authzcheck
- Move /server/service/middleware/ratelimit to
/server/platform/middleware/ratelimit

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Refactor**
* Reorganized internal endpoint utilities to a centralized platform
location for improved code organization and maintainability. No
functional changes to existing features or APIs.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-06 14:23:07 -06:00

123 lines
3.5 KiB
Go

package service
import (
"context"
"fmt"
"github.com/fleetdm/fleet/v4/server/authz"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/platform/endpointer"
)
type translatorRequest struct {
List []fleet.TranslatePayload `json:"list"`
}
type translatorResponse struct {
List []fleet.TranslatePayload `json:"list"`
Err error `json:"error,omitempty"`
}
func (r translatorResponse) Error() error { return r.Err }
func translatorEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) {
req := request.(*translatorRequest)
resp, err := svc.Translate(ctx, req.List)
if err != nil {
return translatorResponse{Err: err}, nil
}
return translatorResponse{List: resp}, nil
}
type translateFunc func(ctx context.Context, ds fleet.Datastore, identifier string) (uint, error)
func translateEmailToUserID(ctx context.Context, ds fleet.Datastore, identifier string) (uint, error) {
user, err := ds.UserByEmail(ctx, identifier)
if err != nil {
return 0, err
}
return user.ID, nil
}
func translateLabelToID(ctx context.Context, ds fleet.Datastore, identifier string) (uint, error) {
labelIDs, err := ds.LabelIDsByName(ctx, []string{identifier}, fleet.TeamFilter{User: authz.UserFromContext(ctx)})
if err != nil {
return 0, err
}
return labelIDs[identifier], nil
}
func translateTeamToID(ctx context.Context, ds fleet.Datastore, identifier string) (uint, error) {
team, err := ds.TeamByName(ctx, identifier)
if err != nil {
return 0, err
}
return team.ID, nil
}
func translateHostToID(ctx context.Context, ds fleet.Datastore, identifier string) (uint, error) {
host, err := ds.HostByIdentifier(ctx, identifier)
if err != nil {
return 0, err
}
return host.ID, nil
}
func (svc *Service) Translate(ctx context.Context, payloads []fleet.TranslatePayload) ([]fleet.TranslatePayload, error) {
if len(payloads) == 0 {
// skip auth since there is no case in which this request will make sense with no payloads
svc.authz.SkipAuthorization(ctx)
return nil, badRequest("payloads must not be empty")
}
var finalPayload []fleet.TranslatePayload
for _, payload := range payloads {
var translateFunc translateFunc
switch payload.Type {
case fleet.TranslatorTypeUserEmail:
if err := svc.authz.Authorize(ctx, &fleet.User{}, fleet.ActionRead); err != nil {
return nil, err
}
translateFunc = translateEmailToUserID
case fleet.TranslatorTypeLabel:
if err := svc.authz.Authorize(ctx, &fleet.Label{}, fleet.ActionRead); err != nil {
return nil, err
}
translateFunc = translateLabelToID
case fleet.TranslatorTypeTeam:
if err := svc.authz.Authorize(ctx, &fleet.Team{}, fleet.ActionRead); err != nil {
return nil, err
}
translateFunc = translateTeamToID
case fleet.TranslatorTypeHost:
if err := svc.authz.Authorize(ctx, &fleet.Host{}, fleet.ActionRead); err != nil {
return nil, err
}
translateFunc = translateHostToID
default:
// if no supported payload type, this is bad regardless of authorization
svc.authz.SkipAuthorization(ctx)
return nil, endpointer.BadRequestErr(
fmt.Sprintf("Type %s is unknown. ", payload.Type),
fleet.NewErrorf(
fleet.ErrNoUnknownTranslate,
"Type %s is unknown.",
payload.Type),
)
}
id, err := translateFunc(ctx, svc.ds, payload.Payload.Identifier)
if err != nil {
return nil, err
}
payload.Payload.ID = id
finalPayload = append(finalPayload, fleet.TranslatePayload{
Type: payload.Type,
Payload: payload.Payload,
})
}
return finalPayload, nil
}