fleet/server/fleet/software_title_icons.go
Martin Angers ba04887100
Backend: Support labels_include_all for installers/apps (#41324)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40721 

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects

## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [ ] QA'd all new/changed functionality manually

I (Martin) did test `labels_include_all` for FMA, custom installer, IPA
and VPP apps, and it seemed to all work great for gitops apply and
gitops generate, **except for VPP apps** which seem to have 2 important
pre-existing bugs, see
https://github.com/fleetdm/fleet/issues/40723#issuecomment-4041780707

## New Fleet configuration settings

- [ ] Verified that the setting is exported via `fleetctl
generate-gitops`
- [ ] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [ ] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [ ] Verified that any relevant UI is disabled when GitOps mode is
enabled

---------

Co-authored-by: Jahziel Villasana-Espinoza <jahziel@fleetdm.com>
2026-03-18 13:27:53 -04:00

71 lines
2.9 KiB
Go

package fleet
import (
"context"
"fmt"
"io"
"regexp"
"time"
)
var SoftwareTitleIconURLRegex = regexp.MustCompile(`fleet/software/titles/\d+/icon\?team_id=\d+`)
const SoftwareTitleIconSignedURLExpiry = 6 * time.Hour
type UploadSoftwareTitleIconPayload struct {
TitleID uint
TeamID uint
Filename string
StorageID string
IconFile *TempFileReader
}
type SoftwareTitleIcon struct {
// TeamID is the team (or no team if 0) the icon is associated with. Note that
// it MUST have the JSON tag to serialize as `team_id` so that the rego policies
// can properly check team ownership (rego marshals the struct to JSON to pass it to
// the rego policies script). This struct is never marshalled directly to JSON in
// API responses at this time so it doesn't affect anything else.
TeamID uint `db:"team_id" json:"team_id"` // TODO -- rename to `fleet_id` when authz code switches to using `fleet_id` instead of `team_id`
SoftwareTitleID uint `db:"software_title_id"`
StorageID string `db:"storage_id"`
Filename string `db:"filename"`
}
func (s *SoftwareTitleIcon) AuthzType() string {
return "installable_entity"
}
func (s *SoftwareTitleIcon) IconUrl() string {
return fmt.Sprintf("/api/latest/fleet/software/titles/%d/icon?team_id=%d", s.SoftwareTitleID, s.TeamID)
}
func (s *SoftwareTitleIcon) IconUrlWithDeviceToken(deviceToken string) string {
return fmt.Sprintf("/api/latest/fleet/device/%s/software/titles/%d/icon", deviceToken, s.SoftwareTitleID)
}
type SoftwareTitleIconStore interface {
Put(ctx context.Context, iconID string, content io.ReadSeeker) error
Get(ctx context.Context, iconID string) (io.ReadCloser, int64, error)
Exists(ctx context.Context, iconID string) (bool, error)
Cleanup(ctx context.Context, usedIconIDs []string, removeCreatedBefore time.Time) (int, error)
Sign(ctx context.Context, iconID string, expiresIn time.Duration) (string, error)
}
type DetailsForSoftwareIconActivity struct {
SoftwareInstallerID *uint `db:"software_installer_id"`
InHouseAppID *uint `db:"in_house_app_id"`
AdamID *string `db:"adam_id"`
VPPAppTeamID *uint `db:"vpp_app_team_id"`
VPPIconUrl *string `db:"vpp_icon_url"`
SoftwareTitle string `db:"software_title"`
Filename *string `db:"filename"`
TeamName *string `db:"team_name"`
TeamID uint `db:"team_id"`
SelfService bool `db:"self_service"`
SoftwareTitleID uint `db:"software_title_id"`
Platform *InstallableDevicePlatform `json:"platform"`
LabelsIncludeAny []ActivitySoftwareLabel `db:"-"`
LabelsExcludeAny []ActivitySoftwareLabel `db:"-"`
LabelsIncludeAll []ActivitySoftwareLabel `db:"-"`
}