diff --git a/ee/server/service/software_installers.go b/ee/server/service/software_installers.go index 23afcc9c6f2a..380dc14eab99 100644 --- a/ee/server/service/software_installers.go +++ b/ee/server/service/software_installers.go @@ -22,7 +22,6 @@ import ( "github.com/fleetdm/fleet/v4/server/contexts/viewer" "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/mdm/apple/vpp" - "github.com/fleetdm/fleet/v4/server/ptr" "github.com/go-kit/log" kitlog "github.com/go-kit/log" "github.com/go-kit/log/level" @@ -217,16 +216,17 @@ func (svc *Service) UpdateSoftwareInstaller(ctx context.Context, payload *fleet. dirty["SelfService"] = true } - actLabelsIncl, actLabelsExcl := activitySoftwareLabelsFromSoftwareScopeLabels( - existingInstaller.LabelsIncludeAny, existingInstaller.LabelsExcludeAny) + // activity team ID must be null if no team, not zero + var actTeamID *uint + if payload.TeamID != nil && *payload.TeamID != 0 { + actTeamID = payload.TeamID + } activity := fleet.ActivityTypeEditedSoftware{ - SoftwareTitle: existingInstaller.SoftwareTitle, - TeamName: teamName, - TeamID: payload.TeamID, - SelfService: existingInstaller.SelfService, - SoftwarePackage: &existingInstaller.Name, - LabelsIncludeAny: actLabelsIncl, - LabelsExcludeAny: actLabelsExcl, + SoftwareTitle: existingInstaller.SoftwareTitle, + TeamName: teamName, + TeamID: actTeamID, + SelfService: existingInstaller.SelfService, + SoftwarePackage: &existingInstaller.Name, } var payloadForNewInstallerFile *fleet.UploadSoftwareInstallerPayload @@ -367,6 +367,15 @@ func (svc *Service) UpdateSoftwareInstaller(ctx context.Context, payload *fleet. } } + // now that the payload has been updated with any patches, we can set the + // final fields of the activity + actLabelsIncl, actLabelsExcl := activitySoftwareLabelsFromSoftwareScopeLabels( + existingInstaller.LabelsIncludeAny, existingInstaller.LabelsExcludeAny) + activity.LabelsIncludeAny = actLabelsIncl + activity.LabelsExcludeAny = actLabelsExcl + if payload.SelfService != nil { + activity.SelfService = *payload.SelfService + } if err := svc.NewActivity(ctx, vc.User, activity); err != nil { return nil, ctxerr.Wrap(ctx, err, "creating activity for edited software") } @@ -465,20 +474,12 @@ func (svc *Service) deleteSoftwareInstaller(ctx context.Context, meta *fleet.Sof teamName = &t.Name } - var teamID *uint - switch { - case meta.TeamID == nil: - teamID = ptr.Uint(0) - case meta.TeamID != nil: - teamID = meta.TeamID - } - actLabelsIncl, actLabelsExcl := activitySoftwareLabelsFromSoftwareScopeLabels(meta.LabelsIncludeAny, meta.LabelsExcludeAny) if err := svc.NewActivity(ctx, vc.User, fleet.ActivityTypeDeletedSoftware{ SoftwareTitle: meta.SoftwareTitle, SoftwarePackage: meta.Name, TeamName: teamName, - TeamID: teamID, + TeamID: meta.TeamID, SelfService: meta.SelfService, LabelsIncludeAny: actLabelsIncl, LabelsExcludeAny: actLabelsExcl, diff --git a/server/service/integration_enterprise_test.go b/server/service/integration_enterprise_test.go index 881fc9b28355..4a097f15abdf 100644 --- a/server/service/integration_enterprise_test.go +++ b/server/service/integration_enterprise_test.go @@ -10699,12 +10699,24 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD _, titleID := checkSoftwareInstaller(t, payload) // check activity - activityData := fmt.Sprintf(`{"software_title": "ruby", "software_package": "ruby.deb", "team_name": null, "team_id": null, "self_service": false, "software_title_id": %d}`, titleID) - s.lastActivityOfTypeMatches(fleet.ActivityTypeAddedSoftware{}.ActivityName(), activityData, 0) + activityData := fmt.Sprintf(`{"software_title": "ruby", "software_package": "ruby.deb", "team_name": null, + "team_id": null, "self_service": false, "software_title_id": %d, "labels_include_any": [{"id": %d, "name": %q}]}`, + titleID, labelResp.Label.ID, t.Name()) + s.lastActivityMatches(fleet.ActivityTypeAddedSoftware{}.ActivityName(), activityData, 0) // upload again fails s.uploadSoftwareInstaller(t, payload, http.StatusConflict, "already exists") + // update the installer succeeds + body, headers := generateMultipartRequest(t, "software", + "", []byte{}, s.token, map[string][]string{"self_service": {"true"}, "team_id": {"0"}}) + s.DoRawWithHeaders("PATCH", fmt.Sprintf("/api/latest/fleet/software/titles/%d/package", titleID), body.Bytes(), http.StatusOK, headers) + + activityData = fmt.Sprintf(`{"software_title": "ruby", "software_package": "ruby.deb", "team_name": null, + "team_id": null, "self_service": true, "labels_include_any": [{"id": %d, "name": %q}]}`, + labelResp.Label.ID, t.Name()) + s.lastActivityMatches(fleet.ActivityTypeEditedSoftware{}.ActivityName(), activityData, 0) + // orbit-downloading fails with invalid orbit node key s.Do("POST", "/api/fleet/orbit/software_install/package?alt=media", orbitDownloadSoftwareInstallerRequest{ InstallerID: 123, @@ -10719,6 +10731,10 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD // delete from team 0 succeeds s.Do("DELETE", fmt.Sprintf("/api/latest/fleet/software/titles/%d/available_for_install", titleID), nil, http.StatusNoContent, "team_id", "0") + activityData = fmt.Sprintf(`{"software_title": "ruby", "software_package": "ruby.deb", "team_name": null, + "team_id": null, "self_service": true, "labels_include_any": [{"id": %d, "name": %q}]}`, + labelResp.Label.ID, t.Name()) + s.lastActivityMatches(fleet.ActivityTypeDeletedSoftware{}.ActivityName(), activityData, 0) }) t.Run("create team software installer", func(t *testing.T) { @@ -10935,7 +10951,7 @@ func (s *integrationEnterpriseTestSuite) TestSoftwareInstallerUploadDownloadAndD // check activity s.lastActivityOfTypeMatches(fleet.ActivityTypeDeletedSoftware{}.ActivityName(), - `{"software_title": "ruby", "software_package": "ruby.deb", "team_name": null, "team_id": 0, "self_service": true}`, 0) + `{"software_title": "ruby", "software_package": "ruby.deb", "team_name": null, "team_id": null, "self_service": true}`, 0) // download the installer, not found anymore s.Do("GET", fmt.Sprintf("/api/latest/fleet/software/titles/%d/package?alt=media", titleID), nil, http.StatusNotFound, "team_id", fmt.Sprintf("%d", 0)) diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go index fa8f13911dc0..01633975826e 100644 --- a/server/service/integration_mdm_test.go +++ b/server/service/integration_mdm_test.go @@ -4753,10 +4753,12 @@ func generateMultipartRequest(t *testing.T, writer := multipart.NewWriter(&body) // add file content - ff, err := writer.CreateFormFile(uploadFileField, fileName) - require.NoError(t, err) - _, err = io.Copy(ff, bytes.NewReader(fileContent)) - require.NoError(t, err) + if fileName != "" || len(fileContent) > 0 { + ff, err := writer.CreateFormFile(uploadFileField, fileName) + require.NoError(t, err) + _, err = io.Copy(ff, bytes.NewReader(fileContent)) + require.NoError(t, err) + } // add extra fields for key, values := range extraFields { @@ -4766,7 +4768,7 @@ func generateMultipartRequest(t *testing.T, } } - err = writer.Close() + err := writer.Close() require.NoError(t, err) headers := map[string]string{