From 03d724b6a64dbb7bb41a9491f60d277244a8c488 Mon Sep 17 00:00:00 2001 From: Miguel de la Cruz Date: Fri, 4 Apr 2025 18:06:55 +0200 Subject: [PATCH] Adds the CPA property group endpoint (#30620) * Adds the CPA property group endpoint * Fix test calls --------- Co-authored-by: Miguel de la Cruz --- api/v4/source/custom_profile_attributes.yaml | 29 +++++++++++++++++++ .../api4/custom_profile_attributes.go | 18 ++++++++++++ .../channels/app/custom_profile_attributes.go | 16 +++++----- .../app/custom_profile_attributes_test.go | 16 +++++----- 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/api/v4/source/custom_profile_attributes.yaml b/api/v4/source/custom_profile_attributes.yaml index 893162c041..c7955c0cf9 100644 --- a/api/v4/source/custom_profile_attributes.yaml +++ b/api/v4/source/custom_profile_attributes.yaml @@ -218,6 +218,35 @@ $ref: "#/components/responses/Unauthorized" "403": $ref: "#/components/responses/Forbidden" + "/api/v4/custom_profile_attributes/group": + get: + tags: + - custom profile attributes + summary: Get Custom Profile Attribute property group data + description: | + Get the property group used for Custom Profile Attributes. + + __Minimum server version__: 10.8 + + ##### Permissions + Must be authenticated. + operationId: GetCPAGroup + responses: + "200": + description: Group fetch successful + content: + application/json: + schema: + type: object + properties: + id: + type: string + description: The ID of the custom profile attributes group + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "/api/v4/users/{user_id}/custom_profile_attributes": get: tags: diff --git a/server/channels/api4/custom_profile_attributes.go b/server/channels/api4/custom_profile_attributes.go index 7076ecf1ac..694d552853 100644 --- a/server/channels/api4/custom_profile_attributes.go +++ b/server/channels/api4/custom_profile_attributes.go @@ -23,6 +23,7 @@ func (api *API) InitCustomProfileAttributes() { api.BaseRoutes.CustomProfileAttributesField.Handle("", api.APISessionRequired(deleteCPAField)).Methods(http.MethodDelete) api.BaseRoutes.User.Handle("/custom_profile_attributes", api.APISessionRequired(listCPAValues)).Methods(http.MethodGet) api.BaseRoutes.CustomProfileAttributesValues.Handle("", api.APISessionRequired(patchCPAValues)).Methods(http.MethodPatch) + api.BaseRoutes.CustomProfileAttributes.Handle("/group", api.APISessionRequired(getCPAGroup)).Methods(http.MethodGet) } } @@ -184,6 +185,23 @@ func deleteCPAField(c *Context, w http.ResponseWriter, r *http.Request) { ReturnStatusOK(w) } +func getCPAGroup(c *Context, w http.ResponseWriter, r *http.Request) { + if !model.MinimumEnterpriseLicense(c.App.Channels().License()) { + c.Err = model.NewAppError("Api4.getCPAGroup", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden) + return + } + + groupID, err := c.App.CpaGroupID() + if err != nil { + c.Err = model.NewAppError("Api4.getCPAGroup", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) + return + } + + if err := json.NewEncoder(w).Encode(map[string]string{"id": groupID}); err != nil { + c.Logger.Warn("Error while writing response", mlog.Err(err)) + } +} + func sanitizePropertyValue(cpaField *model.CPAField, rawValue json.RawMessage) (json.RawMessage, error) { fieldType := cpaField.Type diff --git a/server/channels/app/custom_profile_attributes.go b/server/channels/app/custom_profile_attributes.go index 997465dd7c..56346b21a2 100644 --- a/server/channels/app/custom_profile_attributes.go +++ b/server/channels/app/custom_profile_attributes.go @@ -22,7 +22,7 @@ var cpaGroupID string // ToDo: we should explore moving this to the database cache layer // instead of maintaining the ID cached at the application level -func (a *App) cpaGroupID() (string, error) { +func (a *App) CpaGroupID() (string, error) { if cpaGroupID != "" { return cpaGroupID, nil } @@ -37,7 +37,7 @@ func (a *App) cpaGroupID() (string, error) { } func (a *App) GetCPAField(fieldID string) (*model.PropertyField, *model.AppError) { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return nil, model.NewAppError("GetCPAField", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -56,7 +56,7 @@ func (a *App) GetCPAField(fieldID string) (*model.PropertyField, *model.AppError } func (a *App) ListCPAFields() ([]*model.PropertyField, *model.AppError) { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return nil, model.NewAppError("GetCPAFields", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -79,7 +79,7 @@ func (a *App) ListCPAFields() ([]*model.PropertyField, *model.AppError) { } func (a *App) CreateCPAField(field *model.CPAField) (*model.PropertyField, *model.AppError) { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return nil, model.NewAppError("CreateCPAField", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -158,7 +158,7 @@ func (a *App) PatchCPAField(fieldID string, patch *model.PropertyFieldPatch) (*m } func (a *App) DeleteCPAField(id string) *model.AppError { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return model.NewAppError("DeleteCPAField", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -181,7 +181,7 @@ func (a *App) DeleteCPAField(id string) *model.AppError { } func (a *App) ListCPAValues(userID string) ([]*model.PropertyValue, *model.AppError) { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return nil, model.NewAppError("GetCPAFields", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -197,7 +197,7 @@ func (a *App) ListCPAValues(userID string) ([]*model.PropertyValue, *model.AppEr } func (a *App) GetCPAValue(valueID string) (*model.PropertyValue, *model.AppError) { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return nil, model.NewAppError("GetCPAValue", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } @@ -220,7 +220,7 @@ func (a *App) PatchCPAValue(userID string, fieldID string, value json.RawMessage } func (a *App) PatchCPAValues(userID string, fieldValueMap map[string]json.RawMessage) ([]*model.PropertyValue, *model.AppError) { - groupID, err := a.cpaGroupID() + groupID, err := a.CpaGroupID() if err != nil { return nil, model.NewAppError("PatchCPAValues", "app.custom_profile_attributes.cpa_group_id.app_error", nil, "", http.StatusInternalServerError).Wrap(err) } diff --git a/server/channels/app/custom_profile_attributes_test.go b/server/channels/app/custom_profile_attributes_test.go index 0910622f32..251267af13 100644 --- a/server/channels/app/custom_profile_attributes_test.go +++ b/server/channels/app/custom_profile_attributes_test.go @@ -21,7 +21,7 @@ func TestGetCPAField(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) t.Run("should fail when getting a non-existent field", func(t *testing.T) { @@ -73,7 +73,7 @@ func TestListCPAFields(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) t.Run("should list the CPA property fields", func(t *testing.T) { @@ -117,7 +117,7 @@ func TestCreateCPAField(t *testing.T) { defer os.Unsetenv("MM_FEATUREFLAGS_CUSTOMPROFILEATTRIBUTES") th := Setup(t).InitBasic() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) t.Run("should fail if the field is not valid", func(t *testing.T) { @@ -227,7 +227,7 @@ func TestPatchCPAField(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) newField, err := model.NewCPAFieldFromPropertyField(&model.PropertyField{ @@ -363,7 +363,7 @@ func TestDeleteCPAField(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) newField, err := model.NewCPAFieldFromPropertyField(&model.PropertyField{ @@ -445,7 +445,7 @@ func TestGetCPAValue(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) fieldID := model.NewId() @@ -522,7 +522,7 @@ func TestListCPAValues(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) userID := model.NewId() @@ -579,7 +579,7 @@ func TestPatchCPAValue(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() - cpaGroupID, cErr := th.App.cpaGroupID() + cpaGroupID, cErr := th.App.CpaGroupID() require.NoError(t, cErr) t.Run("should fail if the field doesn't exist", func(t *testing.T) {