3
0

Add endpoint to undo dismissed reminder

User can undo their own reminders.
This commit is contained in:
Vivek Patel 2023-02-24 15:11:49 +05:30 committed by Jože Fortun
parent fdf46fa083
commit 8a7b8d9c7f
7 changed files with 183 additions and 40 deletions

View File

@ -1374,6 +1374,16 @@ endpoints:
name: reminderID
required: true
title: reminder ID
- name: undismiss
method: PATCH
title: Undismiss reminder
path: "/{reminderID}/undismiss"
parameters:
path:
- type: uint64
name: reminderID
required: true
title: reminder ID
- name: snooze
method: PATCH
title: Snooze reminder

View File

@ -25,18 +25,20 @@ type (
Read(context.Context, *request.ReminderRead) (interface{}, error)
Delete(context.Context, *request.ReminderDelete) (interface{}, error)
Dismiss(context.Context, *request.ReminderDismiss) (interface{}, error)
Undismiss(context.Context, *request.ReminderUndismiss) (interface{}, error)
Snooze(context.Context, *request.ReminderSnooze) (interface{}, error)
}
// HTTP API interface
Reminder struct {
List func(http.ResponseWriter, *http.Request)
Create func(http.ResponseWriter, *http.Request)
Update func(http.ResponseWriter, *http.Request)
Read func(http.ResponseWriter, *http.Request)
Delete func(http.ResponseWriter, *http.Request)
Dismiss func(http.ResponseWriter, *http.Request)
Snooze func(http.ResponseWriter, *http.Request)
List func(http.ResponseWriter, *http.Request)
Create func(http.ResponseWriter, *http.Request)
Update func(http.ResponseWriter, *http.Request)
Read func(http.ResponseWriter, *http.Request)
Delete func(http.ResponseWriter, *http.Request)
Dismiss func(http.ResponseWriter, *http.Request)
Undismiss func(http.ResponseWriter, *http.Request)
Snooze func(http.ResponseWriter, *http.Request)
}
)
@ -138,6 +140,22 @@ func NewReminder(h ReminderAPI) *Reminder {
api.Send(w, r, value)
},
Undismiss: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewReminderUndismiss()
if err := params.Fill(r); err != nil {
api.Send(w, r, err)
return
}
value, err := h.Undismiss(r.Context(), params)
if err != nil {
api.Send(w, r, err)
return
}
api.Send(w, r, value)
},
Snooze: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewReminderSnooze()
@ -166,6 +184,7 @@ func (h Reminder) MountRoutes(r chi.Router, middlewares ...func(http.Handler) ht
r.Get("/reminder/{reminderID}", h.Read)
r.Delete("/reminder/{reminderID}", h.Delete)
r.Patch("/reminder/{reminderID}/dismiss", h.Dismiss)
r.Patch("/reminder/{reminderID}/undismiss", h.Undismiss)
r.Patch("/reminder/{reminderID}/snooze", h.Snooze)
})
}

View File

@ -95,6 +95,10 @@ func (ctrl *Reminder) Dismiss(ctx context.Context, r *request.ReminderDismiss) (
return api.OK(), ctrl.reminder.Dismiss(ctx, r.ReminderID)
}
func (ctrl *Reminder) Undismiss(ctx context.Context, r *request.ReminderUndismiss) (interface{}, error) {
return api.OK(), ctrl.reminder.Undismiss(ctx, r.ReminderID)
}
func (ctrl *Reminder) Snooze(ctx context.Context, r *request.ReminderSnooze) (interface{}, error) {
return api.OK(), ctrl.reminder.Snooze(ctx, r.ReminderID, r.RemindAt)
}

View File

