Skip to content

Commit 51049c1

Browse files
committed
patch api for user attribute
1 parent 1f7d0d3 commit 51049c1

File tree

3 files changed

+131
-0
lines changed

3 files changed

+131
-0
lines changed

api/restHandler/UserAttributesRestHandler.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
type UserAttributesRestHandler interface {
3333
AddUserAttributes(w http.ResponseWriter, r *http.Request)
3434
UpdateUserAttributes(w http.ResponseWriter, r *http.Request)
35+
PatchUserAttributes(w http.ResponseWriter, r *http.Request)
3536
GetUserAttribute(w http.ResponseWriter, r *http.Request)
3637
}
3738

@@ -137,6 +138,42 @@ func (handler *UserAttributesRestHandlerImpl) UpdateUserAttributes(w http.Respon
137138
common.WriteJsonResp(w, nil, resp, http.StatusOK)
138139
}
139140

141+
func (handler *UserAttributesRestHandlerImpl) PatchUserAttributes(w http.ResponseWriter, r *http.Request) {
142+
userId, err := handler.userService.GetLoggedInUser(r)
143+
if userId == 0 || err != nil {
144+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
145+
return
146+
}
147+
148+
decoder := json.NewDecoder(r.Body)
149+
var dto attributes.UserAttributesDto
150+
err = decoder.Decode(&dto)
151+
if err != nil {
152+
handler.logger.Errorw("request err, PatchUserAttributes", "err", err, "payload", dto)
153+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
154+
return
155+
}
156+
157+
dto.UserId = userId
158+
159+
emailId, err := handler.userService.GetActiveEmailById(userId)
160+
if err != nil {
161+
handler.logger.Errorw("request err, PatchUserAttributes", "err", err, "payload", dto)
162+
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
163+
return
164+
}
165+
dto.EmailId = emailId
166+
167+
handler.logger.Infow("request payload, PatchUserAttributes", "payload", dto)
168+
resp, err := handler.userAttributesService.PatchUserAttributes(&dto)
169+
if err != nil {
170+
handler.logger.Errorw("service err, PatchUserAttributes", "err", err, "payload", dto)
171+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
172+
return
173+
}
174+
common.WriteJsonResp(w, nil, resp, http.StatusOK)
175+
}
176+
140177
// @Summary get user attributes
141178
// @version 1.0
142179
// @produce application/json

api/router/UserAttributesRouter.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ func NewUserAttributesRouterImpl(userAttributesRestHandler user.UserAttributesRe
3939
func (router UserAttributesRouterImpl) InitUserAttributesRouter(attributesRouter *mux.Router) {
4040
attributesRouter.Path("/update").
4141
HandlerFunc(router.userAttributesRestHandler.UpdateUserAttributes).Methods("POST")
42+
attributesRouter.Path("/patch").
43+
HandlerFunc(router.userAttributesRestHandler.PatchUserAttributes).Methods("PATCH")
4244
attributesRouter.Path("/get").
4345
HandlerFunc(router.userAttributesRestHandler.GetUserAttribute).Queries("key", "{key}").Methods("GET")
4446
}

pkg/attributes/UserAttributesService.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,18 @@
1717
package attributes
1818

1919
import (
20+
"encoding/json"
2021
"errors"
2122
"github.com/devtron-labs/devtron/internal/sql/repository"
2223
"github.com/go-pg/pg"
2324
"go.uber.org/zap"
25+
"reflect"
2426
)
2527

2628
type UserAttributesService interface {
2729
AddUserAttributes(request *UserAttributesDto) (*UserAttributesDto, error)
2830
UpdateUserAttributes(request *UserAttributesDto) (*UserAttributesDto, error)
31+
PatchUserAttributes(request *UserAttributesDto) (*UserAttributesDto, error)
2932
GetUserAttribute(request *UserAttributesDto) (*UserAttributesDto, error)
3033
}
3134

@@ -95,6 +98,95 @@ func (impl UserAttributesServiceImpl) UpdateUserAttributes(request *UserAttribut
9598
return request, nil
9699
}
97100

101+
func (impl UserAttributesServiceImpl) PatchUserAttributes(request *UserAttributesDto) (*UserAttributesDto, error) {
102+
userAttribute, err := impl.GetUserAttribute(request)
103+
if err != nil {
104+
impl.logger.Errorw("error while getting user attributes during patch request", "req", request, "error", err)
105+
return nil, errors.New("error occurred while updating user attributes")
106+
}
107+
if userAttribute == nil {
108+
impl.logger.Info("no data found for request, so going to add instead of update", "req", request)
109+
attributes, err := impl.AddUserAttributes(request)
110+
if err != nil {
111+
impl.logger.Errorw("error in adding new user attributes", "req", request, "error", err)
112+
return nil, errors.New("error occurred while updating user attributes")
113+
}
114+
return attributes, nil
115+
}
116+
117+
// Parse existing JSON
118+
var existingData map[string]interface{}
119+
if userAttribute.Value != "" {
120+
err = json.Unmarshal([]byte(userAttribute.Value), &existingData)
121+
if err != nil {
122+
impl.logger.Errorw("error parsing existing json value", "value", userAttribute.Value, "error", err)
123+
return nil, errors.New("error occurred while updating user attributes")
124+
}
125+
} else {
126+
existingData = make(map[string]interface{})
127+
}
128+
129+
// Parse new JSON
130+
var newData map[string]interface{}
131+
if request.Value != "" {
132+
err = json.Unmarshal([]byte(request.Value), &newData)
133+
if err != nil {
134+
impl.logger.Errorw("error parsing request json value", "value", request.Value, "error", err)
135+
return nil, errors.New("error occurred while updating user attributes")
136+
}
137+
} else {
138+
newData = make(map[string]interface{})
139+
}
140+
141+
// Check if there are any changes
142+
anyChanges := false
143+
144+
// Merge the objects (patch style)
145+
for key, newValue := range newData {
146+
existingValue, exists := existingData[key]
147+
if !exists || !reflect.DeepEqual(existingValue, newValue) {
148+
existingData[key] = newValue
149+
anyChanges = true
150+
}
151+
}
152+
153+
// If no changes, return the existing data
154+
if !anyChanges {
155+
impl.logger.Infow("no change detected, skipping update", "key", request.Key)
156+
return userAttribute, nil
157+
}
158+
159+
// Convert back to JSON string
160+
mergedJson, err := json.Marshal(existingData)
161+
if err != nil {
162+
impl.logger.Errorw("error converting merged data to json", "data", existingData, "error", err)
163+
return nil, errors.New("error occurred while updating user attributes")
164+
}
165+
166+
dao := &repository.UserAttributesDao{
167+
EmailId: request.EmailId,
168+
Key: request.Key,
169+
Value: string(mergedJson),
170+
UserId: request.UserId,
171+
}
172+
173+
err = impl.attributesRepository.UpdateDataValByKey(dao)
174+
if err != nil {
175+
impl.logger.Errorw("error in update attributes", "req", dao, "error", err)
176+
return nil, errors.New("error occurred while updating user attributes")
177+
}
178+
179+
// Return the updated data
180+
result := &UserAttributesDto{
181+
EmailId: request.EmailId,
182+
Key: request.Key,
183+
Value: string(mergedJson),
184+
UserId: request.UserId,
185+
}
186+
187+
return result, nil
188+
}
189+
98190
func (impl UserAttributesServiceImpl) GetUserAttribute(request *UserAttributesDto) (*UserAttributesDto, error) {
99191

100192
dao := &repository.UserAttributesDao{

0 commit comments

Comments
 (0)