diff --git a/store/rdbms/reminder.go b/store/rdbms/reminder.go index 1d0b1a220..a62343881 100644 --- a/store/rdbms/reminder.go +++ b/store/rdbms/reminder.go @@ -17,6 +17,10 @@ func (s Store) convertReminderFilter(f types.ReminderFilter) (query squirrel.Sel query = query.Where("rmd.dismissed_at IS NULL") } + if !f.IncludeDeleted { + query = query.Where("rmd.deleted_at IS NULL") + } + if f.ScheduledOnly { query = query.Where("rmd.remind_at IS NOT NULL") } diff --git a/system/rest.yaml b/system/rest.yaml index 6b6d5ae31..1be73dd30 100644 --- a/system/rest.yaml +++ b/system/rest.yaml @@ -987,6 +987,10 @@ endpoints: required: false title: Filter out dismissed reminders type: bool + - name: includeDeleted + required: false + title: Includes deleted reminders + type: bool - type: uint name: limit title: Limit diff --git a/system/rest/reminder.go b/system/rest/reminder.go index 68e4bfb0c..a0622b6f3 100644 --- a/system/rest/reminder.go +++ b/system/rest/reminder.go @@ -40,6 +40,7 @@ func (ctrl *Reminder) List(ctx context.Context, r *request.ReminderList) (interf ScheduledFrom: r.ScheduledFrom, ScheduledUntil: r.ScheduledUntil, ExcludeDismissed: r.ExcludeDismissed, + IncludeDeleted: r.IncludeDeleted, ScheduledOnly: r.ScheduledOnly, } ) @@ -52,8 +53,8 @@ func (ctrl *Reminder) List(ctx context.Context, r *request.ReminderList) (interf return nil, err } - set, filter, err := ctrl.reminder.Find(ctx, f) - return ctrl.makeFilterPayload(ctx, set, filter, err) + set, f, err := ctrl.reminder.Find(ctx, f) + return ctrl.makeFilterPayload(ctx, set, f, err) } func (ctrl *Reminder) Create(ctx context.Context, r *request.ReminderCreate) (interface{}, error) { diff --git a/system/rest/request/reminder.go b/system/rest/request/reminder.go index bf300a892..48a7f59ab 100644 --- a/system/rest/request/reminder.go +++ b/system/rest/request/reminder.go @@ -71,6 +71,11 @@ type ( // Filter out dismissed reminders ExcludeDismissed bool + // IncludeDeleted GET parameter + // + // Includes deleted reminders + IncludeDeleted bool + // Limit GET parameter // // Limit @@ -185,6 +190,7 @@ func (r ReminderList) Auditable() map[string]interface{} { "scheduledUntil": r.ScheduledUntil, "scheduledOnly": r.ScheduledOnly, "excludeDismissed": r.ExcludeDismissed, + "includeDeleted": r.IncludeDeleted, "limit": r.Limit, "pageCursor": r.PageCursor, "sort": r.Sort, @@ -226,6 +232,11 @@ func (r ReminderList) GetExcludeDismissed() bool { return r.ExcludeDismissed } +// Auditable returns all auditable/loggable parameters +func (r ReminderList) GetIncludeDeleted() bool { + return r.IncludeDeleted +} + // Auditable returns all auditable/loggable parameters func (r ReminderList) GetLimit() uint { return r.Limit @@ -295,6 +306,12 @@ func (r *ReminderList) Fill(req *http.Request) (err error) { return err } } + if val, ok := tmp["includeDeleted"]; ok && len(val) > 0 { + r.IncludeDeleted, err = payload.ParseBool(val[0]), nil + if err != nil { + return err + } + } if val, ok := tmp["limit"]; ok && len(val) > 0 { r.Limit, err = payload.ParseUint(val[0]), nil if err != nil { diff --git a/system/types/reminder.go b/system/types/reminder.go index 7c0da63a9..e38adbbd2 100644 --- a/system/types/reminder.go +++ b/system/types/reminder.go @@ -35,6 +35,7 @@ type ( ScheduledFrom *time.Time `json:"scheduledFrom"` ScheduledUntil *time.Time `json:"scheduledUntil"` ExcludeDismissed bool `json:"excludeDismissed"` + IncludeDeleted bool `json:"includeDeleted"` ScheduledOnly bool `json:"scheduledOnly"` // Check fn is called by store backend for each resource found function can diff --git a/tests/system/reminder_test.go b/tests/system/reminder_test.go index 9d2c2e94d..94637f2f9 100644 --- a/tests/system/reminder_test.go +++ b/tests/system/reminder_test.go @@ -21,13 +21,26 @@ func (h helper) clearReminders() { } func (h helper) makeReminder() *types.Reminder { - return h.makeReminderByUserID(h.cUser.ID) + return h.reminder(h.cUser.ID, false) } func (h helper) makeReminderByUserID(userID uint64) *types.Reminder { + return h.reminder(userID, false) +} + +func (h helper) makeDeletedReminder() *types.Reminder { + return h.reminder(h.cUser.ID, true) +} + +func (h helper) reminder(userID uint64, deleted bool) *types.Reminder { rm := &types.Reminder{Resource: "test:resource", AssignedTo: userID} rm.ID = id.Next() rm.CreatedAt = time.Now() + if deleted { + now := time.Now() + rm.DeletedAt = &now + } + h.noError(store.CreateReminder(context.Background(), service.DefaultStore, rm)) return rm } @@ -123,14 +136,33 @@ func TestReminderList(t *testing.T) { h.clearReminders() h.makeReminder() - h.makeReminder() + h.makeDeletedReminder() + h.makeDeletedReminder() h.apiInit(). Get("/reminder/"). Expect(t). Status(http.StatusOK). Assert(helpers.AssertNoErrors). - Assert(jsonpath.Len("$.response.set", 2)). + Assert(jsonpath.Len("$.response.set", 1)). + End() +} + +func TestReminderListIncludeDeleted(t *testing.T) { + h := newHelper(t) + h.clearReminders() + + h.makeReminder() + h.makeDeletedReminder() + h.makeDeletedReminder() + + h.apiInit(). + Get("/reminder/"). + Query("includeDeleted", "true"). + Expect(t). + Status(http.StatusOK). + Assert(helpers.AssertNoErrors). + Assert(jsonpath.Len("$.response.set", 3)). End() }