Adds the CPA property group endpoint (#30620)

* Adds the CPA property group endpoint

* Fix test calls

---------

Co-authored-by: Miguel de la Cruz <miguel@ctrlz.es>
Этот коммит содержится в:
Miguel de la Cruz
2025-04-04 18:06:55 +02:00
коммит произвёл GitHub
родитель d2173eb664
Коммит 03d724b6a6
4 изменённых файлов: 63 добавлений и 16 удалений

Просмотреть файл

@@ -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:

Просмотреть файл

@@ -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

Просмотреть файл

@@ -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)
}

Просмотреть файл

@@ -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) {