From 887fd65c756edc5d7699e293988a83bfcbd45d11 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Sun, 13 Nov 2022 08:31:43 -0800 Subject: [PATCH] addind endpoints to support notification config --- doc/api.oa3 | 74 ++++++++++++++++++- net/server/internal/api_getAccountStatus.go | 1 + .../internal/api_getChannelNotification.go | 58 +++++++++++++++ .../internal/api_setAccountNotification.go | 41 ++++++++++ .../internal/api_setChannelNotification.go | 52 +++++++++++++ net/server/internal/models.go | 2 + net/server/internal/routers.go | 21 ++++++ net/server/internal/store/schema.go | 2 +- 8 files changed, 248 insertions(+), 3 deletions(-) create mode 100644 net/server/internal/api_getChannelNotification.go create mode 100644 net/server/internal/api_setAccountNotification.go create mode 100644 net/server/internal/api_setChannelNotification.go diff --git a/doc/api.oa3 b/doc/api.oa3 index 9f1bc7cb..2bb7cf9c 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -534,7 +534,35 @@ paths: description: authentication error '500': description: internal server error - + + /account/notification: + put: + tags: + - account + description: Set whether account should receive push notifications. + operationId: set-account-notification + parameters: + - name: agent + in: query + description: agent token + required: false + schema: + type: string + responses: + '201': + description: success + '401': + description: permission denied + '405': + description: failed to confirm + '500': + description: internal server error + requestBody: + content: + application/json: + schema: + type: boolean + /account/searchable: put: tags: @@ -2494,7 +2522,46 @@ paths: description: internal server error /content/channels/{channelId}/notification: - put: + get: + tags: + - content + description: Get notification enabled state for the specified channel + operationId: get-channel-notifications + parameters: + - name: channelId + in: path + description: specified channel id + required: true + schema: + type: string + - name: agent + in: query + description: access token granted to agent + required: true + schema: + type: string + - name: contact + in: query + description: access token granted to contact + required: true + schema: + type: string + responses: + '200': + description: success + content: + application/json: + schema: + type: boolean + '401': + description: permission denied + '404': + description: field, channel not found + '410': + description: account disabled + '500': + description: internal server error + put: tags: - content description: Set notification enabled state for the specified channel @@ -3577,6 +3644,7 @@ components: - storageAvailable - forwardingAddress - searchable + - pushEnabled properties: disabled: type: boolean @@ -3590,6 +3658,8 @@ components: type: string searchable: type: boolean + pushEnabled: + type: boolean AccountProfile: type: object diff --git a/net/server/internal/api_getAccountStatus.go b/net/server/internal/api_getAccountStatus.go index 5fb4427a..09364acc 100644 --- a/net/server/internal/api_getAccountStatus.go +++ b/net/server/internal/api_getAccountStatus.go @@ -29,6 +29,7 @@ func GetAccountStatus(w http.ResponseWriter, r *http.Request) { status.Disabled = account.Disabled status.ForwardingAddress = account.Forward status.Searchable = account.Searchable + status.PushEnabled = account.PushEnabled WriteResponse(w, status) } diff --git a/net/server/internal/api_getChannelNotification.go b/net/server/internal/api_getChannelNotification.go new file mode 100644 index 00000000..998878c9 --- /dev/null +++ b/net/server/internal/api_getChannelNotification.go @@ -0,0 +1,58 @@ +package databag + +import ( + "databag/internal/store" + "errors" + "github.com/gorilla/mux" + "gorm.io/gorm" + "net/http" +) + +//GetChannelNotifications gets enabled state of channel +func GetChannelNotification(w http.ResponseWriter, r *http.Request) { + + // get referenced channel + params := mux.Vars(r) + channelID := params["channelID"] + + // get enabled state + var flag bool + if err := ParseRequest(r, w, &flag); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + tokenType := ParamTokenType(r) + if tokenType == APPTokenAgent { + account, code, err := ParamAgentToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + + // return notification status + WriteResponse(w, account.PushEnabled) + } else if tokenType == APPTokenContact { + card, code, err := ParamContactToken(r, true) + if err != nil { + ErrResponse(w, code, err) + return + } + + // update member notification status + member := store.Member{} + if store.DB.Model(&member).Where("channel_id ? AND card_id = ?", channelID, card.ID).First(&member).Error != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + ErrResponse(w, http.StatusNotFound, err) + } else { + ErrResponse(w, http.StatusInternalServerError, err) + } + return + } + + // return notification status + WriteResponse(w, member.PushEnabled) + } else { + ErrResponse(w, http.StatusUnauthorized, errors.New("invalid access token")) + } +} diff --git a/net/server/internal/api_setAccountNotification.go b/net/server/internal/api_setAccountNotification.go new file mode 100644 index 00000000..b02ec7b5 --- /dev/null +++ b/net/server/internal/api_setAccountNotification.go @@ -0,0 +1,41 @@ +package databag + +import ( + "databag/internal/store" + "gorm.io/gorm" + "net/http" +) + +//SetAccountNotification sets whether notifications should be received +func SetAccountNotification(w http.ResponseWriter, r *http.Request) { + + account, code, err := ParamAgentToken(r, true) + if err != nil { + ErrResponse(w, code, err) + return + } + + var flag bool + if err := ParseRequest(r, w, &flag); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := tx.Model(account).Update("push_enabled", flag).Error; res != nil { + ErrResponse(w, http.StatusInternalServerError, res) + return res + } + if res := tx.Model(&account).Update("account_revision", account.AccountRevision+1).Error; res != nil { + return res + } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + SetStatus(account) + WriteResponse(w, nil) +} diff --git a/net/server/internal/api_setChannelNotification.go b/net/server/internal/api_setChannelNotification.go new file mode 100644 index 00000000..9cefc794 --- /dev/null +++ b/net/server/internal/api_setChannelNotification.go @@ -0,0 +1,52 @@ +package databag + +import ( + "databag/internal/store" + "errors" + "github.com/gorilla/mux" + "net/http" +) + +//SetChannelNotifications enables or disables notifcation +func SetChannelNotification(w http.ResponseWriter, r *http.Request) { + + // get referenced channel + params := mux.Vars(r) + channelID := params["channelID"] + + // get enabled state + var flag bool + if err := ParseRequest(r, w, &flag); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + tokenType := ParamTokenType(r) + if tokenType == APPTokenAgent { + account, code, err := ParamAgentToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + + // update host notification status + if err = store.DB.Model(&store.Channel{}).Where("account_id = ? AND id = ?", account.ID, channelID).Update("host_push", flag).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else if tokenType == APPTokenContact { + card, code, err := ParamContactToken(r, true) + if err != nil { + ErrResponse(w, code, err) + return + } + + // update member notification status + if err := store.DB.Model(&store.Member{}).Where("channel_id = ? AND card_id = ?", channelID, card.ID).Update("push_enabled", flag).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + } + } else { + ErrResponse(w, http.StatusUnauthorized, errors.New("invalid access token")) + return + } +} diff --git a/net/server/internal/models.go b/net/server/internal/models.go index 97a61447..8ac1115d 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -30,6 +30,8 @@ type AccountStatus struct { ForwardingAddress string `json:"forwardingAddress"` Searchable bool `json:"searchable"` + + PushEnabled bool `json:"pushEnabled"` } //Announce initial message sent on websocket diff --git a/net/server/internal/routers.go b/net/server/internal/routers.go index 1ed7d009..f6f56e40 100644 --- a/net/server/internal/routers.go +++ b/net/server/internal/routers.go @@ -181,6 +181,13 @@ var endpoints = routes{ SetAccountLogin, }, + route{ + "SetAccountNotification", + strings.ToUpper("Get"), + "/account/notification", + SetAccountNotification, + }, + route{ "SetAccountSerchable", strings.ToUpper("Put"), @@ -692,6 +699,20 @@ var endpoints = routes{ SetChannelGroup, }, + route{ + "GetChannelNotification", + strings.ToUpper("Get"), + "/content/channels/{channelID}/notification", + GetChannelNotification, + }, + + route{ + "SetChannelNotification", + strings.ToUpper("Put"), + "/content/channels/{channelID}/notification", + SetChannelNotification, + }, + route{ "SetChannelSubject", strings.ToUpper("Put"), diff --git a/net/server/internal/store/schema.go b/net/server/internal/store/schema.go index b6d09a89..8b7fab2d 100644 --- a/net/server/internal/store/schema.go +++ b/net/server/internal/store/schema.go @@ -80,6 +80,7 @@ type Account struct { Updated int64 `gorm:"autoUpdateTime"` Disabled bool `gorm:"not null;default:false"` Searchable bool `gorm:"not null;default:false"` + PushEnabled bool `gorm:"not null;default:true"` Forward string AccountDetail AccountDetail Apps []App @@ -238,7 +239,6 @@ type Channel struct { DetailRevision int64 `gorm:"not null"` DataType string `gorm:"index"` Data string - ChannelPush bool HostPush bool Created int64 `gorm:"autoCreateTime"` Updated int64 `gorm:"autoUpdateTime"`