Merge branch 'test/remove_userid_param'
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
hl "blackforestbytes.com/simplecloudnotifier/api/apihighlight"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||
@@ -8,13 +13,9 @@ import (
|
||||
primarydb "blackforestbytes.com/simplecloudnotifier/db/impl/primary"
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/dataext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/ginext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type CompatHandler struct {
|
||||
@@ -90,7 +91,7 @@ func (h CompatHandler) SendMessage(pctx ginext.PreContext) ginext.HTTPResponse {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
okResp, errResp := h.app.SendMessage(g, ctx, langext.Ptr(models.UserID(*newid)), data.UserKey, nil, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp, nil)
|
||||
okResp, errResp := h.app.SendMessage(g, ctx, data.UserKey, nil, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp, nil)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
} else {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||
primarydb "blackforestbytes.com/simplecloudnotifier/db/impl/primary"
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"fmt"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/ginext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ExternalHandler struct {
|
||||
@@ -36,14 +37,13 @@ func NewExternalHandler(app *logic.Application) ExternalHandler {
|
||||
//
|
||||
// @Success 200 {object} handler.UptimeKuma.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
// @Failure 401 {object} ginresp.apiError "The user_id was not found or the user_key is wrong"
|
||||
// @Failure 401 {object} ginresp.apiError "The user_key is wrong"
|
||||
// @Failure 403 {object} ginresp.apiError "The user has exceeded its daily quota - wait 24 hours or upgrade your account"
|
||||
// @Failure 500 {object} ginresp.apiError "An internal server error occurred - try again later"
|
||||
//
|
||||
// @Router /external/v1/uptime-kuma [POST]
|
||||
func (h ExternalHandler) UptimeKuma(pctx ginext.PreContext) ginext.HTTPResponse {
|
||||
type query struct {
|
||||
UserID *models.UserID `form:"user_id" example:"7725"`
|
||||
KeyToken *string `form:"key" example:"P3TNH8mvv14fm"`
|
||||
Channel *string `form:"channel"`
|
||||
ChannelUp *string `form:"channel_up"`
|
||||
@@ -125,7 +125,7 @@ func (h ExternalHandler) UptimeKuma(pctx ginext.PreContext) ginext.HTTPResponse
|
||||
priority = q.PriorityDown
|
||||
}
|
||||
|
||||
okResp, errResp := h.app.SendMessage(g, ctx, q.UserID, q.KeyToken, channel, &title, &content, priority, nil, timestamp, q.SenderName)
|
||||
okResp, errResp := h.app.SendMessage(g, ctx, q.KeyToken, channel, &title, &content, priority, nil, timestamp, q.SenderName)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
primarydb "blackforestbytes.com/simplecloudnotifier/db/impl/primary"
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
@@ -8,7 +10,6 @@ import (
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/dataext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/ginext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type SendMessageResponse struct {
|
||||
@@ -42,7 +43,7 @@ func NewMessageHandler(app *logic.Application) MessageHandler {
|
||||
//
|
||||
// @Success 200 {object} handler.SendMessage.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
// @Failure 401 {object} ginresp.apiError "The user_id was not found or the user_key is wrong"
|
||||
// @Failure 401 {object} ginresp.apiError "The user_key is wrong"
|
||||
// @Failure 403 {object} ginresp.apiError "The user has exceeded its daily quota - wait 24 hours or upgrade your account"
|
||||
// @Failure 500 {object} ginresp.apiError "An internal server error occurred - try again later"
|
||||
//
|
||||
@@ -50,7 +51,6 @@ func NewMessageHandler(app *logic.Application) MessageHandler {
|
||||
// @Router /send [POST]
|
||||
func (h MessageHandler) SendMessage(pctx ginext.PreContext) ginext.HTTPResponse {
|
||||
type combined struct {
|
||||
UserID *models.UserID `json:"user_id" form:"user_id" example:"7725" `
|
||||
KeyToken *string `json:"key" form:"key" example:"P3TNH8mvv14fm" `
|
||||
Channel *string `json:"channel" form:"channel" example:"test" `
|
||||
Title *string `json:"title" form:"title" example:"Hello World" `
|
||||
@@ -88,7 +88,7 @@ func (h MessageHandler) SendMessage(pctx ginext.PreContext) ginext.HTTPResponse
|
||||
// query has highest prio, then form, then json
|
||||
data := dataext.ObjectMerge(dataext.ObjectMerge(b, f), q)
|
||||
|
||||
okResp, errResp := h.app.SendMessage(g, ctx, data.UserID, data.KeyToken, data.Channel, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp, data.SenderName)
|
||||
okResp, errResp := h.app.SendMessage(g, ctx, data.KeyToken, data.Channel, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp, data.SenderName)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
} else {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package primary
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
scn "blackforestbytes.com/simplecloudnotifier"
|
||||
"blackforestbytes.com/simplecloudnotifier/db"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/sq"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (db *Database) CreateUser(ctx db.TxContext, protoken *string, username *string) (models.User, error) {
|
||||
@@ -63,6 +64,15 @@ func (db *Database) GetUser(ctx db.TxContext, userid models.UserID) (models.User
|
||||
return sq.QuerySingle[models.User](ctx, tx, "SELECT * FROM users WHERE user_id = :uid AND deleted=0 LIMIT 1", sq.PP{"uid": userid}, sq.SModeExtended, sq.Safe)
|
||||
}
|
||||
|
||||
func (db *Database) GetUserByKey(ctx db.TxContext, key string) (models.User, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return models.User{}, err
|
||||
}
|
||||
|
||||
return sq.QuerySingle[models.User](ctx, tx, "SELECT * FROM users WHERE EXISTS(SELECT keytokens.keytoken_id FROM keytokens WHERE keytokens.token = :tok AND users.user_id = keytokens.owner_user_id AND keytokens.deleted=0) AND users.deleted=0 LIMIT 1", sq.PP{"tok": key}, sq.SModeExtended, sq.Safe)
|
||||
}
|
||||
|
||||
func (db *Database) GetUserOpt(ctx db.TxContext, userid models.UserID) (*models.User, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
hl "blackforestbytes.com/simplecloudnotifier/api/apihighlight"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/ginext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/mathext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/timeext"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SendMessageResponse struct {
|
||||
@@ -25,7 +26,7 @@ type SendMessageResponse struct {
|
||||
CompatMessageID int64
|
||||
}
|
||||
|
||||
func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, UserID *models.UserID, Key *string, Channel *string, Title *string, Content *string, Priority *int, UserMessageID *string, SendTimestamp *float64, SenderName *string) (*SendMessageResponse, *ginext.HTTPResponse) {
|
||||
func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, Key *string, Channel *string, Title *string, Content *string, Priority *int, UserMessageID *string, SendTimestamp *float64, SenderName *string) (*SendMessageResponse, *ginext.HTTPResponse) {
|
||||
if Title != nil {
|
||||
Title = langext.Ptr(strings.TrimSpace(*Title))
|
||||
}
|
||||
@@ -33,9 +34,6 @@ func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, UserID *mod
|
||||
UserMessageID = langext.Ptr(strings.TrimSpace(*UserMessageID))
|
||||
}
|
||||
|
||||
if UserID == nil {
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 400, apierr.MISSING_UID, hl.USER_ID, "Missing parameter [[user_id]]", nil))
|
||||
}
|
||||
if Key == nil {
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 400, apierr.MISSING_TOK, hl.USER_KEY, "Missing parameter [[key]]", nil))
|
||||
}
|
||||
@@ -49,9 +47,9 @@ func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, UserID *mod
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 400, apierr.NO_TITLE, hl.TITLE, "No title specified", nil))
|
||||
}
|
||||
|
||||
user, err := app.Database.Primary.GetUser(ctx, *UserID)
|
||||
user, err := app.Database.Primary.GetUserByKey(ctx, *Key)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found", err))
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 401, apierr.USER_AUTH_FAILED, hl.USER_KEY, "Key not found or not valid", err))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query user", err))
|
||||
@@ -126,7 +124,7 @@ func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, UserID *mod
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 403, apierr.QUOTA_REACHED, hl.NONE, fmt.Sprintf("Daily quota reached (%d)", user.QuotaPerDay()), nil))
|
||||
}
|
||||
|
||||
channel, err := app.GetOrCreateChannel(ctx, *UserID, channelDisplayName, channelInternalName)
|
||||
channel, err := app.GetOrCreateChannel(ctx, user.UserID, channelDisplayName, channelInternalName)
|
||||
if err != nil {
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query/create (owned) channel", err))
|
||||
}
|
||||
@@ -145,7 +143,7 @@ func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, UserID *mod
|
||||
|
||||
clientIP := g.ClientIP()
|
||||
|
||||
msg, err := app.Database.Primary.CreateMessage(ctx, *UserID, channel, sendTimestamp, *Title, Content, priority, UserMessageID, clientIP, SenderName, keytok.KeyTokenID)
|
||||
msg, err := app.Database.Primary.CreateMessage(ctx, user.UserID, channel, sendTimestamp, *Title, Content, priority, UserMessageID, clientIP, SenderName, keytok.KeyTokenID)
|
||||
if err != nil {
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create message in db", err))
|
||||
}
|
||||
@@ -176,7 +174,7 @@ func (app *Application) SendMessage(g *gin.Context, ctx *AppContext, UserID *mod
|
||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to inc token msg-counter", err))
|
||||
}
|
||||
|
||||
log.Info().Msg(fmt.Sprintf("Sending new notification %s for user %s (to %d active subscriptions)", msg.MessageID, UserID, len(activeSubscriptions)))
|
||||
log.Info().Msg(fmt.Sprintf("Sending new notification %s for user %s (to %d active subscriptions)", msg.MessageID, user.UserID, len(activeSubscriptions)))
|
||||
|
||||
for _, sub := range activeSubscriptions {
|
||||
clients, err := app.Database.Primary.ListClients(ctx, sub.SubscriberUserID)
|
||||
|
||||
@@ -1143,7 +1143,6 @@ func TestChannelMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1001, 1),
|
||||
})
|
||||
|
||||
@@ -1172,7 +1171,6 @@ func TestChannelMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1002, 1),
|
||||
})
|
||||
|
||||
@@ -1180,19 +1178,16 @@ func TestChannelMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan1",
|
||||
"title": tt.ShortLipsum(1003, 1),
|
||||
})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan2",
|
||||
"title": tt.ShortLipsum(1004, 1),
|
||||
})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan2",
|
||||
"title": tt.ShortLipsum(1005, 1),
|
||||
})
|
||||
|
||||
@@ -126,7 +126,6 @@ func TestTokenKeys(t *testing.T) {
|
||||
|
||||
msg1s := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": key7.Token,
|
||||
"user_id": data.UID,
|
||||
"channel": "testchan1",
|
||||
"title": "HelloWorld_001",
|
||||
})
|
||||
@@ -137,14 +136,12 @@ func TestTokenKeys(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": key7.Token,
|
||||
"user_id": data.UID,
|
||||
"channel": "testchan2",
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED) // wrong channel
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": key7.Token,
|
||||
"user_id": data.UID,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED) // no channel (=main)
|
||||
|
||||
@@ -161,7 +158,6 @@ func TestTokenKeys(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": key8.Token,
|
||||
"user_id": data.UID,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED) // no send perm
|
||||
|
||||
@@ -470,14 +466,12 @@ func TestTokenKeysPermissions(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": key7.Token,
|
||||
"user_id": data.UID,
|
||||
"channel": "testchan2",
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED) // wrong channel
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": key7.Token,
|
||||
"user_id": data.UID,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED) // no channel (=main)
|
||||
|
||||
@@ -494,7 +488,6 @@ func TestTokenKeysPermissions(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": key8.Token,
|
||||
"user_id": data.UID,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED) // no send perm
|
||||
|
||||
@@ -551,7 +544,6 @@ func TestTokenKeysMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1001, 1),
|
||||
})
|
||||
|
||||
@@ -559,7 +551,6 @@ func TestTokenKeysMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1002, 1),
|
||||
})
|
||||
|
||||
@@ -567,7 +558,6 @@ func TestTokenKeysMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1002, 1),
|
||||
})
|
||||
|
||||
@@ -575,19 +565,16 @@ func TestTokenKeysMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan1",
|
||||
"title": tt.ShortLipsum(1003, 1),
|
||||
})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan2",
|
||||
"title": tt.ShortLipsum(1004, 1),
|
||||
})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan2",
|
||||
"title": tt.ShortLipsum(1005, 1),
|
||||
})
|
||||
@@ -597,7 +584,6 @@ func TestTokenKeysMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"channel": "Chan2",
|
||||
"title": tt.ShortLipsum(1004, 1),
|
||||
})
|
||||
@@ -606,7 +592,6 @@ func TestTokenKeysMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1002, 1),
|
||||
})
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@ package test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/exerr"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"github.com/glebarez/go-sqlite"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@@ -20,3 +22,10 @@ func TestMain(m *testing.M) {
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestInitFactory(t *testing.T) {
|
||||
ws, _, stop := tt.StartSimpleWebserver(t)
|
||||
defer stop()
|
||||
|
||||
tt.InitDefaultData(t, ws)
|
||||
}
|
||||
|
||||
@@ -418,13 +418,11 @@ func TestDeleteMessage(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "Message_1",
|
||||
})
|
||||
|
||||
@@ -446,13 +444,11 @@ func TestDeleteMessageAndResendUsrMsgId(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "Message_1",
|
||||
"msg_id": "bef8dd3d-078e-4f89-abf4-5258ad22a2e4",
|
||||
})
|
||||
@@ -463,7 +459,6 @@ func TestDeleteMessageAndResendUsrMsgId(t *testing.T) {
|
||||
|
||||
msg2 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "Message_1",
|
||||
"msg_id": "bef8dd3d-078e-4f89-abf4-5258ad22a2e4",
|
||||
})
|
||||
@@ -476,7 +471,6 @@ func TestDeleteMessageAndResendUsrMsgId(t *testing.T) {
|
||||
|
||||
msg3 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "Message_1",
|
||||
"msg_id": "bef8dd3d-078e-4f89-abf4-5258ad22a2e4",
|
||||
})
|
||||
@@ -493,7 +487,6 @@ func TestGetMessageSimple(t *testing.T) {
|
||||
|
||||
msgOut := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": data.User[0].SendKey,
|
||||
"user_id": data.User[0].UID,
|
||||
"title": "Message_1",
|
||||
})
|
||||
|
||||
@@ -533,7 +526,6 @@ func TestGetMessageFull(t *testing.T) {
|
||||
|
||||
msgOut := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": data.User[0].SendKey,
|
||||
"user_id": data.User[0].UID,
|
||||
"title": "Message_1",
|
||||
"content": content,
|
||||
"channel": "demo-channel-007",
|
||||
@@ -948,7 +940,6 @@ func TestDeactivatedSubscriptionListMessages(t *testing.T) {
|
||||
newMessageTitle := langext.RandBase62(48)
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": user15.AdminKey,
|
||||
"user_id": user15.UID,
|
||||
"channel": chanName,
|
||||
"title": newMessageTitle,
|
||||
})
|
||||
@@ -1122,7 +1113,6 @@ func TestActiveSubscriptionListMessages(t *testing.T) {
|
||||
newMessageTitle := langext.RandBase62(48)
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": user15.AdminKey,
|
||||
"user_id": user15.UID,
|
||||
"channel": chanName,
|
||||
"title": newMessageTitle,
|
||||
})
|
||||
@@ -1176,7 +1166,6 @@ func TestUnconfirmedSubscriptionListMessages(t *testing.T) {
|
||||
newMessageTitle := langext.RandBase62(48)
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": user15.AdminKey,
|
||||
"user_id": user15.UID,
|
||||
"channel": chanName,
|
||||
"title": newMessageTitle,
|
||||
})
|
||||
@@ -1229,7 +1218,7 @@ func TestListMessagesSubscriptionStatusAllInactiveSubscription(t *testing.T) {
|
||||
subscriptionID, _ := tt.FindSubscriptionByChanName(t, baseUrl, user14, user15.UID, chanName)
|
||||
|
||||
newMessageTitle := langext.RandBase62(48)
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{"key": user15.AdminKey, "user_id": user15.UID, "channel": chanName, "title": newMessageTitle})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{"key": user15.AdminKey, "channel": chanName, "title": newMessageTitle})
|
||||
|
||||
type msg struct {
|
||||
MessageId string `json:"message_id"`
|
||||
@@ -1282,7 +1271,7 @@ func TestListMessagesSubscriptionStatusAllNoSubscription(t *testing.T) {
|
||||
chan2 := data.User[0].Channels[2]
|
||||
|
||||
newMessageTitle := langext.RandBase62(48)
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{"key": user0.AdminKey, "user_id": user0.UID, "channel": chan2.InternalName, "title": newMessageTitle})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{"key": user0.AdminKey, "channel": chan2.InternalName, "title": newMessageTitle})
|
||||
|
||||
{
|
||||
messages := tt.RequestAuthGet[mglist](t, user0.AdminKey, baseUrl, "/api/v2/messages")
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"blackforestbytes.com/simplecloudnotifier/push"
|
||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||
"fmt"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"github.com/gin-gonic/gin"
|
||||
"math/rand/v2"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/push"
|
||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func TestSendSimpleMessageJSON(t *testing.T) {
|
||||
@@ -28,26 +28,22 @@ func TestSendSimpleMessageJSON(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
})
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": readtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
"key": "asdf",
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED)
|
||||
|
||||
@@ -117,13 +113,11 @@ func TestSendSimpleMessageForm(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", tt.FormData{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "Hello World 9999 [$$$]",
|
||||
})
|
||||
|
||||
@@ -190,7 +184,6 @@ func TestSendSimpleMessageJSONAndQuery(t *testing.T) {
|
||||
// query overwrite body
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%s&key=%s&title=%s", uid, sendtok, url.QueryEscape("1111111")), gin.H{
|
||||
"key": "ERR",
|
||||
"user_id": models.NewUserID(),
|
||||
"title": "2222222",
|
||||
})
|
||||
|
||||
@@ -212,20 +205,17 @@ func TestSendSimpleMessageAlt1(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/send", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
})
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/send", gin.H{
|
||||
"key": readtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_001",
|
||||
}, 401, apierr.USER_AUTH_FAILED)
|
||||
|
||||
@@ -259,13 +249,11 @@ func TestSendContentMessage(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_042",
|
||||
"content": "I am Content\nasdf",
|
||||
})
|
||||
@@ -304,13 +292,11 @@ func TestSendWithSendername(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_xyz",
|
||||
"content": "Unicode: 日本 - yäy\000\n\t\x00...",
|
||||
"sender_name": "localhorst",
|
||||
@@ -353,7 +339,6 @@ func TestSendLongContent(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
@@ -364,7 +349,6 @@ func TestSendLongContent(t *testing.T) {
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": sendtok,
|
||||
"user_id": uid,
|
||||
"title": "HelloWorld_042",
|
||||
"content": longContent,
|
||||
})
|
||||
|
||||
@@ -402,7 +402,6 @@ func TestUserMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1001, 1),
|
||||
})
|
||||
|
||||
@@ -411,7 +410,6 @@ func TestUserMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1002, 1),
|
||||
})
|
||||
|
||||
@@ -419,17 +417,14 @@ func TestUserMessageCounter(t *testing.T) {
|
||||
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1003, 1),
|
||||
})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1004, 1),
|
||||
})
|
||||
tt.RequestPost[gin.H](t, baseUrl, "/", gin.H{
|
||||
"key": admintok,
|
||||
"user_id": uid,
|
||||
"title": tt.ShortLipsum(1005, 1),
|
||||
})
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/langext"
|
||||
"git.blackforestbytes.com/BlackForestBytes/goext/timeext"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gopkg.in/loremipsum.v1"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// # Generated by https://chat.openai.com/chat
|
||||
@@ -393,7 +394,6 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
||||
for _, mex := range messageExamples {
|
||||
body := gin.H{}
|
||||
body["title"] = mex.Title
|
||||
body["user_id"] = users[mex.User].UID
|
||||
switch mex.Key {
|
||||
case AKEY:
|
||||
body["key"] = users[mex.User].AdminKey
|
||||
|
||||
@@ -19,10 +19,9 @@
|
||||
|
||||
<a tabindex="-1" href="/" class="linkcaption"><h1>Simple Cloud Notifier</h1></a>
|
||||
|
||||
<p>Get your user-id and user-key from the android or iOS app.<br/>And send notifications to your phone by performing a POST request against <code>{{config|baseURL}}/</code> from anywhere</p>
|
||||
<p>Get your user-key from the android or iOS app.<br/>And send notifications to your phone by performing a POST request against <code>{{config|baseURL}}/</code> from anywhere</p>
|
||||
<pre>
|
||||
curl \
|
||||
--data "user_id=${userid}" \
|
||||
--data "key=${key}" \
|
||||
--data "title=${message_title}" \
|
||||
--data "content=${message_body}" \
|
||||
@@ -35,7 +34,6 @@ curl \
|
||||
<p>Most parameters are optional, you can send a message with only a title (default priority and channel will be used)</p>
|
||||
<pre>
|
||||
curl \
|
||||
--data "user_id={userid}" \
|
||||
--data "key={key}" \
|
||||
--data "title={message_title}" \
|
||||
{{config|baseURL}}/</pre>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
All Parameters can either directly be submitted as URL parameters or they can be put into the POST body (either multipart/form-data or JSON).
|
||||
</p>
|
||||
<p>
|
||||
You <i>need</i> to supply a valid <code>[user_id, key]</code> pair and a <code>title</code> for your message, all other parameter are optional.
|
||||
You <i>need</i> to supply a valid <code>key</code> and a <code>title</code> for your message, all other parameter are optional.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Statuscode">401 (Unauthorized)</td>
|
||||
<td data-label="Explanation">The user_id was not found, the key is wrong or the [user_id, key] combination does not have the SEND permissions on the specified channel</td>
|
||||
<td data-label="Explanation">The key is wrong or does not have the SEND permissions on the specified channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-label="Statuscode">403 (Forbidden)</td>
|
||||
@@ -125,7 +125,6 @@
|
||||
If needed the content can be supplied in the <code>content</code> parameter.
|
||||
</p>
|
||||
<pre>curl \
|
||||
--data "user_id={userid}" \
|
||||
--data "key={key}" \
|
||||
--data "title={message_title}" \
|
||||
--data "content={message_content}" \
|
||||
@@ -143,7 +142,6 @@
|
||||
If no priority is supplied the message will get the default priority of 1.
|
||||
</p>
|
||||
<pre>curl \
|
||||
--data "user_id={userid}" \
|
||||
--data "key={key}" \
|
||||
--data "title={message_title}" \
|
||||
--data "priority={0|1|2}" \
|
||||
@@ -158,7 +156,6 @@
|
||||
Channel names are case-insensitive and can only contain letters, numbers, underscores and minuses ( <code>/[[:alnum:]\-_]+/</code> )
|
||||
</p>
|
||||
<pre>curl \
|
||||
--data "user_id={userid}" \
|
||||
--data "key={key}" \
|
||||
--data "title={message_title}" \
|
||||
--data "channel={my_channel}" \
|
||||
@@ -229,7 +226,6 @@
|
||||
The message_id is optional - but if you want to use it you need to supply it via the <code>msg_id</code> parameter.
|
||||
</p>
|
||||
<pre>curl \
|
||||
--data "user_id={userid}" \
|
||||
--data "key={key}" \
|
||||
--data "title={message_title}" \
|
||||
--data "msg_id={message_id}" \
|
||||
@@ -248,7 +244,6 @@
|
||||
The custom timestamp must be within 48 hours of the current time. This parameter is only intended to supply a more precise value in case the message sending was delayed.
|
||||
</p>
|
||||
<pre>curl \
|
||||
--data "user_id={userid}" \
|
||||
--data "key={key}" \
|
||||
--data "title={message_title}" \
|
||||
--data "timestamp={unix_timestamp}" \
|
||||
|
||||
@@ -21,11 +21,6 @@
|
||||
|
||||
<a tabindex="-1" href="/" class="linkcaption"><h1>Simple Cloud Notifier</h1></a>
|
||||
|
||||
<div class="row responsive-label">
|
||||
<div class="col-sm-12 col-md-3"><label for="uid" class="doc">UserID</label></div>
|
||||
<div class="col-sm-12 col-md"><input placeholder="UserID" id="uid" class="doc" type="text" pattern="USR[A-Za-z0-9]{21}"></div>
|
||||
</div>
|
||||
|
||||
<div class="row responsive-label">
|
||||
<div class="col-sm-12 col-md-3"><label for="ukey" class="doc">Authentification Key</label></div>
|
||||
<div class="col-sm-12 col-md"><input placeholder="Key" id="ukey" class="doc" type="text" pattern="[A-Za-z0-9]{64}"></div>
|
||||
|
||||
@@ -8,20 +8,17 @@ function send()
|
||||
|
||||
me.classList.add("btn-disabled");
|
||||
|
||||
let uid = document.getElementById("uid");
|
||||
let key = document.getElementById("ukey");
|
||||
let tit = document.getElementById("tit");
|
||||
let cnt = document.getElementById("cnt");
|
||||
let pio = document.getElementById("prio");
|
||||
let cha = document.getElementById("chan");
|
||||
|
||||
uid.classList.remove('input-invalid');
|
||||
key.classList.remove('input-invalid');
|
||||
cnt.classList.remove('input-invalid');
|
||||
pio.classList.remove('input-invalid');
|
||||
|
||||
let data = new FormData();
|
||||
data.append('user_id', uid.value);
|
||||
data.append('key', key.value);
|
||||
if (tit.value !== '') data.append('title', tit.value);
|
||||
if (cnt.value !== '') data.append('content', cnt.value);
|
||||
@@ -40,7 +37,6 @@ function send()
|
||||
let resp = JSON.parse(xhr.responseText);
|
||||
if (!resp.success || xhr.status !== 200)
|
||||
{
|
||||
if (resp.errhighlight === 101) uid.classList.add('input-invalid');
|
||||
if (resp.errhighlight === 102) key.classList.add('input-invalid');
|
||||
if (resp.errhighlight === 103) tit.classList.add('input-invalid');
|
||||
if (resp.errhighlight === 104) cnt.classList.add('input-invalid');
|
||||
@@ -63,7 +59,6 @@ function send()
|
||||
'"a=' + resp.quota +
|
||||
'"a_remain=' + (resp.quota_max-resp.quota) +
|
||||
'"a_max=' + resp.quota_max +
|
||||
'&preset_user_id=' + uid.value +
|
||||
'&preset_user_key=' + key.value +
|
||||
'&preset_channel=' + cha.value;
|
||||
}
|
||||
@@ -89,7 +84,6 @@ window.addEventListener("load", function ()
|
||||
const qp = new URLSearchParams(window.location.search);
|
||||
|
||||
let btn = document.getElementById("btnSend");
|
||||
let uid = document.getElementById("uid");
|
||||
let key = document.getElementById("ukey");
|
||||
let tit = document.getElementById("tit");
|
||||
let cnt = document.getElementById("cnt");
|
||||
@@ -100,7 +94,6 @@ window.addEventListener("load", function ()
|
||||
|
||||
if (qp.has('preset_priority')) pio.selectedIndex = parseInt(qp.get("preset_priority"));
|
||||
if (qp.has('preset_user_key')) key.value = qp.get("preset_user_key");
|
||||
if (qp.has('preset_user_id')) uid.value = qp.get("preset_user_id");
|
||||
if (qp.has('preset_title')) tit.value = qp.get("preset_title");
|
||||
if (qp.has('preset_content')) cnt.value = qp.get("preset_content");
|
||||
if (qp.has('preset_channel')) cha.value = qp.get("preset_channel");
|
||||
|
||||
Reference in New Issue
Block a user