diff --git a/api/handlers.go b/api/handlers.go index a3c2377..413c1d3 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -128,14 +128,10 @@ func (h *Handlers) UpdateEntry(w http.ResponseWriter, r *http.Request) { entryID := chi.URLParam(r, "entryID") var req struct { - ProjectID string `json:"project_id"` - ParentID string `json:"parent_id"` - Type string `json:"type"` - Depth int `json:"depth"` - Summary string `json:"summary"` Data string `json:"data"` - Stage string `json:"stage"` + Summary string `json:"summary"` AssigneeID string `json:"assignee_id"` + Stage string `json:"stage"` Version int `json:"version"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -143,20 +139,29 @@ func (h *Handlers) UpdateEntry(w http.ResponseWriter, r *http.Request) { return } - entry := &lib.Entry{ - EntryID: entryID, - ProjectID: req.ProjectID, - ParentID: req.ParentID, - Type: req.Type, - Depth: req.Depth, - SummaryText: req.Summary, - DataText: req.Data, - Stage: req.Stage, - AssigneeID: req.AssigneeID, - Version: req.Version, + // Load the existing entry so we preserve project_id, parent_id, type, depth, sort_order + existing, err := lib.EntryByID(h.DB, h.Cfg, entryID) + if err != nil || existing == nil { + ErrorResponse(w, http.StatusNotFound, "not_found", "Entry not found") + return } - if err := lib.EntryWrite(h.DB, h.Cfg, actorID, entry); err != nil { + // Only update the fields the client is allowed to change + if req.Data != "" { + existing.DataText = req.Data + } + if req.Summary != "" { + existing.SummaryText = req.Summary + } + if req.AssigneeID != "" { + existing.AssigneeID = req.AssigneeID + } + if req.Stage != "" { + existing.Stage = req.Stage + } + existing.Version = req.Version + + if err := lib.EntryWrite(h.DB, h.Cfg, actorID, existing); err != nil { if err == lib.ErrAccessDenied { ErrorResponse(w, http.StatusForbidden, "access_denied", "Access denied") return @@ -169,7 +174,7 @@ func (h *Handlers) UpdateEntry(w http.ResponseWriter, r *http.Request) { return } - JSONResponse(w, http.StatusOK, entry) + JSONResponse(w, http.StatusOK, map[string]any{"entry_id": existing.EntryID, "version": existing.Version}) } // DeleteEntry soft-deletes an entry. @@ -1950,6 +1955,8 @@ func (h *Handlers) CreateSection(w http.ResponseWriter, r *http.Request) { projectKey, err := lib.DeriveProjectKey(h.Cfg.MasterKey, projectID) if err != nil { ErrorResponse(w, http.StatusInternalServerError, "internal", "key error"); return } + var parentDepth int + h.DB.Conn.QueryRow(`SELECT depth FROM entries WHERE entry_id=?`, body.ParentID).Scan(&parentDepth) var maxSort int h.DB.Conn.QueryRow( `SELECT COALESCE(MAX(sort_order),0) FROM entries WHERE parent_id=? AND deleted_at IS NULL`, body.ParentID, @@ -1968,7 +1975,7 @@ func (h *Handlers) CreateSection(w http.ResponseWriter, r *http.Request) { search_key, search_key2, summary, data, stage, assignee_id, return_to_id, origin_id, version, deleted_at, deleted_by, key_version, created_at, updated_at, created_by) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, - secID, projectID, body.ParentID, lib.TypeSection, 2, maxSort+1000, + secID, projectID, body.ParentID, lib.TypeSection, parentDepth+1, maxSort+1000, nil, nil, sumPacked, dataPacked, lib.StagePreDataroom, "", "", "", 1, nil, nil, 1, now, now, actorID, ) @@ -2361,6 +2368,12 @@ func (h *Handlers) ImportRequests(w http.ResponseWriter, r *http.Request) { rlSummaryPacked, _ := lib.Pack(projectKey, listName) rlDataPacked, _ := lib.Pack(projectKey, string(rlDataJSON)) + var importMaxSort int + h.DB.Conn.QueryRow( + `SELECT COALESCE(MAX(sort_order),0) FROM entries WHERE project_id=? AND type='request_list' AND deleted_at IS NULL`, projectID, + ).Scan(&importMaxSort) + rlSortOrder := importMaxSort + 1000 + h.DB.Conn.Exec( `INSERT INTO entries (entry_id, project_id, parent_id, type, depth, sort_order, search_key, search_key2, summary, data, stage, @@ -2368,7 +2381,7 @@ func (h *Handlers) ImportRequests(w http.ResponseWriter, r *http.Request) { version, deleted_at, deleted_by, key_version, created_at, updated_at, created_by) VALUES (?,?,?,?,?,?, ?,?,?,?,?, ?,?,?, ?,?,?,?, ?,?,?)`, - requestListID, projectID, projectID, lib.TypeRequestList, 1, 0, + requestListID, projectID, projectID, lib.TypeRequestList, 1, rlSortOrder, nil, nil, rlSummaryPacked, rlDataPacked, lib.StagePreDataroom, "", "", "", 1, nil, nil, 1,