Tests[TestSendSimpleMessageJSON]
This commit is contained in:
parent
0ff1188c3d
commit
62d7df9710
@ -31,7 +31,7 @@ docker: build
|
||||
.PHONY: swagger
|
||||
swagger:
|
||||
which swag || go install github.com/swaggo/swag/cmd/swag@latest
|
||||
swag init -generalInfo api/router.go --output ./swagger/ --outputTypes "json,yaml"
|
||||
swag init -generalInfo api/router.go --propertyStrategy snakecase --output ./swagger/ --outputTypes "json,yaml"
|
||||
|
||||
run-docker-local: docker
|
||||
mkdir -p .run-data
|
||||
|
16
server/api/apihighlight/highlights.go
Normal file
16
server/api/apihighlight/highlights.go
Normal file
@ -0,0 +1,16 @@
|
||||
package apihighlight
|
||||
|
||||
type ErrHighlight int
|
||||
|
||||
//goland:noinspection GoSnakeCaseUsage
|
||||
const (
|
||||
NONE ErrHighlight = -1
|
||||
USER_ID ErrHighlight = 101
|
||||
USER_KEY ErrHighlight = 102
|
||||
TITLE ErrHighlight = 103
|
||||
CONTENT ErrHighlight = 104
|
||||
PRIORITY ErrHighlight = 105
|
||||
CHANNEL ErrHighlight = 106
|
||||
SENDER_NAME ErrHighlight = 107
|
||||
USER_MESSAGE_ID ErrHighlight = 108
|
||||
)
|
@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
hl "blackforestbytes.com/simplecloudnotifier/api/apihighlight"
|
||||
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
|
||||
"blackforestbytes.com/simplecloudnotifier/db"
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
@ -38,8 +39,8 @@ func NewMessageHandler(app *logic.Application) MessageHandler {
|
||||
// @Description All parameter can be set via query-parameter or form-data body. Only UserID, UserKey and Title are required
|
||||
// @Tags External
|
||||
//
|
||||
// @Param query_data query handler.SendMessageCompat.query false " "
|
||||
// @Param form_data formData handler.SendMessageCompat.form false " "
|
||||
// @Param query_data query handler.SendMessageCompat.combined false " "
|
||||
// @Param form_data formData handler.SendMessageCompat.combined false " "
|
||||
//
|
||||
// @Success 200 {object} handler.sendMessageInternal.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
@ -49,7 +50,7 @@ func NewMessageHandler(app *logic.Application) MessageHandler {
|
||||
//
|
||||
// @Router /send.php [POST]
|
||||
func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
|
||||
type query struct {
|
||||
type combined struct {
|
||||
UserID *models.UserID `json:"user_id" form:"user_id"`
|
||||
UserKey *string `json:"user_key" form:"user_key"`
|
||||
Title *string `json:"title" form:"title"`
|
||||
@ -58,18 +59,9 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
|
||||
UserMessageID *string `json:"msg_id" form:"msg_id"`
|
||||
SendTimestamp *float64 `json:"timestamp" form:"timestamp"`
|
||||
}
|
||||
type form struct {
|
||||
UserID *models.UserID `form:"user_id"`
|
||||
UserKey *string `form:"user_key"`
|
||||
Title *string `form:"title"`
|
||||
Content *string `form:"content"`
|
||||
Priority *int `form:"priority"`
|
||||
UserMessageID *string `form:"msg_id"`
|
||||
SendTimestamp *float64 `form:"timestamp"`
|
||||
}
|
||||
|
||||
var f form
|
||||
var q query
|
||||
var f combined
|
||||
var q combined
|
||||
ctx, errResp := h.app.StartRequest(g, nil, &q, nil, &f)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
@ -88,9 +80,9 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Description All parameter can be set via query-parameter or the json body. Only UserID, UserKey and Title are required
|
||||
// @Tags External
|
||||
//
|
||||
// @Param query_data query handler.SendMessage.query false " "
|
||||
// @Param post_body body handler.SendMessage.body false " "
|
||||
// @Param form_body formData handler.SendMessage.body false " "
|
||||
// @Param query_data query handler.SendMessage.combined false " "
|
||||
// @Param post_body body handler.SendMessage.combined false " "
|
||||
// @Param form_body formData handler.SendMessage.combined false " "
|
||||
//
|
||||
// @Success 200 {object} handler.sendMessageInternal.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
@ -101,46 +93,22 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router / [POST]
|
||||
// @Router /send [POST]
|
||||
func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
type query struct {
|
||||
UserID *models.UserID `json:"user_id" form:"user_id"`
|
||||
UserKey *string `json:"user_key" form:"user_key"`
|
||||
Channel *string `json:"channel" form:"channel"`
|
||||
ChanKey *string `json:"chan_key" form:"chan_key"`
|
||||
Title *string `json:"title" form:"title"`
|
||||
Content *string `json:"content" form:"content"`
|
||||
Priority *int `json:"priority" form:"priority"`
|
||||
UserMessageID *string `json:"msg_id" form:"msg_id"`
|
||||
SendTimestamp *float64 `json:"timestamp" form:"timestamp"`
|
||||
SenderName *string `json:"sender_name" form:"sender_name"`
|
||||
}
|
||||
type body struct {
|
||||
UserID *models.UserID `json:"user_id"`
|
||||
UserKey *string `json:"user_key"`
|
||||
Channel *string `json:"channel"`
|
||||
ChanKey *string `json:"chan_key"`
|
||||
Title *string `json:"title"`
|
||||
Content *string `json:"content"`
|
||||
Priority *int `json:"priority"`
|
||||
UserMessageID *string `json:"msg_id"`
|
||||
SendTimestamp *float64 `json:"timestamp"`
|
||||
SenderName *string `json:"sender_name"`
|
||||
}
|
||||
type form struct {
|
||||
UserID *models.UserID `form:"user_id"`
|
||||
UserKey *string `form:"user_key"`
|
||||
Channel *string `form:"channel"`
|
||||
ChanKey *string `form:"chan_key"`
|
||||
Title *string `form:"title"`
|
||||
Content *string `form:"content"`
|
||||
Priority *int `form:"priority"`
|
||||
UserMessageID *string `form:"msg_id"`
|
||||
SendTimestamp *float64 `form:"timestamp"`
|
||||
SenderName *string `form:"sender_name"`
|
||||
type combined struct {
|
||||
UserID *models.UserID `json:"user_id" form:"user_id" example:"7725" `
|
||||
UserKey *string `json:"user_key" form:"user_key" example:"P3TNH8mvv14fm" `
|
||||
Channel *string `json:"channel" form:"channel" example:"test" `
|
||||
ChanKey *string `json:"chan_key" form:"chan_key" example:"qhnUbKcLgp6tg" `
|
||||
Title *string `json:"title" form:"title" example:"Hello World" `
|
||||
Content *string `json:"content" form:"content" example:"This is a message" `
|
||||
Priority *int `json:"priority" form:"priority" example:"1" enums:"0,1,2" `
|
||||
UserMessageID *string `json:"msg_id" form:"msg_id" example:"db8b0e6a-a08c-4646" `
|
||||
SendTimestamp *float64 `json:"timestamp" form:"timestamp" example:"1669824037" `
|
||||
SenderName *string `json:"sender_name" form:"sender_name" example:"example-server" `
|
||||
}
|
||||
|
||||
var b body
|
||||
var q query
|
||||
var f form
|
||||
var b combined
|
||||
var q combined
|
||||
var f combined
|
||||
ctx, errResp := h.app.StartRequest(g, nil, &q, &b, &f)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
@ -175,30 +143,30 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
}
|
||||
|
||||
if UserID == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.MISSING_UID, 101, "Missing parameter [[user_id]]", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.MISSING_UID, hl.USER_ID, "Missing parameter [[user_id]]", nil)
|
||||
}
|
||||
if UserKey == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.MISSING_TOK, 102, "Missing parameter [[user_token]]", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.MISSING_TOK, hl.USER_KEY, "Missing parameter [[user_token]]", nil)
|
||||
}
|
||||
if Title == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.MISSING_TITLE, 103, "Missing parameter [[title]]", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.MISSING_TITLE, hl.TITLE, "Missing parameter [[title]]", nil)
|
||||
}
|
||||
if SendTimestamp != nil && mathext.Abs(*SendTimestamp-float64(time.Now().Unix())) > (24*time.Hour).Seconds() {
|
||||
return ginresp.SendAPIError(g, 400, apierr.TIMESTAMP_OUT_OF_RANGE, -1, "The timestamp mus be within 24 hours of now()", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.TIMESTAMP_OUT_OF_RANGE, hl.NONE, "The timestamp mus be within 24 hours of now()", nil)
|
||||
}
|
||||
if Priority != nil && (*Priority != 0 && *Priority != 1 && *Priority != 2) {
|
||||
return ginresp.SendAPIError(g, 400, apierr.INVALID_PRIO, 105, "Invalid priority", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.INVALID_PRIO, hl.PRIORITY, "Invalid priority", nil)
|
||||
}
|
||||
if len(*Title) == 0 {
|
||||
return ginresp.SendAPIError(g, 400, apierr.NO_TITLE, 103, "No title specified", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.NO_TITLE, hl.TITLE, "No title specified", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, *UserID)
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, -1, "User not found", nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found", nil)
|
||||
}
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query user", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query user", err)
|
||||
}
|
||||
|
||||
channelName := user.DefaultChannel()
|
||||
@ -207,25 +175,25 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
}
|
||||
|
||||
if len(*Title) > user.MaxTitleLength() {
|
||||
return ginresp.SendAPIError(g, 400, apierr.TITLE_TOO_LONG, 103, fmt.Sprintf("Title too long (max %d characters)", user.MaxTitleLength()), nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.TITLE_TOO_LONG, hl.TITLE, fmt.Sprintf("Title too long (max %d characters)", user.MaxTitleLength()), nil)
|
||||
}
|
||||
if Content != nil && len(*Content) > user.MaxContentLength() {
|
||||
return ginresp.SendAPIError(g, 400, apierr.CONTENT_TOO_LONG, 104, fmt.Sprintf("Content too long (%d characters; max := %d characters)", len(*Content), user.MaxContentLength()), nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.CONTENT_TOO_LONG, hl.CONTENT, fmt.Sprintf("Content too long (%d characters; max := %d characters)", len(*Content), user.MaxContentLength()), nil)
|
||||
}
|
||||
if len(channelName) > user.MaxChannelNameLength() {
|
||||
return ginresp.SendAPIError(g, 400, apierr.CONTENT_TOO_LONG, 106, fmt.Sprintf("Channel too long (max %d characters)", user.MaxChannelNameLength()), nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.CONTENT_TOO_LONG, hl.CHANNEL, fmt.Sprintf("Channel too long (max %d characters)", user.MaxChannelNameLength()), nil)
|
||||
}
|
||||
if SenderName != nil && len(*SenderName) > user.MaxSenderName() {
|
||||
return ginresp.SendAPIError(g, 400, apierr.SENDERNAME_TOO_LONG, 107, fmt.Sprintf("SenderName too long (max %d characters)", user.MaxSenderName()), nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.SENDERNAME_TOO_LONG, hl.SENDER_NAME, fmt.Sprintf("SenderName too long (max %d characters)", user.MaxSenderName()), nil)
|
||||
}
|
||||
if UserMessageID != nil && len(*UserMessageID) > user.MaxUserMessageID() {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USR_MSG_ID_TOO_LONG, -1, fmt.Sprintf("MessageID too long (max %d characters)", user.MaxUserMessageID()), nil)
|
||||
return ginresp.SendAPIError(g, 400, apierr.USR_MSG_ID_TOO_LONG, hl.USER_MESSAGE_ID, fmt.Sprintf("MessageID too long (max %d characters)", user.MaxUserMessageID()), nil)
|
||||
}
|
||||
|
||||
if UserMessageID != nil {
|
||||
msg, err := h.database.GetMessageByUserMessageID(ctx, *UserMessageID)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query existing message", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query existing message", err)
|
||||
}
|
||||
if msg != nil {
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||
@ -244,12 +212,28 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
}
|
||||
|
||||
if user.QuotaRemainingToday() <= 0 {
|
||||
return ginresp.SendAPIError(g, 403, apierr.QUOTA_REACHED, -1, fmt.Sprintf("Daily quota reached (%d)", user.QuotaPerDay()), nil)
|
||||
return ginresp.SendAPIError(g, 403, apierr.QUOTA_REACHED, hl.NONE, fmt.Sprintf("Daily quota reached (%d)", user.QuotaPerDay()), nil)
|
||||
}
|
||||
|
||||
channel, err := h.app.GetOrCreateChannel(ctx, *UserID, channelName)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query/create channel", err)
|
||||
var channel models.Channel
|
||||
if ChanKey != nil {
|
||||
// foreign channel (+ channel send-key)
|
||||
|
||||
foreignChan, err := h.database.GetChannelByNameAndSendKey(ctx, channelName, *ChanKey)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query (foreign) channel", err)
|
||||
}
|
||||
if foreignChan == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.CHANNEL_NOT_FOUND, hl.CHANNEL, "(Foreign) Channel not found", err)
|
||||
}
|
||||
channel = *foreignChan
|
||||
} else {
|
||||
// own channel
|
||||
|
||||
channel, err = h.app.GetOrCreateChannel(ctx, *UserID, channelName)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query/create (owned) channel", err)
|
||||
}
|
||||
}
|
||||
|
||||
selfChanAdmin := *UserID == channel.OwnerUserID && *UserKey == user.AdminKey
|
||||
@ -257,7 +241,7 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
forgChanSend := *UserID != channel.OwnerUserID && ChanKey != nil && *ChanKey == channel.SendKey
|
||||
|
||||
if !selfChanAdmin && !selfChanSend && !forgChanSend {
|
||||
return ginresp.SendAPIError(g, 401, apierr.USER_AUTH_FAILED, 102, fmt.Sprintf("Daily quota reached (%d)", user.QuotaPerDay()), nil)
|
||||
return ginresp.SendAPIError(g, 401, apierr.USER_AUTH_FAILED, hl.USER_KEY, "You are not authorized for this action", nil)
|
||||
}
|
||||
|
||||
var sendTimestamp *time.Time = nil
|
||||
@ -271,28 +255,28 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
|
||||
msg, err := h.database.CreateMessage(ctx, *UserID, channel, sendTimestamp, *Title, Content, priority, UserMessageID, clientIP, SenderName)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to create message in db", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create message in db", err)
|
||||
}
|
||||
|
||||
subscriptions, err := h.database.ListSubscriptionsByChannel(ctx, channel.ChannelID)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query subscriptions", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query subscriptions", err)
|
||||
}
|
||||
|
||||
err = h.database.IncUserMessageCounter(ctx, user)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to inc user msg-counter", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to inc user msg-counter", err)
|
||||
}
|
||||
|
||||
err = h.database.IncChannelMessageCounter(ctx, channel)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to inc channel msg-counter", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to inc channel msg-counter", err)
|
||||
}
|
||||
|
||||
for _, sub := range subscriptions {
|
||||
clients, err := h.database.ListClients(ctx, sub.SubscriberUserID)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query clients", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query clients", err)
|
||||
}
|
||||
|
||||
if !sub.Confirmed {
|
||||
@ -305,12 +289,12 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
if err != nil {
|
||||
_, err = h.database.CreateRetryDelivery(ctx, client, msg)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to create delivery", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create delivery", err)
|
||||
}
|
||||
} else {
|
||||
_, err = h.database.CreateSuccessDelivery(ctx, client, msg, *fcmDelivID)
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to create delivery", err)
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create delivery", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,10 +38,10 @@ func NewRouter(app *logic.Application) *Router {
|
||||
// @description API for SCN
|
||||
// @host scn.blackforestbytes.com
|
||||
//
|
||||
// @tag.name Common
|
||||
// @tag.name External
|
||||
// @tag.name API-v1
|
||||
// @tag.name API-v2
|
||||
// @tag.name Common
|
||||
//
|
||||
// @BasePath /
|
||||
func (r *Router) Init(e *gin.Engine) {
|
||||
|
@ -3,6 +3,7 @@ package ginresp
|
||||
import (
|
||||
scn "blackforestbytes.com/simplecloudnotifier"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apihighlight"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
@ -73,7 +74,7 @@ func APIError(g *gin.Context, status int, errorid apierr.APIError, msg string, e
|
||||
return createApiError(g, "APIError", status, errorid, 0, msg, e)
|
||||
}
|
||||
|
||||
func SendAPIError(g *gin.Context, status int, errorid apierr.APIError, highlight int, msg string, e error) HTTPResponse {
|
||||
func SendAPIError(g *gin.Context, status int, errorid apierr.APIError, highlight apihighlight.ErrHighlight, msg string, e error) HTTPResponse {
|
||||
return createApiError(g, "SendAPIError", status, errorid, highlight, msg, e)
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ func NotImplemented(g *gin.Context) HTTPResponse {
|
||||
return createApiError(g, "NotImplemented", 500, apierr.UNDEFINED, 0, "Not Implemented", nil)
|
||||
}
|
||||
|
||||
func createApiError(g *gin.Context, ident string, status int, errorid apierr.APIError, highlight int, msg string, e error) HTTPResponse {
|
||||
func createApiError(g *gin.Context, ident string, status int, errorid apierr.APIError, highlight apihighlight.ErrHighlight, msg string, e error) HTTPResponse {
|
||||
reqUri := ""
|
||||
if g != nil && g.Request != nil {
|
||||
reqUri = g.Request.Method + " :: " + g.Request.RequestURI
|
||||
@ -89,7 +90,7 @@ func createApiError(g *gin.Context, ident string, status int, errorid apierr.API
|
||||
|
||||
log.Error().
|
||||
Int("errorid", int(errorid)).
|
||||
Int("highlight", highlight).
|
||||
Int("highlight", int(highlight)).
|
||||
Str("uri", reqUri).
|
||||
AnErr("err", e).
|
||||
Stack().
|
||||
@ -101,7 +102,7 @@ func createApiError(g *gin.Context, ident string, status int, errorid apierr.API
|
||||
data: apiError{
|
||||
Success: false,
|
||||
Error: int(errorid),
|
||||
ErrorHighlight: highlight,
|
||||
ErrorHighlight: int(highlight),
|
||||
Message: msg,
|
||||
RawError: fmt.Sprintf("%+v", e),
|
||||
Trace: string(debug.Stack()),
|
||||
@ -113,7 +114,7 @@ func createApiError(g *gin.Context, ident string, status int, errorid apierr.API
|
||||
data: apiError{
|
||||
Success: false,
|
||||
Error: int(errorid),
|
||||
ErrorHighlight: highlight,
|
||||
ErrorHighlight: int(highlight),
|
||||
Message: msg,
|
||||
},
|
||||
}
|
||||
|
@ -28,6 +28,28 @@ func (db *Database) GetChannelByName(ctx TxContext, userid models.UserID, chanNa
|
||||
return &channel, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetChannelByNameAndSendKey(ctx TxContext, chanName string, sendKey string) (*models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.QueryContext(ctx, "SELECT * FROM channels WHERE name = ? OR send_key = ? LIMIT 1", chanName, sendKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
channel, err := models.DecodeChannel(rows)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &channel, nil
|
||||
}
|
||||
|
||||
func (db *Database) CreateChannel(ctx TxContext, userid models.UserID, name string, subscribeKey string, sendKey string) (models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
|
@ -28,7 +28,7 @@ type Application struct {
|
||||
Config scn.Config
|
||||
Gin *gin.Engine
|
||||
Database *db.Database
|
||||
Firebase push.NotificationClient
|
||||
Pusher push.NotificationClient
|
||||
AndroidPublisher google.AndroidPublisherClient
|
||||
Jobs []Job
|
||||
stopChan chan bool
|
||||
@ -45,7 +45,7 @@ func NewApp(db *db.Database) *Application {
|
||||
func (app *Application) Init(cfg scn.Config, g *gin.Engine, fb push.NotificationClient, apc google.AndroidPublisherClient, jobs []Job) {
|
||||
app.Config = cfg
|
||||
app.Gin = g
|
||||
app.Firebase = fb
|
||||
app.Pusher = fb
|
||||
app.AndroidPublisher = apc
|
||||
app.Jobs = jobs
|
||||
}
|
||||
@ -314,7 +314,7 @@ func (app *Application) NormalizeUsername(v string) string {
|
||||
|
||||
func (app *Application) DeliverMessage(ctx context.Context, client models.Client, msg models.Message) (*string, error) {
|
||||
if client.FCMToken != nil {
|
||||
fcmDelivID, err := app.Firebase.SendNotification(ctx, client, msg)
|
||||
fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg)
|
||||
if err != nil {
|
||||
log.Warn().Int64("SCNMessageID", msg.SCNMessageID.IntID()).Int64("ClientID", client.ClientID.IntID()).Err(err).Msg("FCM Delivery failed")
|
||||
return nil, err
|
||||
|
@ -13,13 +13,17 @@ type SinkData struct {
|
||||
}
|
||||
|
||||
type TestSink struct {
|
||||
data []SinkData
|
||||
Data []SinkData
|
||||
}
|
||||
|
||||
func NewTestSink() NotificationClient {
|
||||
return &TestSink{}
|
||||
}
|
||||
|
||||
func (d *TestSink) Last() SinkData {
|
||||
return d.Data[len(d.Data)-1]
|
||||
}
|
||||
|
||||
func (d *TestSink) SendNotification(ctx context.Context, client models.Client, msg models.Message) (string, error) {
|
||||
id, err := langext.NewHexUUID()
|
||||
if err != nil {
|
||||
@ -28,7 +32,7 @@ func (d *TestSink) SendNotification(ctx context.Context, client models.Client, m
|
||||
|
||||
key := "TestSink[" + id + "]"
|
||||
|
||||
d.data = append(d.data, SinkData{
|
||||
d.Data = append(d.Data, SinkData{
|
||||
Message: msg,
|
||||
Client: client,
|
||||
})
|
||||
|
@ -19,51 +19,66 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"example": "qhnUbKcLgp6tg",
|
||||
"name": "chan_key",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "test",
|
||||
"name": "channel",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "This is a message",
|
||||
"name": "content",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "db8b0e6a-a08c-4646",
|
||||
"name": "msg_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "integer",
|
||||
"example": 1,
|
||||
"name": "priority",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "example-server",
|
||||
"name": "sender_name",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"example": 1669824037,
|
||||
"name": "timestamp",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "Hello World",
|
||||
"name": "title",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"name": "user_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "P3TNH8mvv14fm",
|
||||
"name": "user_key",
|
||||
"in": "query"
|
||||
},
|
||||
@ -72,56 +87,71 @@
|
||||
"name": "post_body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.SendMessage.body"
|
||||
"$ref": "#/definitions/handler.SendMessage.combined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "qhnUbKcLgp6tg",
|
||||
"name": "chan_key",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "test",
|
||||
"name": "channel",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "This is a message",
|
||||
"name": "content",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "db8b0e6a-a08c-4646",
|
||||
"name": "msg_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "integer",
|
||||
"example": 1,
|
||||
"name": "priority",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "example-server",
|
||||
"name": "sender_name",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"example": 1669824037,
|
||||
"name": "timestamp",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "Hello World",
|
||||
"name": "title",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "P3TNH8mvv14fm",
|
||||
"name": "user_key",
|
||||
"in": "formData"
|
||||
}
|
||||
@ -1959,51 +1989,66 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"example": "qhnUbKcLgp6tg",
|
||||
"name": "chan_key",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "test",
|
||||
"name": "channel",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "This is a message",
|
||||
"name": "content",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "db8b0e6a-a08c-4646",
|
||||
"name": "msg_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "integer",
|
||||
"example": 1,
|
||||
"name": "priority",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "example-server",
|
||||
"name": "sender_name",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"example": 1669824037,
|
||||
"name": "timestamp",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "Hello World",
|
||||
"name": "title",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"name": "user_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "P3TNH8mvv14fm",
|
||||
"name": "user_key",
|
||||
"in": "query"
|
||||
},
|
||||
@ -2012,56 +2057,71 @@
|
||||
"name": "post_body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.SendMessage.body"
|
||||
"$ref": "#/definitions/handler.SendMessage.combined"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "qhnUbKcLgp6tg",
|
||||
"name": "chan_key",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "test",
|
||||
"name": "channel",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "This is a message",
|
||||
"name": "content",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "db8b0e6a-a08c-4646",
|
||||
"name": "msg_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"type": "integer",
|
||||
"example": 1,
|
||||
"name": "priority",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "example-server",
|
||||
"name": "sender_name",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"example": 1669824037,
|
||||
"name": "timestamp",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "Hello World",
|
||||
"name": "title",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"example": "P3TNH8mvv14fm",
|
||||
"name": "user_key",
|
||||
"in": "formData"
|
||||
}
|
||||
@ -2149,6 +2209,11 @@
|
||||
"name": "content",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "msg_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "priority",
|
||||
@ -2156,7 +2221,7 @@
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"name": "sendTimestamp",
|
||||
"name": "timestamp",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
@ -2166,17 +2231,12 @@
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "userID",
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "userKey",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "userMessageID",
|
||||
"name": "user_key",
|
||||
"in": "formData"
|
||||
}
|
||||
],
|
||||
@ -2297,13 +2357,13 @@
|
||||
"type": "object",
|
||||
"required": [
|
||||
"channel",
|
||||
"channelOwnerUserID"
|
||||
"channel_owner_user_id"
|
||||
],
|
||||
"properties": {
|
||||
"channel": {
|
||||
"type": "string"
|
||||
},
|
||||
"channelOwnerUserID": {
|
||||
"channel_owner_user_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
@ -2529,38 +2589,53 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"handler.SendMessage.body": {
|
||||
"handler.SendMessage.combined": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chan_key": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "qhnUbKcLgp6tg"
|
||||
},
|
||||
"channel": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
},
|
||||
"content": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "This is a message"
|
||||
},
|
||||
"msg_id": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "db8b0e6a-a08c-4646"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer"
|
||||
"type": "integer",
|
||||
"enum": [
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
"example": 1
|
||||
},
|
||||
"sender_name": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "example-server"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "number"
|
||||
"type": "number",
|
||||
"example": 1669824037
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "Hello World"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
"type": "integer",
|
||||
"example": 7725
|
||||
},
|
||||
"user_key": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"example": "P3TNH8mvv14fm"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2948,9 +3023,6 @@
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "Common"
|
||||
},
|
||||
{
|
||||
"name": "External"
|
||||
},
|
||||
@ -2959,6 +3031,9 @@
|
||||
},
|
||||
{
|
||||
"name": "API-v2"
|
||||
},
|
||||
{
|
||||
"name": "Common"
|
||||
}
|
||||
]
|
||||
}
|
@ -55,11 +55,11 @@ definitions:
|
||||
properties:
|
||||
channel:
|
||||
type: string
|
||||
channelOwnerUserID:
|
||||
channel_owner_user_id:
|
||||
type: integer
|
||||
required:
|
||||
- channel
|
||||
- channelOwnerUserID
|
||||
- channel_owner_user_id
|
||||
type: object
|
||||
handler.CreateUser.body:
|
||||
properties:
|
||||
@ -204,27 +204,41 @@ definitions:
|
||||
success:
|
||||
type: boolean
|
||||
type: object
|
||||
handler.SendMessage.body:
|
||||
handler.SendMessage.combined:
|
||||
properties:
|
||||
chan_key:
|
||||
example: qhnUbKcLgp6tg
|
||||
type: string
|
||||
channel:
|
||||
example: test
|
||||
type: string
|
||||
content:
|
||||
example: This is a message
|
||||
type: string
|
||||
msg_id:
|
||||
example: db8b0e6a-a08c-4646
|
||||
type: string
|
||||
priority:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
example: 1
|
||||
type: integer
|
||||
sender_name:
|
||||
example: example-server
|
||||
type: string
|
||||
timestamp:
|
||||
example: 1669824037
|
||||
type: number
|
||||
title:
|
||||
example: Hello World
|
||||
type: string
|
||||
user_id:
|
||||
example: 7725
|
||||
type: integer
|
||||
user_key:
|
||||
example: P3TNH8mvv14fm
|
||||
type: string
|
||||
type: object
|
||||
handler.Sleep.response:
|
||||
@ -490,69 +504,97 @@ paths:
|
||||
description: All parameter can be set via query-parameter or the json body.
|
||||
Only UserID, UserKey and Title are required
|
||||
parameters:
|
||||
- in: query
|
||||
- example: qhnUbKcLgp6tg
|
||||
in: query
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: query
|
||||
- example: test
|
||||
in: query
|
||||
name: channel
|
||||
type: string
|
||||
- in: query
|
||||
- example: This is a message
|
||||
in: query
|
||||
name: content
|
||||
type: string
|
||||
- in: query
|
||||
- example: db8b0e6a-a08c-4646
|
||||
in: query
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: query
|
||||
- enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
example: 1
|
||||
in: query
|
||||
name: priority
|
||||
type: integer
|
||||
- in: query
|
||||
- example: example-server
|
||||
in: query
|
||||
name: sender_name
|
||||
type: string
|
||||
- in: query
|
||||
- example: 1669824037
|
||||
in: query
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: query
|
||||
- example: Hello World
|
||||
in: query
|
||||
name: title
|
||||
type: string
|
||||
- in: query
|
||||
- example: 7725
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: query
|
||||
- example: P3TNH8mvv14fm
|
||||
in: query
|
||||
name: user_key
|
||||
type: string
|
||||
- description: ' '
|
||||
in: body
|
||||
name: post_body
|
||||
schema:
|
||||
$ref: '#/definitions/handler.SendMessage.body'
|
||||
- in: formData
|
||||
$ref: '#/definitions/handler.SendMessage.combined'
|
||||
- example: qhnUbKcLgp6tg
|
||||
in: formData
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: formData
|
||||
- example: test
|
||||
in: formData
|
||||
name: channel
|
||||
type: string
|
||||
- in: formData
|
||||
- example: This is a message
|
||||
in: formData
|
||||
name: content
|
||||
type: string
|
||||
- in: formData
|
||||
- example: db8b0e6a-a08c-4646
|
||||
in: formData
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: formData
|
||||
- enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
example: 1
|
||||
in: formData
|
||||
name: priority
|
||||
type: integer
|
||||
- in: formData
|
||||
- example: example-server
|
||||
in: formData
|
||||
name: sender_name
|
||||
type: string
|
||||
- in: formData
|
||||
- example: 1669824037
|
||||
in: formData
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: formData
|
||||
- example: Hello World
|
||||
in: formData
|
||||
name: title
|
||||
type: string
|
||||
- in: formData
|
||||
- example: 7725
|
||||
in: formData
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: formData
|
||||
- example: P3TNH8mvv14fm
|
||||
in: formData
|
||||
name: user_key
|
||||
type: string
|
||||
responses:
|
||||
@ -1801,69 +1843,97 @@ paths:
|
||||
description: All parameter can be set via query-parameter or the json body.
|
||||
Only UserID, UserKey and Title are required
|
||||
parameters:
|
||||
- in: query
|
||||
- example: qhnUbKcLgp6tg
|
||||
in: query
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: query
|
||||
- example: test
|
||||
in: query
|
||||
name: channel
|
||||
type: string
|
||||
- in: query
|
||||
- example: This is a message
|
||||
in: query
|
||||
name: content
|
||||
type: string
|
||||
- in: query
|
||||
- example: db8b0e6a-a08c-4646
|
||||
in: query
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: query
|
||||
- enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
example: 1
|
||||
in: query
|
||||
name: priority
|
||||
type: integer
|
||||
- in: query
|
||||
- example: example-server
|
||||
in: query
|
||||
name: sender_name
|
||||
type: string
|
||||
- in: query
|
||||
- example: 1669824037
|
||||
in: query
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: query
|
||||
- example: Hello World
|
||||
in: query
|
||||
name: title
|
||||
type: string
|
||||
- in: query
|
||||
- example: 7725
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: query
|
||||
- example: P3TNH8mvv14fm
|
||||
in: query
|
||||
name: user_key
|
||||
type: string
|
||||
- description: ' '
|
||||
in: body
|
||||
name: post_body
|
||||
schema:
|
||||
$ref: '#/definitions/handler.SendMessage.body'
|
||||
- in: formData
|
||||
$ref: '#/definitions/handler.SendMessage.combined'
|
||||
- example: qhnUbKcLgp6tg
|
||||
in: formData
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: formData
|
||||
- example: test
|
||||
in: formData
|
||||
name: channel
|
||||
type: string
|
||||
- in: formData
|
||||
- example: This is a message
|
||||
in: formData
|
||||
name: content
|
||||
type: string
|
||||
- in: formData
|
||||
- example: db8b0e6a-a08c-4646
|
||||
in: formData
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: formData
|
||||
- enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
example: 1
|
||||
in: formData
|
||||
name: priority
|
||||
type: integer
|
||||
- in: formData
|
||||
- example: example-server
|
||||
in: formData
|
||||
name: sender_name
|
||||
type: string
|
||||
- in: formData
|
||||
- example: 1669824037
|
||||
in: formData
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: formData
|
||||
- example: Hello World
|
||||
in: formData
|
||||
name: title
|
||||
type: string
|
||||
- in: formData
|
||||
- example: 7725
|
||||
in: formData
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: formData
|
||||
- example: P3TNH8mvv14fm
|
||||
in: formData
|
||||
name: user_key
|
||||
type: string
|
||||
responses:
|
||||
@ -1921,23 +1991,23 @@ paths:
|
||||
- in: formData
|
||||
name: content
|
||||
type: string
|
||||
- in: formData
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: formData
|
||||
name: priority
|
||||
type: integer
|
||||
- in: formData
|
||||
name: sendTimestamp
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: formData
|
||||
name: title
|
||||
type: string
|
||||
- in: formData
|
||||
name: userID
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: formData
|
||||
name: userKey
|
||||
type: string
|
||||
- in: formData
|
||||
name: userMessageID
|
||||
name: user_key
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
@ -1965,7 +2035,7 @@ paths:
|
||||
- External
|
||||
swagger: "2.0"
|
||||
tags:
|
||||
- name: Common
|
||||
- name: External
|
||||
- name: API-v1
|
||||
- name: API-v2
|
||||
- name: Common
|
||||
|
88
server/test/message_test.go
Normal file
88
server/test/message_test.go
Normal file
@ -0,0 +1,88 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/push"
|
||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSendSimpleMessageJSON(t *testing.T) {
|
||||
ws, stop := tt.StartSimpleWebserver(t)
|
||||
defer stop()
|
||||
|
||||
pusher := ws.Pusher.(*push.TestSink)
|
||||
|
||||
baseUrl := "http://127.0.0.1:" + ws.Port
|
||||
|
||||
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
|
||||
"agent_model": "DUMMY_PHONE",
|
||||
"agent_version": "4X",
|
||||
"client_type": "ANDROID",
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"user_key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
})
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"user_key": readtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, 1311)
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
}
|
||||
|
||||
msgList1 := tt.RequestAuthGet[mglist](t, admintok, baseUrl, "/api/messages")
|
||||
tt.AssertEqual(t, "len(messages)", 1, len(msgList1.Messages))
|
||||
|
||||
msg1Get := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/messages/"+fmt.Sprintf("%v", msg1["scn_msg_id"]))
|
||||
tt.AssertEqual(t, "msg.title", "HelloWorld_001", msg1Get["title"])
|
||||
tt.AssertEqual(t, "msg.channel_name", "main", msg1Get["channel_name"])
|
||||
|
||||
}
|
||||
|
||||
//TODO message -> query
|
||||
//TODO message -> form
|
||||
//TODO overwrite order when all 3 are specified
|
||||
|
||||
//TODO send content
|
||||
//TODO sendername
|
||||
|
||||
//TODO trim too-long content
|
||||
|
||||
//TODO compat route
|
||||
|
||||
//TODO post to channel
|
||||
//TODO post to newly-created-channel
|
||||
//TODO post to foreign channel via send-key
|
||||
|
||||
//TODO usr_msg_id
|
||||
|
||||
//TODO quota exceed (+ quota counter)
|
||||
|
||||
//TODO invalid priority
|
||||
//TODO chan_naem too long
|
||||
//TODO chan_name normalization
|
||||
//TODO custom_timestamp
|
||||
//TODO invalid time
|
||||
//TODO title too long
|
||||
//TODO content too long
|
||||
|
||||
//TODO check message_counter + last_sent in channel
|
||||
//TODO check message_counter + last_sent in user
|
@ -22,8 +22,13 @@ func TestCreateUserNoClient(t *testing.T) {
|
||||
|
||||
uid := fmt.Sprintf("%v", r0["user_id"])
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
r1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/users/"+uid)
|
||||
tt.RequestAuthGetShouldFail(t, sendtok, baseUrl, "/api/users/"+uid, 401, apierr.USER_AUTH_FAILED)
|
||||
tt.RequestAuthGetShouldFail(t, "", baseUrl, "/api/users/"+uid, 401, apierr.USER_AUTH_FAILED)
|
||||
|
||||
r1 := tt.RequestAuthGet[gin.H](t, readtok, baseUrl, "/api/users/"+uid)
|
||||
|
||||
tt.AssertEqual(t, "uid", uid, fmt.Sprintf("%v", r1["user_id"]))
|
||||
tt.AssertEqual(t, "admin_key", admintok, r1["admin_key"])
|
||||
@ -214,6 +219,8 @@ func TestDeleteUser(t *testing.T) {
|
||||
|
||||
tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/users/"+uid)
|
||||
|
||||
tt.RequestAuthDeleteShouldFail(t, admintok, baseUrl, "/api/users/"+uid, nil, 401, apierr.USER_AUTH_FAILED)
|
||||
|
||||
tt.RequestAuthDelete[tt.Void](t, admintok, baseUrl, "/api/users/"+uid, nil)
|
||||
|
||||
tt.RequestAuthGetShouldFail(t, admintok, baseUrl, "/api/users/"+uid, 404, apierr.USER_NOT_FOUND)
|
||||
|
@ -55,6 +55,31 @@ func AssertEqual(t *testing.T, key string, expected any, actual any) {
|
||||
}
|
||||
}
|
||||
|
||||
func AssertStrRepEqual(t *testing.T, key string, expected any, actual any) {
|
||||
str1 := fmt.Sprintf("%v", expected)
|
||||
str2 := fmt.Sprintf("%v", actual)
|
||||
|
||||
if str1 != str2 {
|
||||
t.Errorf("Value [%s] differs (%T <-> %T):\n", key, expected, actual)
|
||||
|
||||
if strings.Contains(str1, "\n") {
|
||||
t.Errorf("Actual:\n~~~~~~~~~~~~~~~~\n%v\n~~~~~~~~~~~~~~~~\n\n", expected)
|
||||
} else {
|
||||
t.Errorf("Actual := \"%v\"\n", expected)
|
||||
}
|
||||
|
||||
if strings.Contains(str2, "\n") {
|
||||
t.Errorf("Expected:\n~~~~~~~~~~~~~~~~\n%v\n~~~~~~~~~~~~~~~~\n\n", actual)
|
||||
} else {
|
||||
t.Errorf("Expected := \"%v\"\n", actual)
|
||||
}
|
||||
|
||||
t.Error(string(debug.Stack()))
|
||||
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func AssertNotEqual(t *testing.T, key string, expected any, actual any) {
|
||||
if expected == actual {
|
||||
t.Errorf("Value [%s] does not differ (%T <-> %T):\n", key, expected, actual)
|
||||
|
@ -52,6 +52,38 @@ func RequestAuthDelete[TResult any](t *testing.T, akey string, baseURL string, u
|
||||
return RequestAny[TResult](t, akey, "DELETE", baseURL, urlSuffix, body)
|
||||
}
|
||||
|
||||
func RequestGetShouldFail(t *testing.T, baseURL string, urlSuffix string, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, "", "GET", baseURL, urlSuffix, nil, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestPostShouldFail(t *testing.T, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, "", "POST", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestPatchShouldFail(t *testing.T, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, "", "PATCH", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestDeleteShouldFail(t *testing.T, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, "", "DELETE", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthGetShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "GET", baseURL, urlSuffix, nil, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthPostShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "POST", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthPatchShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "PATCH", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthDeleteShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "DELETE", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAny[TResult any](t *testing.T, akey string, method string, baseURL string, urlSuffix string, body any) TResult {
|
||||
client := http.Client{}
|
||||
|
||||
@ -108,22 +140,6 @@ func RequestAny[TResult any](t *testing.T, akey string, method string, baseURL s
|
||||
return data
|
||||
}
|
||||
|
||||
func RequestAuthGetShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "GET", baseURL, urlSuffix, nil, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthPostShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "POST", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthPatchShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "PATCH", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthDeleteShouldFail(t *testing.T, akey string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
RequestAuthAnyShouldFail(t, akey, "DELETE", baseURL, urlSuffix, body, statusCode, errcode)
|
||||
}
|
||||
|
||||
func RequestAuthAnyShouldFail(t *testing.T, akey string, method string, baseURL string, urlSuffix string, body any, statusCode int, errcode apierr.APIError) {
|
||||
client := http.Client{}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user