@ -162,6 +162,13 @@ type (
ReminderID uint64 `json:",string"`
}
ReminderUndismiss struct {
// ReminderID PATH parameter
//
// reminder ID
ReminderID uint64 `json:",string"`
}
ReminderSnooze struct {
// ReminderID PATH parameter
//
@ -708,6 +715,41 @@ func (r *ReminderDismiss) Fill(req *http.Request) (err error) {
return err
}
// NewReminderUndismiss request
func NewReminderUndismiss() *ReminderUndismiss {
return &ReminderUndismiss{}
}
// Auditable returns all auditable/loggable parameters
func (r ReminderUndismiss) Auditable() map[string]interface{} {
return map[string]interface{}{
"reminderID": r.ReminderID,
}
}
// Auditable returns all auditable/loggable parameters
func (r ReminderUndismiss) GetReminderID() uint64 {
return r.ReminderID
}
// Fill processes request and fills internal variables
func (r *ReminderUndismiss) Fill(req *http.Request) (err error) {
{
var val string
// path params
val = chi.URLParam(req, "reminderID")
r.ReminderID, err = payload.ParseUint64(val), nil
if err != nil {
return err
}
}
return err
}
// NewReminderSnooze request
func NewReminderSnooze() *ReminderSnooze {
return &ReminderSnooze{}

View File

@ -39,6 +39,7 @@ type (
Update(context.Context, *types.Reminder) (*types.Reminder, error)
Dismiss(context.Context, uint64) error
Undismiss(context.Context, uint64) error
Snooze(context.Context, uint64, *time.Time) error
Delete(context.Context, uint64) error
@ -232,6 +233,42 @@ func (svc reminder) Dismiss(ctx context.Context, ID uint64) (err error) {
return svc.recordAction(ctx, raProps, ReminderActionDismiss, err)
}
func (svc reminder) Undismiss(ctx context.Context, ID uint64) (err error) {
var (
r *types.Reminder
raProps = &reminderActionProps{reminder: &types.Reminder{ID: ID}}
)
err = func() (err error) {
if ID == 0 {
return ReminderErrInvalidID()
}
if r, err = store.LookupReminderByID(ctx, svc.store, ID); err != nil {
return ReminderErrNotFound()
}
if svc.checkAssignTo(ctx, r) {
return ReminderErrNotAllowedToUndismiss()
}
raProps.setReminder(r)
// Assign changed values
r.DismissedAt = nil
r.DismissedBy = 0
if err = store.UpdateReminder(ctx, svc.store, r); err != nil {
return err
}
return nil
}()
return svc.recordAction(ctx, raProps, ReminderActionDismiss, err)
}
func (svc reminder) Snooze(ctx context.Context, ID uint64, remindAt *time.Time) (err error) {
var (
r *types.Reminder

View File

@ -11,12 +11,13 @@ package service
import (
"context"
"fmt"
"strings"
"time"
"github.com/cortezaproject/corteza/server/pkg/actionlog"
"github.com/cortezaproject/corteza/server/pkg/errors"
"github.com/cortezaproject/corteza/server/pkg/locale"
"github.com/cortezaproject/corteza/server/system/types"
"strings"
"time"
)
type (
@ -55,7 +56,6 @@ var (
// setReminder updates reminderActionProps's reminder
//
// This function is auto-generated.
//
func (p *reminderActionProps) setReminder(reminder *types.Reminder) *reminderActionProps {
p.reminder = reminder
return p
@ -64,7 +64,6 @@ func (p *reminderActionProps) setReminder(reminder *types.Reminder) *reminderAct
// setNew updates reminderActionProps's new
//
// This function is auto-generated.
//
func (p *reminderActionProps) setNew(new *types.Reminder) *reminderActionProps {
p.new = new
return p
@ -73,7 +72,6 @@ func (p *reminderActionProps) setNew(new *types.Reminder) *reminderActionProps {
// setUpdated updates reminderActionProps's updated
//
// This function is auto-generated.
//
func (p *reminderActionProps) setUpdated(updated *types.Reminder) *reminderActionProps {
p.updated = updated
return p
@ -82,7 +80,6 @@ func (p *reminderActionProps) setUpdated(updated *types.Reminder) *reminderActio
// setFilter updates reminderActionProps's filter
//
// This function is auto-generated.
//
func (p *reminderActionProps) setFilter(filter *types.ReminderFilter) *reminderActionProps {
p.filter = filter
return p
@ -91,7 +88,6 @@ func (p *reminderActionProps) setFilter(filter *types.ReminderFilter) *reminderA
// Serialize converts reminderActionProps to actionlog.Meta
//
// This function is auto-generated.
//
func (p reminderActionProps) Serialize() actionlog.Meta {
var (
m = make(actionlog.Meta)
@ -135,7 +131,6 @@ func (p reminderActionProps) Serialize() actionlog.Meta {
// tr translates string and replaces meta value placeholder with values
//
// This function is auto-generated.
//
func (p reminderActionProps) Format(in string, err error) string {
var (
pairs = []string{"{{err}}"}
@ -252,7 +247,6 @@ func (p reminderActionProps) Format(in string, err error) string {
// String returns loggable description as string
//
// This function is auto-generated.
//
func (a *reminderAction) String() string {
var props = &reminderActionProps{}
@ -280,7 +274,6 @@ func (e *reminderAction) ToAction() *actionlog.Action {
// ReminderActionSearch returns "system:reminder.search" action
//
// This function is auto-generated.
//
func ReminderActionSearch(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
@ -300,7 +293,6 @@ func ReminderActionSearch(props ...*reminderActionProps) *reminderAction {
// ReminderActionLookup returns "system:reminder.lookup" action
//
// This function is auto-generated.
//
func ReminderActionLookup(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
@ -320,7 +312,6 @@ func ReminderActionLookup(props ...*reminderActionProps) *reminderAction {
// ReminderActionCreate returns "system:reminder.create" action
//
// This function is auto-generated.
//
func ReminderActionCreate(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
@ -340,7 +331,6 @@ func ReminderActionCreate(props ...*reminderActionProps) *reminderAction {
// ReminderActionUpdate returns "system:reminder.update" action
//
// This function is auto-generated.
//
func ReminderActionUpdate(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
@ -360,7 +350,6 @@ func ReminderActionUpdate(props ...*reminderActionProps) *reminderAction {
// ReminderActionDelete returns "system:reminder.delete" action
//
// This function is auto-generated.
//
func ReminderActionDelete(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
@ -380,13 +369,31 @@ func ReminderActionDelete(props ...*reminderActionProps) *reminderAction {
// ReminderActionDismiss returns "system:reminder.dismiss" action
//
// This function is auto-generated.
//
func ReminderActionDismiss(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
resource: "system:reminder",
action: "dismiss",
log: "deleted {{reminder}}",
log: "dismissed {{reminder}}",
severity: actionlog.Notice,
}
if len(props) > 0 {
a.props = props[0]
}
return a
}
// ReminderActionUndismiss returns "system:reminder.undismiss" action
//
// This function is auto-generated.
func ReminderActionUndismiss(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
resource: "system:reminder",
action: "undismiss",
log: "undismissed {{reminder}}",
severity: actionlog.Notice,
}
@ -400,13 +407,12 @@ func ReminderActionDismiss(props ...*reminderActionProps) *reminderAction {
// ReminderActionSnooze returns "system:reminder.snooze" action
//
// This function is auto-generated.
//
func ReminderActionSnooze(props ...*reminderActionProps) *reminderAction {
a := &reminderAction{
timestamp: time.Now(),
resource: "system:reminder",
action: "snooze",
log: "deleted {{reminder}}",
log: "snoozed {{reminder}}",
severity: actionlog.Notice,
}
@ -423,9 +429,7 @@ func ReminderActionSnooze(props ...*reminderActionProps) *reminderAction {
// ReminderErrGeneric returns "system:reminder.generic" as *errors.Error
//
//
// This function is auto-generated.
//
func ReminderErrGeneric(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
@ -459,9 +463,7 @@ func ReminderErrGeneric(mm ...*reminderActionProps) *errors.Error {
// ReminderErrNotFound returns "system:reminder.notFound" as *errors.Error
//
//
// This function is auto-generated.
//
func ReminderErrNotFound(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
@ -493,9 +495,7 @@ func ReminderErrNotFound(mm ...*reminderActionProps) *errors.Error {
// ReminderErrInvalidID returns "system:reminder.invalidID" as *errors.Error
//
//
// This function is auto-generated.
//
func ReminderErrInvalidID(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
@ -527,9 +527,7 @@ func ReminderErrInvalidID(mm ...*reminderActionProps) *errors.Error {
// ReminderErrNotAllowedToAssign returns "system:reminder.notAllowedToAssign" as *errors.Error
//
//
// This function is auto-generated.
//
func ReminderErrNotAllowedToAssign(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
@ -561,9 +559,7 @@ func ReminderErrNotAllowedToAssign(mm ...*reminderActionProps) *errors.Error {
// ReminderErrNotAllowedToDismiss returns "system:reminder.notAllowedToDismiss" as *errors.Error
//
//
// This function is auto-generated.
//
func ReminderErrNotAllowedToDismiss(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
@ -593,11 +589,41 @@ func ReminderErrNotAllowedToDismiss(mm ...*reminderActionProps) *errors.Error {
return e
}
// ReminderErrNotAllowedToRead returns "system:reminder.notAllowedToRead" as *errors.Error
//
// ReminderErrNotAllowedToUndismiss returns "system:reminder.notAllowedToUndismiss" as *errors.Error
//
// This function is auto-generated.
func ReminderErrNotAllowedToUndismiss(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to undo dismissed reminders of other users", nil),
errors.Meta("type", "notAllowedToUndismiss"),
errors.Meta("resource", "system:reminder"),
errors.Meta(reminderPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "system"),
errors.Meta(locale.ErrorMetaKey{}, "reminder.errors.notAllowedToUndismiss"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// ReminderErrNotAllowedToRead returns "system:reminder.notAllowedToRead" as *errors.Error
//
// This function is auto-generated.
func ReminderErrNotAllowedToRead(mm ...*reminderActionProps) *errors.Error {
var p = &reminderActionProps{}
if len(mm) > 0 {
@ -635,7 +661,6 @@ func ReminderErrNotAllowedToRead(mm ...*reminderActionProps) *errors.Error {
// It will wrap unrecognized/internal errors with generic errors.
//
// This function is auto-generated.
//
func (svc reminder) recordAction(ctx context.Context, props *reminderActionProps, actionFn func(...*reminderActionProps) *reminderAction, err error) error {
if svc.actionlog == nil || actionFn == nil {
// action log disabled or no action fn passed, return error as-is

View File

@ -45,10 +45,13 @@ actions:
log: "deleted {{reminder}}"
- action: dismiss
log: "deleted {{reminder}}"
log: "dismissed {{reminder}}"
- action: undismiss
log: "undismissed {{reminder}}"
- action: snooze
log: "deleted {{reminder}}"
log: "snoozed {{reminder}}"
errors:
- error: notFound
@ -65,5 +68,8 @@ errors:
- error: notAllowedToDismiss
message: "not allowed to dismiss reminders of other users"
- error: notAllowedToUndismiss
message: "not allowed to undo dismissed reminders of other users"
- error: notAllowedToRead
message: "not allowed to read reminders of other users"