[Gekidou] Add push notification check to ping (#19610)
* Add push notification check to ping * Add test type and missing details * Address feedback * Fix function name * Address feedback Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7e2ae93231
Коммит
32e3c2f0b8
@@ -183,6 +183,10 @@ func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set(filestoreStatusKey, s[filestoreStatusKey])
|
||||
}
|
||||
|
||||
if deviceID := r.FormValue("device_id"); deviceID != "" {
|
||||
s["CanReceiveNotifications"] = c.App.SendTestPushNotification(deviceID)
|
||||
}
|
||||
|
||||
if s[model.STATUS] != model.StatusOk {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -96,6 +96,17 @@ func TestGetPing(t *testing.T) {
|
||||
respString = string(respBytes)
|
||||
require.Contains(t, respString, "testvalue")
|
||||
}, "ping feature flag test")
|
||||
|
||||
th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
|
||||
th.App.ReloadConfig()
|
||||
resp, err := client.DoAPIGet("/system/ping?device_id=platform:id", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
var respMap map[string]string
|
||||
err = json.NewDecoder(resp.Body).Decode(&respMap)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "unknown", respMap["CanReceiveNotifications"]) // Unrecognized platform
|
||||
}, "ping and test push notification")
|
||||
}
|
||||
|
||||
func TestGetAudits(t *testing.T) {
|
||||
|
||||
@@ -977,6 +977,7 @@ type AppIface interface {
|
||||
SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User, parentPostList *model.PostList, setOnline bool) ([]string, error)
|
||||
SendPasswordReset(email string, siteURL string) (bool, *model.AppError)
|
||||
SendPaymentFailedEmail(failedPayment *model.FailedPayment) *model.AppError
|
||||
SendTestPushNotification(deviceID string) string
|
||||
ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId, destinationPluginId string)
|
||||
SessionHasPermissionTo(session model.Session, permission *model.Permission) bool
|
||||
SessionHasPermissionToAny(session model.Session, permissions []*model.Permission) bool
|
||||
|
||||
@@ -379,6 +379,32 @@ func (s *Server) StopPushNotificationsHubWorkers() {
|
||||
s.PushNotificationsHub.stop()
|
||||
}
|
||||
|
||||
func (a *App) rawSendToPushProxy(msg *model.PushNotification) (model.PushResponse, error) {
|
||||
msgJSON, jsonErr := json.Marshal(msg)
|
||||
if jsonErr != nil {
|
||||
return nil, errors.Wrap(jsonErr, "failed to encode to JSON")
|
||||
}
|
||||
|
||||
url := strings.TrimRight(*a.Config().EmailSettings.PushNotificationServer, "/") + model.APIURLSuffixV1 + "/send_push"
|
||||
request, err := http.NewRequest("POST", url, bytes.NewReader(msgJSON))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := a.Srv().pushNotificationClient.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var pushResponse model.PushResponse
|
||||
if jsonErr := json.NewDecoder(resp.Body).Decode(&pushResponse); jsonErr != nil {
|
||||
return nil, errors.Wrap(jsonErr, "failed to decode from JSON")
|
||||
}
|
||||
|
||||
return pushResponse, nil
|
||||
}
|
||||
|
||||
func (a *App) sendToPushProxy(msg *model.PushNotification, session *model.Session) error {
|
||||
msg.ServerId = a.TelemetryId()
|
||||
|
||||
@@ -390,28 +416,11 @@ func (a *App) sendToPushProxy(msg *model.PushNotification, session *model.Sessio
|
||||
mlog.String("status", model.PushSendPrepare),
|
||||
)
|
||||
|
||||
msgJSON, jsonErr := json.Marshal(msg)
|
||||
if jsonErr != nil {
|
||||
return errors.Wrap(jsonErr, "failed to encode to JSON")
|
||||
}
|
||||
|
||||
url := strings.TrimRight(*a.Config().EmailSettings.PushNotificationServer, "/") + model.APIURLSuffixV1 + "/send_push"
|
||||
request, err := http.NewRequest("POST", url, bytes.NewReader(msgJSON))
|
||||
pushResponse, err := a.rawSendToPushProxy(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := a.Srv().pushNotificationClient.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var pushResponse model.PushResponse
|
||||
if jsonErr := json.NewDecoder(resp.Body).Decode(&pushResponse); jsonErr != nil {
|
||||
return errors.Wrap(jsonErr, "failed to decode from JSON")
|
||||
}
|
||||
|
||||
switch pushResponse[model.PushStatus] {
|
||||
case model.PushStatusRemove:
|
||||
a.AttachDeviceId(session.Id, "", session.ExpiresAt)
|
||||
@@ -568,6 +577,40 @@ func (a *App) BuildPushNotificationMessage(contentsConfig string, post *model.Po
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func (a *App) SendTestPushNotification(deviceID string) string {
|
||||
msg := &model.PushNotification{
|
||||
Version: "2",
|
||||
Type: model.PushTypeTest,
|
||||
ServerId: a.TelemetryId(),
|
||||
Badge: -1,
|
||||
}
|
||||
msg.SetDeviceIdAndPlatform(deviceID)
|
||||
|
||||
pushResponse, err := a.rawSendToPushProxy(msg)
|
||||
if err != nil {
|
||||
a.NotificationsLog().Error("Notification error",
|
||||
mlog.String("type", msg.Type),
|
||||
mlog.String("deviceId", msg.DeviceId),
|
||||
mlog.String("status", err.Error()),
|
||||
)
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
switch pushResponse[model.PushStatus] {
|
||||
case model.PushStatusRemove:
|
||||
return "false"
|
||||
case model.PushStatusFail:
|
||||
a.NotificationsLog().Error("Notification error",
|
||||
mlog.String("type", msg.Type),
|
||||
mlog.String("deviceId", msg.DeviceId),
|
||||
mlog.String("status", pushResponse[model.PushStatusErrorMsg]),
|
||||
)
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
return "true"
|
||||
}
|
||||
|
||||
func (a *App) buildIdLoadedPushNotificationMessage(channel *model.Channel, post *model.Post, user *model.User) *model.PushNotification {
|
||||
userLocale := i18n.GetUserTranslations(user.Locale)
|
||||
msg := &model.PushNotification{
|
||||
|
||||
@@ -1031,9 +1031,7 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R
|
||||
|
||||
// Don't do any checking if it's a benchmark
|
||||
if _, ok := h.t.(*testing.B); ok {
|
||||
resp := model.NewOkPushResponse()
|
||||
jsonData, _ := json.Marshal(&resp)
|
||||
fmt.Fprintln(w, jsonData)
|
||||
h.printResponse(w, model.NewOkPushResponse())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1042,9 +1040,7 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R
|
||||
var err error
|
||||
if r.URL.Path == "/api/v1/send_push" {
|
||||
if err = json.NewDecoder(r.Body).Decode(¬ification); err != nil {
|
||||
resp := model.NewErrorPushResponse("fail")
|
||||
jsonData, _ := json.Marshal(&resp)
|
||||
fmt.Fprintln(w, jsonData)
|
||||
h.printResponse(w, model.NewErrorPushResponse("fail"))
|
||||
return
|
||||
}
|
||||
// We verify that messages are being sent in order per-device.
|
||||
@@ -1057,9 +1053,7 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R
|
||||
}
|
||||
} else {
|
||||
if err = json.NewDecoder(r.Body).Decode(¬ificationAck); err != nil {
|
||||
resp := model.NewErrorPushResponse("fail")
|
||||
jsonData, _ := json.Marshal(&resp)
|
||||
fmt.Fprintln(w, jsonData)
|
||||
h.printResponse(w, model.NewErrorPushResponse("fail"))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1086,11 +1080,15 @@ func (h *testPushNotificationHandler) handleReq(w http.ResponseWriter, r *http.R
|
||||
resp = model.NewRemovePushResponse()
|
||||
}
|
||||
}
|
||||
jsonData, _ := json.Marshal(&resp)
|
||||
fmt.Fprintln(w, jsonData)
|
||||
h.printResponse(w, resp)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *testPushNotificationHandler) printResponse(w http.ResponseWriter, resp model.PushResponse) {
|
||||
jsonData, _ := json.Marshal(&resp)
|
||||
fmt.Fprintln(w, string(jsonData))
|
||||
}
|
||||
|
||||
func (h *testPushNotificationHandler) numReqs() int {
|
||||
h.mut.RLock()
|
||||
defer h.mut.RUnlock()
|
||||
@@ -1239,6 +1237,33 @@ func TestUpdateMobileAppBadgeSync(t *testing.T) {
|
||||
assert.Equal(t, model.PushTypeUpdateBadge, handler.notifications()[1].Type)
|
||||
}
|
||||
|
||||
func TestSendTestPushNotification(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
handler := &testPushNotificationHandler{t: t}
|
||||
pushServer := httptest.NewServer(
|
||||
http.HandlerFunc(handler.handleReq),
|
||||
)
|
||||
defer pushServer.Close()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.EmailSettings.PushNotificationServer = pushServer.URL
|
||||
})
|
||||
|
||||
// Per mock definition, first time will send remove, second time will send OK
|
||||
result := th.App.SendTestPushNotification("platform:id")
|
||||
assert.Equal(t, "false", result)
|
||||
result = th.App.SendTestPushNotification("platform:id")
|
||||
assert.Equal(t, "true", result)
|
||||
|
||||
// Server side verification.
|
||||
// We verify that 2 requests have been sent, and also check the message contents.
|
||||
require.Equal(t, 2, handler.numReqs())
|
||||
assert.Equal(t, model.PushTypeTest, handler.notifications()[0].Type)
|
||||
assert.Equal(t, model.PushTypeTest, handler.notifications()[1].Type)
|
||||
}
|
||||
|
||||
func TestSendAckToPushProxy(t *testing.T) {
|
||||
th := SetupWithStoreMock(t)
|
||||
defer th.TearDown()
|
||||
|
||||
@@ -14637,6 +14637,23 @@ func (a *OpenTracingAppLayer) SendPaymentFailedEmail(failedPayment *model.Failed
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) SendTestPushNotification(deviceID string) string {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendTestPushNotification")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store.SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.SendTestPushNotification(deviceID)
|
||||
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) ServeInterPluginRequest(w http.ResponseWriter, r *http.Request, sourcePluginId string, destinationPluginId string) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ServeInterPluginRequest")
|
||||
|
||||
@@ -17,6 +17,7 @@ const (
|
||||
PushTypeClear = "clear"
|
||||
PushTypeUpdateBadge = "update_badge"
|
||||
PushTypeSession = "session"
|
||||
PushTypeTest = "test"
|
||||
PushMessageV2 = "v2"
|
||||
|
||||
PushSoundNone = "none"
|
||||
|
||||
Ссылка в новой задаче
Block a user