[MM-62552] Custom Profile Attributes: use json.RawMessage for the value. (#29989)
* refactor: Move property value sanitization to model layer * feat: Add value sanitization for custom profile attributes * refactor: Update custom profile attributes to use json.RawMessage * refactor: Update patchCustomProfileAttribute to handle json.RawMessage directly * refactor: Refactor custom profile attributes handler with improved validation * refactor: Rename `patchCustomProfileAttribute` to `patchCPAValues` * refactor: Replace ReturnJSON with json.NewEncoder and add error logging * feat: Add encoding/json import to property_value.go * refactor: Update property value tests to use json.RawMessage * fix: Convert string value to json.RawMessage in property value test * fix: Convert string literals to json.RawMessage in property value tests * fix: Add missing encoding/json import in custom_profile_attributes.go * fix: Preserve JSON RawMessage type in listCPAValues function * fix: Update custom profile attributes test to use json.RawMessage * feat: Add json import to custom_profile_attributes_test.go * refactor: Update ListCPAValues and PatchCPAValues to use json.RawMessage * refactor: Rename `actualValue` to `updatedValue` in custom profile attributes test * refactor: Improve user permission and audit logging for custom profile attributes patch * refactor: Optimize CPA field lookup by using ListCPAFields() and map * fix: Correct user ID reference in custom profile attributes patch endpoint * refactor: Change patchCPAValues to use map[string]json.RawMessage for results * refactor: format and fix tests * test: Add comprehensive unit tests for sanitizePropertyValue function * test: Add test case for invalid property value type * feat: Use `model.NewId()` to generate valid IDs in custom profile attributes tests * refactor: Replace hardcoded IDs with dynamic variables in custom profile attributes test * refactor: restore variable name * refactor: drop undesired changes * chore: refresh app layers * feat: Update API definition to support string or string array values for custom profile attributes * test: Add test cases for multiselect custom profile attribute values * test: Add tests for multiselect custom profile attribute values * test: Isolate array value test in separate t.Run * test: Add test case for multiselect array values in custom profile attributes * refactor: Move array value test from TestCreateCPAField to TestPatchCPAValue * test: Update custom profile attributes test assertions * test: add test case for handling array values in GetCPAValue * test: Add array value tests for property value store * refactor(store): no need to convert to json the rawmessage * chore: lint * i18n * use model to interface with sqlx * fix: Allow empty strings for text, date, and select profile attributes * refactor: Filter out empty strings in multiselect and multiuser fields * refactor: Update multiuser field sanitization to validate and error on invalid IDs * refactor: Simplify sanitizePropertyValue function with reduced code duplication * fix: Allow empty user ID in custom profile attribute sanitization * refactor: Convert comment-based subtests to nested t.Run in TestSanitizePropertyValue * refactor: Convert comment-based subtests to nested t.Run tests in TestSanitizePropertyValue --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
@@ -9465,21 +9465,21 @@ func (c *Client4) DeleteCPAField(ctx context.Context, fieldID string) (*Response
|
||||
return BuildResponse(r), nil
|
||||
}
|
||||
|
||||
func (c *Client4) ListCPAValues(ctx context.Context, userID string) (map[string]string, *Response, error) {
|
||||
func (c *Client4) ListCPAValues(ctx context.Context, userID string) (map[string]json.RawMessage, *Response, error) {
|
||||
r, err := c.DoAPIGet(ctx, c.userCustomProfileAttributesRoute(userID), "")
|
||||
if err != nil {
|
||||
return nil, BuildResponse(r), err
|
||||
}
|
||||
defer closeBody(r)
|
||||
|
||||
fields := make(map[string]string)
|
||||
fields := make(map[string]json.RawMessage)
|
||||
if err := json.NewDecoder(r.Body).Decode(&fields); err != nil {
|
||||
return nil, nil, NewAppError("ListCPAValues", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
return fields, BuildResponse(r), nil
|
||||
}
|
||||
|
||||
func (c *Client4) PatchCPAValues(ctx context.Context, values map[string]string) (map[string]string, *Response, error) {
|
||||
func (c *Client4) PatchCPAValues(ctx context.Context, values map[string]json.RawMessage) (map[string]json.RawMessage, *Response, error) {
|
||||
buf, err := json.Marshal(values)
|
||||
if err != nil {
|
||||
return nil, nil, NewAppError("PatchCPAValues", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
@@ -9491,7 +9491,7 @@ func (c *Client4) PatchCPAValues(ctx context.Context, values map[string]string)
|
||||
}
|
||||
defer closeBody(r)
|
||||
|
||||
var patchedValues map[string]string
|
||||
var patchedValues map[string]json.RawMessage
|
||||
if err := json.NewDecoder(r.Body).Decode(&patchedValues); err != nil {
|
||||
return nil, nil, NewAppError("PatchCPAValues", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@ func (pf *PropertyField) IsValid() error {
|
||||
return NewAppError("PropertyField.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "name", "Reason": "value cannot be empty"}, "id="+pf.ID, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !(pf.Type == PropertyFieldTypeText ||
|
||||
pf.Type == PropertyFieldTypeSelect ||
|
||||
pf.Type == PropertyFieldTypeMultiselect ||
|
||||
pf.Type == PropertyFieldTypeDate ||
|
||||
pf.Type == PropertyFieldTypeUser ||
|
||||
pf.Type == PropertyFieldTypeMultiuser) {
|
||||
if pf.Type != PropertyFieldTypeText &&
|
||||
pf.Type != PropertyFieldTypeSelect &&
|
||||
pf.Type != PropertyFieldTypeMultiselect &&
|
||||
pf.Type != PropertyFieldTypeDate &&
|
||||
pf.Type != PropertyFieldTypeUser &&
|
||||
pf.Type != PropertyFieldTypeMultiuser {
|
||||
return NewAppError("PropertyField.IsValid", "model.property_field.is_valid.app_error", map[string]any{"FieldName": "type", "Reason": "unknown value"}, "id="+pf.ID, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,21 @@
|
||||
|
||||
package model
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type PropertyValue struct {
|
||||
ID string `json:"id"`
|
||||
TargetID string `json:"target_id"`
|
||||
TargetType string `json:"target_type"`
|
||||
GroupID string `json:"group_id"`
|
||||
FieldID string `json:"field_id"`
|
||||
Value string `json:"value"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
ID string `json:"id"`
|
||||
TargetID string `json:"target_id"`
|
||||
TargetType string `json:"target_type"`
|
||||
GroupID string `json:"group_id"`
|
||||
FieldID string `json:"field_id"`
|
||||
Value json.RawMessage `json:"value"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
}
|
||||
|
||||
func (pv *PropertyValue) PreSave() {
|
||||
|
||||
Ссылка в новой задаче
Block a user