add test notification endpoint

This commit is contained in:
Andre Medeiros 2021-07-26 13:05:09 -04:00
parent 1249f54bf2
commit 0d296a672e
4 changed files with 84 additions and 1 deletions

1
go.mod
View file

@ -7,6 +7,7 @@ require (
github.com/DataDog/datadog-go v4.8.1+incompatible github.com/DataDog/datadog-go v4.8.1+incompatible
github.com/Microsoft/go-winio v0.5.0 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/adjust/rmq/v4 v4.0.1 github.com/adjust/rmq/v4 v4.0.1
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/go-co-op/gocron v1.6.2 github.com/go-co-op/gocron v1.6.2
github.com/go-redis/redis/v8 v8.11.0 github.com/go-redis/redis/v8 v8.11.0
github.com/heroku/x v0.0.31 github.com/heroku/x v0.0.31

2
go.sum
View file

@ -112,6 +112,8 @@ github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fp
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=

View file

@ -9,6 +9,7 @@ import (
"github.com/DataDog/datadog-go/statsd" "github.com/DataDog/datadog-go/statsd"
"github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/pgx/v4/pgxpool"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/sideshow/apns2/token"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/christianselig/apollo-backend/internal/data" "github.com/christianselig/apollo-backend/internal/data"
@ -21,6 +22,7 @@ type api struct {
db *pgxpool.Pool db *pgxpool.Pool
reddit *reddit.Client reddit *reddit.Client
models *data.Models models *data.Models
apns *token.Token
} }
func NewAPI(ctx context.Context, logger *logrus.Logger, statsd *statsd.Client, db *pgxpool.Pool) *api { func NewAPI(ctx context.Context, logger *logrus.Logger, statsd *statsd.Client, db *pgxpool.Pool) *api {
@ -31,9 +33,23 @@ func NewAPI(ctx context.Context, logger *logrus.Logger, statsd *statsd.Client, d
16, 16,
) )
var apns *token.Token
{
authKey, err := token.AuthKeyFromFile(os.Getenv("APPLE_KEY_PATH"))
if err != nil {
panic(err)
}
apns = &token.Token{
AuthKey: authKey,
KeyID: os.Getenv("APPLE_KEY_ID"),
TeamID: os.Getenv("APPLE_TEAM_ID"),
}
}
models := data.NewModels(ctx, db) models := data.NewModels(ctx, db)
return &api{logger, statsd, db, reddit, models} return &api{logger, statsd, db, reddit, models, apns}
} }
func (a *api) Server(port int) *http.Server { func (a *api) Server(port int) *http.Server {
@ -49,6 +65,7 @@ func (a *api) Routes() *httprouter.Router {
router.GET("/v1/health", a.healthCheckHandler) router.GET("/v1/health", a.healthCheckHandler)
router.POST("/v1/device", a.upsertDeviceHandler) router.POST("/v1/device", a.upsertDeviceHandler)
router.POST("/v1/device/test", a.testDeviceHandler)
router.POST("/v1/device/:apns/account", a.upsertAccountHandler) router.POST("/v1/device/:apns/account", a.upsertAccountHandler)
return router return router

View file

@ -1,10 +1,16 @@
package api package api
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt"
"net/http" "net/http"
"github.com/dustin/go-humanize/english"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/sideshow/apns2"
"github.com/sideshow/apns2/payload"
"github.com/sirupsen/logrus"
"github.com/christianselig/apollo-backend/internal/data" "github.com/christianselig/apollo-backend/internal/data"
) )
@ -23,3 +29,60 @@ func (a *api) upsertDeviceHandler(w http.ResponseWriter, r *http.Request, _ http
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }
func (a *api) testDeviceHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
ctx := context.Background()
d, err := a.models.Devices.GetByAPNSToken(ps.ByName("apns"))
if err != nil {
a.logger.WithFields(logrus.Fields{
"err": err,
}).Info("failed fetching device from database")
a.errorResponse(w, r, 500, err.Error())
return
}
stmt := `
SELECT username
FROM accounts
INNER JOIN devices_accounts ON devices.account_id = accounts.id
WHERE devices_accounts.device = $1`
rows, err := a.db.Query(ctx, stmt, d.ID)
if err != nil {
a.logger.WithFields(logrus.Fields{
"apns": ps.ByName("apns"),
"err": err,
}).Error("failed to fetch device accounts")
return
}
defer rows.Close()
var users []string
for rows.Next() {
var user string
rows.Scan(&user)
users = append(users, user)
}
body := fmt.Sprintf("Active usernames are: %s", english.OxfordWordSeries(users, "and"))
notification := &apns2.Notification{}
notification.Topic = "com.christianselig.Apollo"
notification.Payload = payload.
NewPayload().
Category("test-notification").
AlertBody(body)
client := apns2.NewTokenClient(a.apns)
if !d.Sandbox {
client = client.Production()
}
if _, err := client.Push(notification); err != nil {
a.logger.WithFields(logrus.Fields{
"err": err,
}).Info("failed to send test notification")
a.errorResponse(w, r, 500, err.Error())
return
}
w.WriteHeader(http.StatusOK)
}