Move to string-ids for all entities (compat translation for existing data)
This commit is contained in:
parent
acd7de0dee
commit
82bc887767
@ -7,5 +7,6 @@
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SqlRedundantOrderingDirectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
@ -23,6 +23,8 @@
|
||||
-> how does it work with existing data?
|
||||
-> do i care, there are only 2 active users... (are there?)
|
||||
|
||||
- convert existing user-ids on compat /send endpoint
|
||||
|
||||
- error logging as goroutine, gets all errors via channel,
|
||||
(channel buffered - nonblocking send, second channel that gets a message when sender failed )
|
||||
(then all errors end up in _second_ sqlite table)
|
||||
@ -57,10 +59,14 @@
|
||||
|
||||
- (?) desktop client for notifications
|
||||
|
||||
- (?) add querylog (similar to requestlog/errorlog) - only for main-db
|
||||
|
||||
#### LATER
|
||||
|
||||
- Pagination for ListChannels / ListSubscriptions / ListClients / ListChannelSubscriptions / ListUserSubscriptions
|
||||
- weblogin, webapp, ...
|
||||
|
||||
- cannot open sqlite in dbbrowsr (cannot parse schema?)
|
||||
-> https://github.com/sqlitebrowser/sqlitebrowser/issues/292 -> https://github.com/sqlitebrowser/sqlitebrowser/issues/29266
|
||||
- Pagination for ListChannels / ListSubscriptions / ListClients / ListChannelSubscriptions / ListUserSubscriptions
|
||||
|
||||
- cannot open sqlite in dbbrowsr (cannot parse schema?)
|
||||
-> https://github.com/sqlitebrowser/sqlitebrowser/issues/292 -> https://github.com/sqlitebrowser/sqlitebrowser/issues/29266
|
||||
|
||||
|
@ -151,7 +151,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid} [GET]
|
||||
func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -200,7 +200,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid} [PATCH]
|
||||
func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type body struct {
|
||||
Username *string `json:"username"`
|
||||
@ -306,7 +306,7 @@ func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/clients [GET]
|
||||
func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type response struct {
|
||||
Clients []models.ClientJSON `json:"clients"`
|
||||
@ -351,8 +351,8 @@ func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/clients/{cid} [GET]
|
||||
func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
ClientID models.ClientID `uri:"cid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
ClientID models.ClientID `uri:"cid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -395,7 +395,7 @@ func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/clients [POST]
|
||||
func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type body struct {
|
||||
FCMToken string `json:"fcm_token" binding:"required"`
|
||||
@ -456,8 +456,8 @@ func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/clients/{cid} [DELETE]
|
||||
func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
ClientID models.ClientID `uri:"cid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
ClientID models.ClientID `uri:"cid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -511,7 +511,7 @@ func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/channels [GET]
|
||||
func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type query struct {
|
||||
Selector *string `json:"selector" form:"selector" enums:"owned,subscribed_any,all_any,subscribed,all"`
|
||||
@ -603,8 +603,8 @@ func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/channels/{cid} [GET]
|
||||
func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
ChannelID models.ChannelID `uri:"cid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -647,7 +647,7 @@ func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/channels [POST]
|
||||
func (h APIHandler) CreateChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type body struct {
|
||||
Name string `json:"name"`
|
||||
@ -744,8 +744,8 @@ func (h APIHandler) CreateChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/channels/{cid} [PATCH]
|
||||
func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
ChannelID models.ChannelID `uri:"cid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||
}
|
||||
type body struct {
|
||||
RefreshSubscribeKey *bool `json:"subscribe_key"`
|
||||
@ -869,8 +869,8 @@ func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/channels/{cid}/messages [GET]
|
||||
func (h APIHandler) ListChannelMessages(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
ChannelUserID models.UserID `uri:"uid"`
|
||||
ChannelID models.ChannelID `uri:"cid"`
|
||||
ChannelUserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||
}
|
||||
type query struct {
|
||||
PageSize *int `json:"page_size" form:"page_size"`
|
||||
@ -972,7 +972,7 @@ func (h APIHandler) ListChannelMessages(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/subscriptions [GET]
|
||||
func (h APIHandler) ListUserSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type query struct {
|
||||
Selector *string `json:"selector" form:"selector" enums:"owner_all,owner_confirmed,owner_unconfirmed,incoming_all,incoming_confirmed,incoming_unconfirmed"`
|
||||
@ -1069,8 +1069,8 @@ func (h APIHandler) ListUserSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/channels/{cid}/subscriptions [GET]
|
||||
func (h APIHandler) ListChannelSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
ChannelID models.ChannelID `uri:"cid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||
}
|
||||
type response struct {
|
||||
Subscriptions []models.SubscriptionJSON `json:"subscriptions"`
|
||||
@ -1123,8 +1123,8 @@ func (h APIHandler) ListChannelSubscriptions(g *gin.Context) ginresp.HTTPRespons
|
||||
// @Router /api/users/{uid}/subscriptions/{sid} [GET]
|
||||
func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
SubscriptionID models.SubscriptionID `uri:"sid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
SubscriptionID models.SubscriptionID `uri:"sid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -1170,8 +1170,8 @@ func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/subscriptions/{sid} [DELETE]
|
||||
func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
SubscriptionID models.SubscriptionID `uri:"sid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
SubscriptionID models.SubscriptionID `uri:"sid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -1223,12 +1223,12 @@ func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/subscriptions [POST]
|
||||
func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
}
|
||||
type body struct {
|
||||
ChannelOwnerUserID *models.UserID `json:"channel_owner_user_id"`
|
||||
ChannelOwnerUserID *models.UserID `json:"channel_owner_user_id" binding:"entityid"`
|
||||
ChannelInternalName *string `json:"channel_internal_name"`
|
||||
ChannelID *models.ChannelID `json:"channel_id"`
|
||||
ChannelID *models.ChannelID `json:"channel_id" binding:"entityid"`
|
||||
}
|
||||
type query struct {
|
||||
ChanSubscribeKey *string `json:"chan_subscribe_key" form:"chan_subscribe_key"`
|
||||
@ -1312,8 +1312,8 @@ func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/users/{uid}/subscriptions/{sid} [PATCH]
|
||||
func (h APIHandler) UpdateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID models.UserID `uri:"uid"`
|
||||
SubscriptionID models.SubscriptionID `uri:"sid"`
|
||||
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||
SubscriptionID models.SubscriptionID `uri:"sid" binding:"entityid"`
|
||||
}
|
||||
type body struct {
|
||||
Confirmed *bool `form:"confirmed"`
|
||||
@ -1454,7 +1454,7 @@ func (h APIHandler) ListMessages(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @ID api-messages-get
|
||||
// @Tags API-v2
|
||||
//
|
||||
// @Param mid path int true "SCNMessageID"
|
||||
// @Param mid path int true "MessageID"
|
||||
//
|
||||
// @Success 200 {object} models.MessageJSON
|
||||
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
||||
@ -1465,7 +1465,7 @@ func (h APIHandler) ListMessages(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/messages/{mid} [PATCH]
|
||||
func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
MessageID models.SCNMessageID `uri:"mid"`
|
||||
MessageID models.MessageID `uri:"mid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -1524,7 +1524,7 @@ func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @ID api-messages-delete
|
||||
// @Tags API-v2
|
||||
//
|
||||
// @Param mid path int true "SCNMessageID"
|
||||
// @Param mid path int true "MessageID"
|
||||
//
|
||||
// @Success 200 {object} models.MessageJSON
|
||||
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
||||
@ -1535,7 +1535,7 @@ func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
// @Router /api/messages/{mid} [DELETE]
|
||||
func (h APIHandler) DeleteMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
MessageID models.SCNMessageID `uri:"mid"`
|
||||
MessageID models.MessageID `uri:"mid" binding:"entityid"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
@ -1561,12 +1561,12 @@ func (h APIHandler) DeleteMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.APIError(g, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil)
|
||||
}
|
||||
|
||||
err = h.database.DeleteMessage(ctx, msg.SCNMessageID)
|
||||
err = h.database.DeleteMessage(ctx, msg.MessageID)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to delete message", err)
|
||||
}
|
||||
|
||||
err = h.database.CancelPendingDeliveries(ctx, msg.SCNMessageID)
|
||||
err = h.database.CancelPendingDeliveries(ctx, msg.MessageID)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to cancel deliveries", err)
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
hl "blackforestbytes.com/simplecloudnotifier/api/apihighlight"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||
primarydb "blackforestbytes.com/simplecloudnotifier/db/impl/primary"
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
@ -24,6 +26,56 @@ func NewCompatHandler(app *logic.Application) CompatHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// SendMessageCompat swaggerdoc
|
||||
//
|
||||
// @Deprecated
|
||||
//
|
||||
// @Summary Send a new message (compatibility)
|
||||
// @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.combined false " "
|
||||
// @Param form_data formData handler.SendMessageCompat.combined false " "
|
||||
//
|
||||
// @Success 200 {object} handler.sendMessageInternal.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
// @Failure 401 {object} ginresp.apiError
|
||||
// @Failure 403 {object} ginresp.apiError
|
||||
// @Failure 500 {object} ginresp.apiError
|
||||
//
|
||||
// @Router /send.php [POST]
|
||||
func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
|
||||
type combined struct {
|
||||
UserID *int64 `json:"user_id" form:"user_id"`
|
||||
UserKey *string `json:"user_key" form:"user_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"`
|
||||
}
|
||||
|
||||
var f combined
|
||||
var q combined
|
||||
ctx, errResp := h.app.StartRequest(g, nil, &q, nil, &f)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
}
|
||||
defer ctx.Cancel()
|
||||
|
||||
data := dataext.ObjectMerge(f, q)
|
||||
|
||||
newid, err := h.database.ConvertCompatID(ctx, langext.Coalesce(data.UserID, -1), "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if newid == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
return h.sendMessageInternal(g, ctx, langext.Ptr(models.UserID(*newid)), data.UserKey, nil, nil, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp, nil)
|
||||
}
|
||||
|
||||
// Register swaggerdoc
|
||||
//
|
||||
// @Summary Register a new account
|
||||
@ -121,10 +173,15 @@ func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(0, "Failed to create client in db")
|
||||
}
|
||||
|
||||
oldid, err := h.database.CreateCompatID(ctx, "userid", user.UserID.String())
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create userid<old>", err)
|
||||
}
|
||||
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||
Success: true,
|
||||
Message: "New user registered",
|
||||
UserID: user.UserID.IntID(),
|
||||
UserID: oldid,
|
||||
UserKey: user.AdminKey,
|
||||
QuotaUsed: user.QuotaUsedToday(),
|
||||
QuotaMax: user.QuotaPerDay(),
|
||||
@ -184,7 +241,15 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]")
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
|
||||
useridCompNew, err := h.database.ConvertCompatID(ctx, *data.UserID, "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if useridCompNew == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*useridCompNew))
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(201, "User not found")
|
||||
}
|
||||
@ -206,7 +271,7 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||
Success: true,
|
||||
Message: "ok",
|
||||
UserID: user.UserID.IntID(),
|
||||
UserID: *data.UserID,
|
||||
UserKey: user.AdminKey,
|
||||
QuotaUsed: user.QuotaUsedToday(),
|
||||
QuotaMax: user.QuotaPerDay(),
|
||||
@ -269,7 +334,15 @@ func (h CompatHandler) Ack(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(103, "Missing parameter [[scn_msg_id]]")
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
|
||||
useridCompNew, err := h.database.ConvertCompatID(ctx, *data.UserID, "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if useridCompNew == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*useridCompNew))
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(201, "User not found")
|
||||
}
|
||||
@ -336,7 +409,15 @@ func (h CompatHandler) Requery(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]")
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
|
||||
useridCompNew, err := h.database.ConvertCompatID(ctx, *data.UserID, "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if useridCompNew == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*useridCompNew))
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(201, "User not found")
|
||||
}
|
||||
@ -409,7 +490,15 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]")
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
|
||||
useridCompNew, err := h.database.ConvertCompatID(ctx, *data.UserID, "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if useridCompNew == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*useridCompNew))
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(201, "User not found")
|
||||
}
|
||||
@ -461,7 +550,7 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||
Success: true,
|
||||
Message: "user updated",
|
||||
UserID: user.UserID.IntID(),
|
||||
UserID: *data.UserID,
|
||||
UserKey: user.AdminKey,
|
||||
QuotaUsed: user.QuotaUsedToday(),
|
||||
QuotaMax: user.QuotaPerDay(),
|
||||
@ -521,7 +610,15 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(103, "Missing parameter [[scn_msg_id]]")
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
|
||||
useridCompNew, err := h.database.ConvertCompatID(ctx, *data.UserID, "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if useridCompNew == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*useridCompNew))
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(201, "User not found")
|
||||
}
|
||||
@ -533,7 +630,15 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(204, "Authentification failed")
|
||||
}
|
||||
|
||||
msg, err := h.database.GetMessage(ctx, models.SCNMessageID(*data.MessageID), false)
|
||||
messageCompNew, err := h.database.ConvertCompatID(ctx, *data.MessageID, "messageid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query messagid<old>", err)
|
||||
}
|
||||
if messageCompNew == nil {
|
||||
return ginresp.CompatAPIError(301, "Message not found")
|
||||
}
|
||||
|
||||
msg, err := h.database.GetMessage(ctx, models.MessageID(*messageCompNew), false)
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(301, "Message not found")
|
||||
}
|
||||
@ -551,7 +656,7 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse {
|
||||
Priority: msg.Priority,
|
||||
Timestamp: msg.Timestamp().Unix(),
|
||||
UserMessageID: msg.UserMessageID,
|
||||
SCNMessageID: msg.SCNMessageID.IntID(),
|
||||
SCNMessageID: *data.MessageID,
|
||||
},
|
||||
}))
|
||||
}
|
||||
@ -617,7 +722,15 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.CompatAPIError(104, "Missing parameter [[pro_token]]")
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
|
||||
useridCompNew, err := h.database.ConvertCompatID(ctx, *data.UserID, "userid")
|
||||
if err != nil {
|
||||
return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to query userid<old>", err)
|
||||
}
|
||||
if useridCompNew == nil {
|
||||
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, hl.USER_ID, "User not found (compat)", nil)
|
||||
}
|
||||
|
||||
user, err := h.database.GetUser(ctx, models.UserID(*useridCompNew))
|
||||
if err == sql.ErrNoRows {
|
||||
return ginresp.CompatAPIError(201, "User not found")
|
||||
}
|
||||
@ -662,7 +775,7 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||
Success: true,
|
||||
Message: "user updated",
|
||||
UserID: user.UserID.IntID(),
|
||||
UserID: *data.UserID,
|
||||
QuotaUsed: user.QuotaUsedToday(),
|
||||
QuotaMax: user.QuotaPerDay(),
|
||||
IsPro: user.IsPro,
|
||||
|
@ -31,48 +31,6 @@ func NewMessageHandler(app *logic.Application) MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// SendMessageCompat swaggerdoc
|
||||
//
|
||||
// @Deprecated
|
||||
//
|
||||
// @Summary Send a new message (compatibility)
|
||||
// @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.combined false " "
|
||||
// @Param form_data formData handler.SendMessageCompat.combined false " "
|
||||
//
|
||||
// @Success 200 {object} handler.sendMessageInternal.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
// @Failure 401 {object} ginresp.apiError
|
||||
// @Failure 403 {object} ginresp.apiError
|
||||
// @Failure 500 {object} ginresp.apiError
|
||||
//
|
||||
// @Router /send.php [POST]
|
||||
func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
|
||||
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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
var f combined
|
||||
var q combined
|
||||
ctx, errResp := h.app.StartRequest(g, nil, &q, nil, &f)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
}
|
||||
defer ctx.Cancel()
|
||||
|
||||
data := dataext.ObjectMerge(f, q)
|
||||
|
||||
return h.sendMessageInternal(g, ctx, data.UserID, data.UserKey, nil, nil, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp, nil)
|
||||
}
|
||||
|
||||
// SendMessage swaggerdoc
|
||||
//
|
||||
// @Summary Send a new message
|
||||
@ -123,16 +81,16 @@ func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||
|
||||
func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContext, UserID *models.UserID, UserKey *string, Channel *string, ChanKey *string, Title *string, Content *string, Priority *int, UserMessageID *string, SendTimestamp *float64, SenderName *string) ginresp.HTTPResponse {
|
||||
type response struct {
|
||||
Success bool `json:"success"`
|
||||
ErrorID apierr.APIError `json:"error"`
|
||||
ErrorHighlight int `json:"errhighlight"`
|
||||
Message string `json:"message"`
|
||||
SuppressSend bool `json:"suppress_send"`
|
||||
MessageCount int `json:"messagecount"`
|
||||
Quota int `json:"quota"`
|
||||
IsPro bool `json:"is_pro"`
|
||||
QuotaMax int `json:"quota_max"`
|
||||
SCNMessageID models.SCNMessageID `json:"scn_msg_id"`
|
||||
Success bool `json:"success"`
|
||||
ErrorID apierr.APIError `json:"error"`
|
||||
ErrorHighlight int `json:"errhighlight"`
|
||||
Message string `json:"message"`
|
||||
SuppressSend bool `json:"suppress_send"`
|
||||
MessageCount int `json:"messagecount"`
|
||||
Quota int `json:"quota"`
|
||||
IsPro bool `json:"is_pro"`
|
||||
QuotaMax int `json:"quota_max"`
|
||||
SCNMessageID models.MessageID `json:"scn_msg_id"`
|
||||
}
|
||||
|
||||
if Title != nil {
|
||||
@ -212,7 +170,7 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
Quota: user.QuotaUsedToday(),
|
||||
IsPro: user.IsPro,
|
||||
QuotaMax: user.QuotaPerDay(),
|
||||
SCNMessageID: msg.SCNMessageID,
|
||||
SCNMessageID: msg.MessageID,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -317,6 +275,6 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
||||
Quota: user.QuotaUsedToday() + 1,
|
||||
IsPro: user.IsPro,
|
||||
QuotaMax: user.QuotaPerDay(),
|
||||
SCNMessageID: msg.SCNMessageID,
|
||||
SCNMessageID: msg.MessageID,
|
||||
}))
|
||||
}
|
||||
|
@ -5,8 +5,12 @@ import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/handler"
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"blackforestbytes.com/simplecloudnotifier/swagger"
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
@ -44,7 +48,16 @@ func NewRouter(app *logic.Application) *Router {
|
||||
// @tag.name Common
|
||||
//
|
||||
// @BasePath /
|
||||
func (r *Router) Init(e *gin.Engine) {
|
||||
func (r *Router) Init(e *gin.Engine) error {
|
||||
|
||||
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
||||
err := v.RegisterValidation("entityid", models.ValidateEntityID, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("failed to add validators - wrong engine")
|
||||
}
|
||||
|
||||
// ================ General ================
|
||||
|
||||
@ -94,7 +107,7 @@ func (r *Router) Init(e *gin.Engine) {
|
||||
|
||||
// ================ Compat (v1) ================
|
||||
|
||||
compat := e.Group("/api/")
|
||||
compat := e.Group("/api")
|
||||
{
|
||||
compat.GET("/register.php", r.Wrap(r.compatHandler.Register))
|
||||
compat.GET("/info.php", r.Wrap(r.compatHandler.Info))
|
||||
@ -150,6 +163,9 @@ func (r *Router) Init(e *gin.Engine) {
|
||||
e.NoRoute(r.Wrap(r.commonHandler.NoRoute))
|
||||
}
|
||||
|
||||
// ================
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Router) Wrap(fn ginresp.WHandlerFunc) gin.HandlerFunc {
|
||||
|
@ -63,7 +63,11 @@ func main() {
|
||||
|
||||
app.Init(conf, ginengine, nc, apc, []logic.Job{jobRetry, jobReqCollector})
|
||||
|
||||
router.Init(ginengine)
|
||||
err = router.Init(ginengine)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("failed to init router")
|
||||
return
|
||||
}
|
||||
|
||||
app.Run()
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ type DBConfig struct {
|
||||
ConnMaxIdleTime time.Duration `env:"CONNEXTIONMAXIDLETIME"`
|
||||
CheckForeignKeys bool `env:"CHECKFOREIGNKEYS"`
|
||||
SingleConn bool `env:"SINGLECONNECTION"`
|
||||
BusyTimeout time.Duration `env:"BUSYTIMEOUT"`
|
||||
}
|
||||
|
||||
var Conf Config
|
||||
@ -76,6 +77,7 @@ var configLocHost = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 100 * time.Millisecond,
|
||||
},
|
||||
DBRequests: DBConfig{
|
||||
File: ".run-data/loc_requests.sqlite3",
|
||||
@ -87,6 +89,7 @@ var configLocHost = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
DBLogs: DBConfig{
|
||||
File: ".run-data/loc_logs.sqlite3",
|
||||
@ -98,6 +101,7 @@ var configLocHost = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
RequestTimeout: 16 * time.Second,
|
||||
RequestMaxRetry: 8,
|
||||
@ -142,6 +146,7 @@ var configLocDocker = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 100 * time.Millisecond,
|
||||
},
|
||||
DBRequests: DBConfig{
|
||||
File: "/data/docker_scn_requests.sqlite3",
|
||||
@ -153,6 +158,7 @@ var configLocDocker = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
DBLogs: DBConfig{
|
||||
File: "/data/docker_scn_logs.sqlite3",
|
||||
@ -164,6 +170,7 @@ var configLocDocker = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
RequestTimeout: 16 * time.Second,
|
||||
RequestMaxRetry: 8,
|
||||
@ -207,6 +214,7 @@ var configDev = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 100 * time.Millisecond,
|
||||
},
|
||||
DBRequests: DBConfig{
|
||||
File: "/data/scn_requests.sqlite3",
|
||||
@ -218,6 +226,7 @@ var configDev = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
DBLogs: DBConfig{
|
||||
File: "/data/scn_logs.sqlite3",
|
||||
@ -229,6 +238,7 @@ var configDev = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
RequestTimeout: 16 * time.Second,
|
||||
RequestMaxRetry: 8,
|
||||
@ -272,6 +282,7 @@ var configStag = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 100 * time.Millisecond,
|
||||
},
|
||||
DBRequests: DBConfig{
|
||||
File: "/data/scn_requests.sqlite3",
|
||||
@ -283,6 +294,7 @@ var configStag = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
DBLogs: DBConfig{
|
||||
File: "/data/scn_logs.sqlite3",
|
||||
@ -294,6 +306,7 @@ var configStag = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
RequestTimeout: 16 * time.Second,
|
||||
RequestMaxRetry: 8,
|
||||
@ -337,6 +350,7 @@ var configProd = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 100 * time.Millisecond,
|
||||
},
|
||||
DBRequests: DBConfig{
|
||||
File: "/data/scn_requests.sqlite3",
|
||||
@ -348,6 +362,7 @@ var configProd = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
DBLogs: DBConfig{
|
||||
File: "/data/scn_logs.sqlite3",
|
||||
@ -359,6 +374,7 @@ var configProd = func() Config {
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 60 * time.Minute,
|
||||
ConnMaxIdleTime: 60 * time.Minute,
|
||||
BusyTimeout: 500 * time.Millisecond,
|
||||
},
|
||||
RequestTimeout: 16 * time.Second,
|
||||
RequestMaxRetry: 8,
|
||||
|
@ -19,14 +19,14 @@ const (
|
||||
type CursorToken struct {
|
||||
Mode Mode
|
||||
Timestamp int64
|
||||
Id int64
|
||||
Id string
|
||||
Direction string
|
||||
FilterHash string
|
||||
}
|
||||
|
||||
type cursorTokenSerialize struct {
|
||||
Timestamp *int64 `json:"ts,omitempty"`
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
Id *string `json:"id,omitempty"`
|
||||
Direction *string `json:"dir,omitempty"`
|
||||
FilterHash *string `json:"f,omitempty"`
|
||||
}
|
||||
@ -35,7 +35,7 @@ func Start() CursorToken {
|
||||
return CursorToken{
|
||||
Mode: CTMStart,
|
||||
Timestamp: 0,
|
||||
Id: 0,
|
||||
Id: "",
|
||||
Direction: "",
|
||||
FilterHash: "",
|
||||
}
|
||||
@ -45,13 +45,13 @@ func End() CursorToken {
|
||||
return CursorToken{
|
||||
Mode: CTMEnd,
|
||||
Timestamp: 0,
|
||||
Id: 0,
|
||||
Id: "",
|
||||
Direction: "",
|
||||
FilterHash: "",
|
||||
}
|
||||
}
|
||||
|
||||
func Normal(ts time.Time, id int64, dir string, filter string) CursorToken {
|
||||
func Normal(ts time.Time, id string, dir string, filter string) CursorToken {
|
||||
return CursorToken{
|
||||
Mode: CTMNormal,
|
||||
Timestamp: ts.UnixMilli(),
|
||||
@ -76,7 +76,7 @@ func (c *CursorToken) Token() string {
|
||||
|
||||
sertok := cursorTokenSerialize{}
|
||||
|
||||
if c.Id != 0 {
|
||||
if c.Id != "" {
|
||||
sertok.Id = &c.Id
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ type Database struct {
|
||||
func NewLogsDatabase(cfg server.Config) (*Database, error) {
|
||||
conf := cfg.DBLogs
|
||||
|
||||
url := fmt.Sprintf("file:%s?_journal=%s&_timeout=%d&_fk=%s", conf.File, conf.Journal, conf.Timeout.Milliseconds(), langext.FormatBool(conf.CheckForeignKeys, "true", "false"))
|
||||
url := fmt.Sprintf("file:%s?_journal=%s&_timeout=%d&_fk=%s&_busy_timeout=%d", conf.File, conf.Journal, conf.Timeout.Milliseconds(), langext.FormatBool(conf.CheckForeignKeys, "true", "false"), conf.BusyTimeout.Milliseconds())
|
||||
|
||||
xdb, err := sqlx.Open("sqlite3", url)
|
||||
if err != nil {
|
||||
|
@ -1,9 +1,10 @@
|
||||
|
||||
CREATE TABLE `logs`
|
||||
(
|
||||
log_id INTEGER PRIMARY KEY,
|
||||
timestamp_created INTEGER NOT NULL
|
||||
log_id TEXT NOT NULL,
|
||||
timestamp_created INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (log_id)
|
||||
) STRICT;
|
||||
|
||||
|
||||
|
@ -89,7 +89,10 @@ func (db *Database) CreateChannel(ctx TxContext, userid models.UserID, dispName
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO channels (owner_user_id, display_name, internal_name, subscribe_key, send_key, timestamp_created) VALUES (:ouid, :dnam, :inam, :subkey, :sendkey, :ts)", sq.PP{
|
||||
channelid := models.NewChannelID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO channels (channel_id, owner_user_id, display_name, internal_name, subscribe_key, send_key, timestamp_created) VALUES (:cid, :ouid, :dnam, :inam, :subkey, :sendkey, :ts)", sq.PP{
|
||||
"cid": channelid,
|
||||
"ouid": userid,
|
||||
"dnam": dispName,
|
||||
"inam": intName,
|
||||
@ -101,13 +104,8 @@ func (db *Database) CreateChannel(ctx TxContext, userid models.UserID, dispName
|
||||
return models.Channel{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.Channel{}, err
|
||||
}
|
||||
|
||||
return models.Channel{
|
||||
ChannelID: models.ChannelID(liid),
|
||||
ChannelID: channelid,
|
||||
OwnerUserID: userid,
|
||||
DisplayName: dispName,
|
||||
InternalName: intName,
|
||||
@ -125,7 +123,9 @@ func (db *Database) ListChannelsByOwner(ctx TxContext, userid models.UserID, sub
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT channels.*, sub.* FROM channels LEFT JOIN subscriptions AS sub ON channels.channel_id = sub.channel_id AND sub.subscriber_user_id = :subuid WHERE owner_user_id = :ouid", sq.PP{
|
||||
order := " ORDER BY channels.timestamp_created ASC, channels.channel_id ASC "
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT channels.*, sub.* FROM channels LEFT JOIN subscriptions AS sub ON channels.channel_id = sub.channel_id AND sub.subscriber_user_id = :subuid WHERE owner_user_id = :ouid"+order, sq.PP{
|
||||
"ouid": userid,
|
||||
"subuid": subUserID,
|
||||
})
|
||||
@ -154,7 +154,9 @@ func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid models.UserID
|
||||
confCond = " AND sub.confirmed = 0"
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT channels.*, sub.* FROM channels LEFT JOIN subscriptions AS sub on channels.channel_id = sub.channel_id AND sub.subscriber_user_id = :subuid WHERE sub.subscription_id IS NOT NULL "+confCond, sq.PP{
|
||||
order := " ORDER BY channels.timestamp_created ASC, channels.channel_id ASC "
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT channels.*, sub.* FROM channels LEFT JOIN subscriptions AS sub on channels.channel_id = sub.channel_id AND sub.subscriber_user_id = :subuid WHERE sub.subscription_id IS NOT NULL "+confCond+order, sq.PP{
|
||||
"subuid": userid,
|
||||
})
|
||||
if err != nil {
|
||||
@ -182,7 +184,9 @@ func (db *Database) ListChannelsByAccess(ctx TxContext, userid models.UserID, co
|
||||
confCond = "OR (sub.subscription_id IS NOT NULL AND sub.confirmed = 0)"
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT channels.*, sub.* FROM channels LEFT JOIN subscriptions AS sub on channels.channel_id = sub.channel_id AND sub.subscriber_user_id = :subuid WHERE owner_user_id = :ouid "+confCond, sq.PP{
|
||||
order := " ORDER BY channels.timestamp_created ASC, channels.channel_id ASC "
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT channels.*, sub.* FROM channels LEFT JOIN subscriptions AS sub on channels.channel_id = sub.channel_id AND sub.subscriber_user_id = :subuid WHERE owner_user_id = :ouid "+confCond+order, sq.PP{
|
||||
"ouid": userid,
|
||||
"subuid": userid,
|
||||
})
|
||||
|
@ -15,7 +15,10 @@ func (db *Database) CreateClient(ctx TxContext, userid models.UserID, ctype mode
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO clients (user_id, type, fcm_token, timestamp_created, agent_model, agent_version) VALUES (:uid, :typ, :fcm, :ts, :am, :av)", sq.PP{
|
||||
clientid := models.NewClientID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO clients (client_id, user_id, type, fcm_token, timestamp_created, agent_model, agent_version) VALUES (:cid, :uid, :typ, :fcm, :ts, :am, :av)", sq.PP{
|
||||
"cid": clientid,
|
||||
"uid": userid,
|
||||
"typ": string(ctype),
|
||||
"fcm": fcmToken,
|
||||
@ -27,13 +30,8 @@ func (db *Database) CreateClient(ctx TxContext, userid models.UserID, ctype mode
|
||||
return models.Client{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.Client{}, err
|
||||
}
|
||||
|
||||
return models.Client{
|
||||
ClientID: models.ClientID(liid),
|
||||
ClientID: clientid,
|
||||
UserID: userid,
|
||||
Type: ctype,
|
||||
FCMToken: langext.Ptr(fcmToken),
|
||||
@ -63,7 +61,7 @@ func (db *Database) ListClients(ctx TxContext, userid models.UserID) ([]models.C
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM clients WHERE user_id = :uid", sq.PP{"uid": userid})
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM clients WHERE user_id = :uid ORDER BY clients.timestamp_created DESC, clients.client_id ASC", sq.PP{"uid": userid})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
100
scnserver/db/impl/primary/compat.go
Normal file
100
scnserver/db/impl/primary/compat.go
Normal file
@ -0,0 +1,100 @@
|
||||
package primary
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/sq"
|
||||
)
|
||||
|
||||
func (db *Database) CreateCompatID(ctx TxContext, idtype string, newid string) (int64, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT COALESCE(MAX(old), 0) FROM compat_ids", sq.PP{})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if !rows.Next() {
|
||||
return 0, errors.New("failed to query MAX(old)")
|
||||
}
|
||||
|
||||
var oldid int64
|
||||
err = rows.Scan(&oldid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
oldid++
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO compat_ids (old, new, type) VALUES (:old, :new, :typ)", sq.PP{
|
||||
"old": oldid,
|
||||
"new": newid,
|
||||
"typ": idtype,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return oldid, nil
|
||||
}
|
||||
|
||||
func (db *Database) ConvertCompatID(ctx TxContext, oldid int64, idtype string) (*string, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT new FROM compat_ids WHERE old = :old AND type = :typ", sq.PP{
|
||||
"old": oldid,
|
||||
"typ": idtype,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !rows.Next() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var newid string
|
||||
err = rows.Scan(&newid)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &newid, nil
|
||||
}
|
||||
|
||||
func (db *Database) ConvertToCompatID(ctx TxContext, newid string) (*int64, *string, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT old, type FROM compat_ids WHERE new = :new", sq.PP{"new": newid})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !rows.Next() {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
var oldid int64
|
||||
var idtype string
|
||||
err = rows.Scan(&oldid, &idtype)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &oldid, &idtype, nil
|
||||
}
|
@ -24,7 +24,7 @@ type Database struct {
|
||||
func NewPrimaryDatabase(cfg server.Config) (*Database, error) {
|
||||
conf := cfg.DBMain
|
||||
|
||||
url := fmt.Sprintf("file:%s?_journal=%s&_timeout=%d&_fk=%s", conf.File, conf.Journal, conf.Timeout.Milliseconds(), langext.FormatBool(conf.CheckForeignKeys, "true", "false"))
|
||||
url := fmt.Sprintf("file:%s?_journal=%s&_timeout=%d&_fk=%s&_busy_timeout=%d", conf.File, conf.Journal, conf.Timeout.Milliseconds(), langext.FormatBool(conf.CheckForeignKeys, "true", "false"), conf.BusyTimeout.Milliseconds())
|
||||
|
||||
xdb, err := sqlx.Open("sqlite3", url)
|
||||
if err != nil {
|
||||
|
@ -17,8 +17,11 @@ func (db *Database) CreateRetryDelivery(ctx TxContext, client models.Client, msg
|
||||
now := time.Now().UTC()
|
||||
next := scn.NextDeliveryTimestamp(now)
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO deliveries (scn_message_id, receiver_user_id, receiver_client_id, timestamp_created, timestamp_finalized, status, fcm_message_id, next_delivery) VALUES (:mid, :ruid, :rcid, :tsc, :tsf, :stat, :fcm, :next)", sq.PP{
|
||||
"mid": msg.SCNMessageID,
|
||||
deliveryid := models.NewDeliveryID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO deliveries (delivery_id, message_id, receiver_user_id, receiver_client_id, timestamp_created, timestamp_finalized, status, fcm_message_id, next_delivery) VALUES (:did, :mid, :ruid, :rcid, :tsc, :tsf, :stat, :fcm, :next)", sq.PP{
|
||||
"did": deliveryid,
|
||||
"mid": msg.MessageID,
|
||||
"ruid": client.UserID,
|
||||
"rcid": client.ClientID,
|
||||
"tsc": time2DB(now),
|
||||
@ -31,14 +34,9 @@ func (db *Database) CreateRetryDelivery(ctx TxContext, client models.Client, msg
|
||||
return models.Delivery{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.Delivery{}, err
|
||||
}
|
||||
|
||||
return models.Delivery{
|
||||
DeliveryID: models.DeliveryID(liid),
|
||||
SCNMessageID: msg.SCNMessageID,
|
||||
DeliveryID: deliveryid,
|
||||
MessageID: msg.MessageID,
|
||||
ReceiverUserID: client.UserID,
|
||||
ReceiverClientID: client.ClientID,
|
||||
TimestampCreated: now,
|
||||
@ -58,8 +56,11 @@ func (db *Database) CreateSuccessDelivery(ctx TxContext, client models.Client, m
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO deliveries (scn_message_id, receiver_user_id, receiver_client_id, timestamp_created, timestamp_finalized, status, fcm_message_id, next_delivery) VALUES (:mid, :ruid, :rcid, :tsc, :tsf, :stat, :fcm, :next)", sq.PP{
|
||||
"mid": msg.SCNMessageID,
|
||||
deliveryid := models.NewDeliveryID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO deliveries (delivery_id, message_id, receiver_user_id, receiver_client_id, timestamp_created, timestamp_finalized, status, fcm_message_id, next_delivery) VALUES (:did, :mid, :ruid, :rcid, :tsc, :tsf, :stat, :fcm, :next)", sq.PP{
|
||||
"did": deliveryid,
|
||||
"mid": msg.MessageID,
|
||||
"ruid": client.UserID,
|
||||
"rcid": client.ClientID,
|
||||
"tsc": time2DB(now),
|
||||
@ -72,14 +73,9 @@ func (db *Database) CreateSuccessDelivery(ctx TxContext, client models.Client, m
|
||||
return models.Delivery{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.Delivery{}, err
|
||||
}
|
||||
|
||||
return models.Delivery{
|
||||
DeliveryID: models.DeliveryID(liid),
|
||||
SCNMessageID: msg.SCNMessageID,
|
||||
DeliveryID: deliveryid,
|
||||
MessageID: msg.MessageID,
|
||||
ReceiverUserID: client.UserID,
|
||||
ReceiverClientID: client.ClientID,
|
||||
TimestampCreated: now,
|
||||
@ -97,7 +93,7 @@ func (db *Database) ListRetrieableDeliveries(ctx TxContext, pageSize int) ([]mod
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM deliveries WHERE status = 'RETRY' AND next_delivery < :next LIMIT :lim", sq.PP{
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM deliveries WHERE status = 'RETRY' AND next_delivery < :next LIMIT :lim ORDER BY next_delivery ASC", sq.PP{
|
||||
"next": time2DB(time.Now()),
|
||||
"lim": pageSize,
|
||||
})
|
||||
@ -169,15 +165,15 @@ func (db *Database) SetDeliveryRetry(ctx TxContext, delivery models.Delivery) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) CancelPendingDeliveries(ctx TxContext, scnMessageID models.SCNMessageID) error {
|
||||
func (db *Database) CancelPendingDeliveries(ctx TxContext, messageID models.MessageID) error {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tx.Exec(ctx, "UPDATE deliveries SET status = 'FAILED', next_delivery = NULL, timestamp_finalized = :ts WHERE scn_message_id = :mid AND status = 'RETRY'", sq.PP{
|
||||
_, err = tx.Exec(ctx, "UPDATE deliveries SET status = 'FAILED', next_delivery = NULL, timestamp_finalized = :ts WHERE message_id = :mid AND status = 'RETRY'", sq.PP{
|
||||
"ts": time.Now(),
|
||||
"mid": scnMessageID,
|
||||
"mid": messageID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,7 +30,7 @@ func (db *Database) GetMessageByUserMessageID(ctx TxContext, usrMsgId string) (*
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetMessage(ctx TxContext, scnMessageID models.SCNMessageID, allowDeleted bool) (models.Message, error) {
|
||||
func (db *Database) GetMessage(ctx TxContext, scnMessageID models.MessageID, allowDeleted bool) (models.Message, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return models.Message{}, err
|
||||
@ -38,9 +38,9 @@ func (db *Database) GetMessage(ctx TxContext, scnMessageID models.SCNMessageID,
|
||||
|
||||
var sqlcmd string
|
||||
if allowDeleted {
|
||||
sqlcmd = "SELECT * FROM messages WHERE scn_message_id = :mid LIMIT 1"
|
||||
sqlcmd = "SELECT * FROM messages WHERE message_id = :mid LIMIT 1"
|
||||
} else {
|
||||
sqlcmd = "SELECT * FROM messages WHERE scn_message_id = :mid AND deleted=0 LIMIT 1"
|
||||
sqlcmd = "SELECT * FROM messages WHERE message_id = :mid AND deleted=0 LIMIT 1"
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, sqlcmd, sq.PP{"mid": scnMessageID})
|
||||
@ -64,7 +64,10 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID models.UserID, cha
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO messages (sender_user_id, owner_user_id, channel_internal_name, channel_id, timestamp_real, timestamp_client, title, content, priority, usr_message_id, sender_ip, sender_name) VALUES (:suid, :ouid, :cnam, :cid, :tsr, :tsc, :tit, :cnt, :prio, :umid, :ip, :snam)", sq.PP{
|
||||
messageid := models.NewMessageID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO messages (message_id, sender_user_id, owner_user_id, channel_internal_name, channel_id, timestamp_real, timestamp_client, title, content, priority, usr_message_id, sender_ip, sender_name) VALUES (:mid, :suid, :ouid, :cnam, :cid, :tsr, :tsc, :tit, :cnt, :prio, :umid, :ip, :snam)", sq.PP{
|
||||
"mid": messageid,
|
||||
"suid": senderUserID,
|
||||
"ouid": channel.OwnerUserID,
|
||||
"cnam": channel.InternalName,
|
||||
@ -82,13 +85,8 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID models.UserID, cha
|
||||
return models.Message{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.Message{}, err
|
||||
}
|
||||
|
||||
return models.Message{
|
||||
SCNMessageID: models.SCNMessageID(liid),
|
||||
MessageID: messageid,
|
||||
SenderUserID: senderUserID,
|
||||
OwnerUserID: channel.OwnerUserID,
|
||||
ChannelInternalName: channel.InternalName,
|
||||
@ -104,13 +102,13 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID models.UserID, cha
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Database) DeleteMessage(ctx TxContext, scnMessageID models.SCNMessageID) error {
|
||||
func (db *Database) DeleteMessage(ctx TxContext, messageID models.MessageID) error {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tx.Exec(ctx, "UPDATE messages SET deleted=1 WHERE scn_message_id = :mid AND deleted=0", sq.PP{"mid": scnMessageID})
|
||||
_, err = tx.Exec(ctx, "UPDATE messages SET deleted=1 WHERE message_id = :mid AND deleted=0", sq.PP{"mid": messageID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -130,12 +128,12 @@ func (db *Database) ListMessages(ctx TxContext, filter models.MessageFilter, pag
|
||||
|
||||
pageCond := "1=1"
|
||||
if inTok.Mode == cursortoken.CTMNormal {
|
||||
pageCond = "timestamp_real < :tokts OR (timestamp_real = :tokts AND scn_message_id < :tokid )"
|
||||
pageCond = "timestamp_real < :tokts OR (timestamp_real = :tokts AND message_id < :tokid )"
|
||||
}
|
||||
|
||||
filterCond, filterJoin, prepParams, err := filter.SQL()
|
||||
|
||||
orderClause := "ORDER BY COALESCE(timestamp_client, timestamp_real) DESC LIMIT :lim"
|
||||
orderClause := "ORDER BY COALESCE(timestamp_client, timestamp_real) DESC, message_id DESC LIMIT :lim"
|
||||
|
||||
sqlQuery := "SELECT " + "messages.*" + " FROM messages " + filterJoin + " WHERE ( " + pageCond + " ) AND ( " + filterCond + " ) " + orderClause
|
||||
|
||||
@ -156,7 +154,7 @@ func (db *Database) ListMessages(ctx TxContext, filter models.MessageFilter, pag
|
||||
if len(data) <= pageSize {
|
||||
return data, cursortoken.End(), nil
|
||||
} else {
|
||||
outToken := cursortoken.Normal(data[pageSize-1].Timestamp(), data[pageSize-1].SCNMessageID.IntID(), "DESC", filter.Hash())
|
||||
outToken := cursortoken.Normal(data[pageSize-1].Timestamp(), data[pageSize-1].MessageID.String(), "DESC", filter.Hash())
|
||||
return data[0:pageSize], outToken, nil
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ CREATE TABLE `users`
|
||||
DROP TABLE IF EXISTS `messages`;
|
||||
CREATE TABLE `messages`
|
||||
(
|
||||
`scn_message_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`message_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`sender_user_id` INT(11) NOT NULL,
|
||||
|
||||
`timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
@ -34,5 +34,5 @@ CREATE TABLE `messages`
|
||||
`fcm_message_id` VARCHAR(256) NULL,
|
||||
`usr_message_id` VARCHAR(256) NULL,
|
||||
|
||||
PRIMARY KEY (`scn_message_id`)
|
||||
PRIMARY KEY (`message_id`)
|
||||
);
|
@ -18,7 +18,7 @@ CREATE TABLE `users`
|
||||
|
||||
CREATE TABLE `messages`
|
||||
(
|
||||
`scn_message_id` INTEGER AUTO_INCREMENT,
|
||||
`message_id` INTEGER AUTO_INCREMENT,
|
||||
`sender_user_id` INTEGER NOT NULL,
|
||||
|
||||
`timestamp_real` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
@ -32,7 +32,7 @@ CREATE TABLE `messages`
|
||||
`fcm_message_id` TEXT NULL,
|
||||
`usr_message_id` TEXT NULL,
|
||||
|
||||
PRIMARY KEY (`scn_message_id`)
|
||||
PRIMARY KEY (`message_id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `meta`
|
||||
|
@ -1,6 +1,6 @@
|
||||
CREATE TABLE users
|
||||
(
|
||||
user_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id TEXT NOT NULL,
|
||||
|
||||
username TEXT NULL DEFAULT NULL,
|
||||
|
||||
@ -18,23 +18,27 @@ CREATE TABLE users
|
||||
quota_used_day TEXT NULL DEFAULT NULL,
|
||||
|
||||
is_pro INTEGER CHECK(is_pro IN (0, 1)) NOT NULL DEFAULT 0,
|
||||
pro_token TEXT NULL DEFAULT NULL
|
||||
pro_token TEXT NULL DEFAULT NULL,
|
||||
|
||||
PRIMARY KEY (user_id)
|
||||
) STRICT;
|
||||
CREATE UNIQUE INDEX "idx_users_protoken" ON users (pro_token) WHERE pro_token IS NOT NULL;
|
||||
|
||||
|
||||
CREATE TABLE clients
|
||||
(
|
||||
client_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
client_id TEXT NOT NULL,
|
||||
|
||||
user_id INTEGER NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
type TEXT CHECK(type IN ('ANDROID', 'IOS')) NOT NULL,
|
||||
fcm_token TEXT NULL,
|
||||
|
||||
timestamp_created INTEGER NOT NULL,
|
||||
|
||||
agent_model TEXT NOT NULL,
|
||||
agent_version TEXT NOT NULL
|
||||
agent_version TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (client_id)
|
||||
) STRICT;
|
||||
CREATE INDEX "idx_clients_userid" ON clients (user_id);
|
||||
CREATE UNIQUE INDEX "idx_clients_fcmtoken" ON clients (fcm_token);
|
||||
@ -42,9 +46,9 @@ CREATE UNIQUE INDEX "idx_clients_fcmtoken" ON clients (fcm_token);
|
||||
|
||||
CREATE TABLE channels
|
||||
(
|
||||
channel_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
channel_id TEXT NOT NULL,
|
||||
|
||||
owner_user_id INTEGER NOT NULL,
|
||||
owner_user_id TEXT NOT NULL,
|
||||
|
||||
internal_name TEXT NOT NULL,
|
||||
display_name TEXT NOT NULL,
|
||||
@ -56,22 +60,26 @@ CREATE TABLE channels
|
||||
timestamp_created INTEGER NOT NULL,
|
||||
timestamp_lastsent INTEGER NULL DEFAULT NULL,
|
||||
|
||||
messages_sent INTEGER NOT NULL DEFAULT '0'
|
||||
messages_sent INTEGER NOT NULL DEFAULT '0',
|
||||
|
||||
PRIMARY KEY (channel_id)
|
||||
) STRICT;
|
||||
CREATE UNIQUE INDEX "idx_channels_identity" ON channels (owner_user_id, internal_name);
|
||||
|
||||
CREATE TABLE subscriptions
|
||||
(
|
||||
subscription_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
subscription_id TEXT NOT NULL,
|
||||
|
||||
subscriber_user_id INTEGER NOT NULL,
|
||||
channel_owner_user_id INTEGER NOT NULL,
|
||||
subscriber_user_id TEXT NOT NULL,
|
||||
channel_owner_user_id TEXT NOT NULL,
|
||||
channel_internal_name TEXT NOT NULL,
|
||||
channel_id INTEGER NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
|
||||
timestamp_created INTEGER NOT NULL,
|
||||
|
||||
confirmed INTEGER CHECK(confirmed IN (0, 1)) NOT NULL
|
||||
confirmed INTEGER CHECK(confirmed IN (0, 1)) NOT NULL,
|
||||
|
||||
PRIMARY KEY (subscription_id)
|
||||
) STRICT;
|
||||
CREATE UNIQUE INDEX "idx_subscriptions_ref" ON subscriptions (subscriber_user_id, channel_owner_user_id, channel_internal_name);
|
||||
CREATE INDEX "idx_subscriptions_chan" ON subscriptions (channel_id);
|
||||
@ -83,11 +91,11 @@ CREATE INDEX "idx_subscriptions_conf" ON subscriptions (confirmed);
|
||||
|
||||
CREATE TABLE messages
|
||||
(
|
||||
scn_message_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sender_user_id INTEGER NOT NULL,
|
||||
owner_user_id INTEGER NOT NULL,
|
||||
message_id TEXT NOT NULL,
|
||||
sender_user_id TEXT NOT NULL,
|
||||
owner_user_id TEXT NOT NULL,
|
||||
channel_internal_name TEXT NOT NULL,
|
||||
channel_id INTEGER NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
sender_ip TEXT NOT NULL,
|
||||
sender_name TEXT NULL,
|
||||
|
||||
@ -99,7 +107,9 @@ CREATE TABLE messages
|
||||
priority INTEGER CHECK(priority IN (0, 1, 2)) NOT NULL,
|
||||
usr_message_id TEXT NULL,
|
||||
|
||||
deleted INTEGER CHECK(deleted IN (0, 1)) NOT NULL DEFAULT '0'
|
||||
deleted INTEGER CHECK(deleted IN (0, 1)) NOT NULL DEFAULT '0',
|
||||
|
||||
PRIMARY KEY (message_id)
|
||||
) STRICT;
|
||||
CREATE INDEX "idx_messages_owner_channel" ON messages (owner_user_id, channel_internal_name COLLATE BINARY);
|
||||
CREATE INDEX "idx_messages_owner_channel_nc" ON messages (owner_user_id, channel_internal_name COLLATE NOCASE);
|
||||
@ -123,31 +133,30 @@ CREATE VIRTUAL TABLE messages_fts USING fts5
|
||||
|
||||
tokenize = unicode61,
|
||||
content = 'messages',
|
||||
content_rowid = 'scn_message_id'
|
||||
content_rowid = 'rowid'
|
||||
);
|
||||
|
||||
CREATE TRIGGER fts_insert AFTER INSERT ON messages BEGIN
|
||||
INSERT INTO messages_fts (rowid, channel_internal_name, sender_name, title, content) VALUES (new.scn_message_id, new.channel_internal_name, new.sender_name, new.title, new.content);
|
||||
INSERT INTO messages_fts (rowid, channel_internal_name, sender_name, title, content) VALUES (new.rowid, new.channel_internal_name, new.sender_name, new.title, new.content);
|
||||
END;
|
||||
|
||||
CREATE TRIGGER fts_update AFTER UPDATE ON messages BEGIN
|
||||
INSERT INTO messages_fts (messages_fts, rowid, channel_internal_name, sender_name, title, content) VALUES ('delete', old.scn_message_id, old.channel_internal_name, old.sender_name, old.title, old.content);
|
||||
INSERT INTO messages_fts ( rowid, channel_internal_name, sender_name, title, content) VALUES ( new.scn_message_id, new.channel_internal_name, new.sender_name, new.title, new.content);
|
||||
INSERT INTO messages_fts (messages_fts, rowid, channel_internal_name, sender_name, title, content) VALUES ('delete', old.rowid, old.channel_internal_name, old.sender_name, old.title, old.content);
|
||||
INSERT INTO messages_fts ( rowid, channel_internal_name, sender_name, title, content) VALUES ( new.rowid, new.channel_internal_name, new.sender_name, new.title, new.content);
|
||||
END;
|
||||
|
||||
CREATE TRIGGER fts_delete AFTER DELETE ON messages BEGIN
|
||||
INSERT INTO messages_fts (messages_fts, rowid, channel_internal_name, sender_name, title, content) VALUES ('delete', old.scn_message_id, old.channel_internal_name, old.sender_name, old.title, old.content);
|
||||
INSERT INTO messages_fts (messages_fts, rowid, channel_internal_name, sender_name, title, content) VALUES ('delete', old.rowid, old.channel_internal_name, old.sender_name, old.title, old.content);
|
||||
END;
|
||||
|
||||
|
||||
|
||||
CREATE TABLE deliveries
|
||||
(
|
||||
delivery_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
delivery_id TEXT NOT NULL,
|
||||
|
||||
scn_message_id INTEGER NOT NULL,
|
||||
receiver_user_id INTEGER NOT NULL,
|
||||
receiver_client_id INTEGER NOT NULL,
|
||||
message_id TEXT NOT NULL,
|
||||
receiver_user_id TEXT NOT NULL,
|
||||
receiver_client_id TEXT NOT NULL,
|
||||
|
||||
timestamp_created INTEGER NOT NULL,
|
||||
timestamp_finalized INTEGER NULL,
|
||||
@ -157,9 +166,21 @@ CREATE TABLE deliveries
|
||||
retry_count INTEGER NOT NULL DEFAULT 0,
|
||||
next_delivery INTEGER NULL DEFAULT NULL,
|
||||
|
||||
fcm_message_id TEXT NULL
|
||||
fcm_message_id TEXT NULL,
|
||||
|
||||
PRIMARY KEY (delivery_id)
|
||||
) STRICT;
|
||||
CREATE INDEX "idx_deliveries_receiver" ON deliveries (scn_message_id, receiver_client_id);
|
||||
CREATE INDEX "idx_deliveries_receiver" ON deliveries (message_id, receiver_client_id);
|
||||
|
||||
|
||||
CREATE TABLE compat_ids
|
||||
(
|
||||
old INTEGER NOT NULL,
|
||||
new TEXT NOT NULL,
|
||||
type TEXT NOT NULL
|
||||
) STRICT;
|
||||
CREATE UNIQUE INDEX "idx_compatids_new" ON compat_ids (new);
|
||||
CREATE UNIQUE INDEX "idx_compatids_old" ON compat_ids (old, type);
|
||||
|
||||
|
||||
CREATE TABLE `meta`
|
||||
|
@ -15,7 +15,10 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID models.UserI
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO subscriptions (subscriber_user_id, channel_owner_user_id, channel_internal_name, channel_id, timestamp_created, confirmed) VALUES (:suid, :ouid, :cnam, :cid, :ts, :conf)", sq.PP{
|
||||
subscriptionid := models.NewSubscriptionID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO subscriptions (subscription_id, subscriber_user_id, channel_owner_user_id, channel_internal_name, channel_id, timestamp_created, confirmed) VALUES (:sid, :suid, :ouid, :cnam, :cid, :ts, :conf)", sq.PP{
|
||||
"sid": subscriptionid,
|
||||
"suid": subscriberUID,
|
||||
"ouid": channel.OwnerUserID,
|
||||
"cnam": channel.InternalName,
|
||||
@ -27,13 +30,8 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID models.UserI
|
||||
return models.Subscription{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.Subscription{}, err
|
||||
}
|
||||
|
||||
return models.Subscription{
|
||||
SubscriptionID: models.SubscriptionID(liid),
|
||||
SubscriptionID: subscriptionid,
|
||||
SubscriberUserID: subscriberUID,
|
||||
ChannelOwnerUserID: channel.OwnerUserID,
|
||||
ChannelID: channel.ChannelID,
|
||||
@ -49,7 +47,9 @@ func (db *Database) ListSubscriptionsByChannel(ctx TxContext, channelID models.C
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM subscriptions WHERE channel_id = :cid", sq.PP{"cid": channelID})
|
||||
order := " ORDER BY subscriptions.timestamp_created DESC, subscriptions.subscription_id DESC "
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM subscriptions WHERE channel_id = :cid"+order, sq.PP{"cid": channelID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -75,7 +75,9 @@ func (db *Database) ListSubscriptionsByChannelOwner(ctx TxContext, ownerUserID m
|
||||
cond = " AND confirmed = 0"
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM subscriptions WHERE channel_owner_user_id = :ouid"+cond, sq.PP{"ouid": ownerUserID})
|
||||
order := " ORDER BY subscriptions.timestamp_created DESC, subscriptions.subscription_id DESC "
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM subscriptions WHERE channel_owner_user_id = :ouid"+cond+order, sq.PP{"ouid": ownerUserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -101,7 +103,9 @@ func (db *Database) ListSubscriptionsBySubscriber(ctx TxContext, subscriberUserI
|
||||
cond = " AND confirmed = 0"
|
||||
}
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM subscriptions WHERE subscriber_user_id = :suid"+cond, sq.PP{"suid": subscriberUserID})
|
||||
order := " ORDER BY subscriptions.timestamp_created DESC, subscriptions.subscription_id DESC "
|
||||
|
||||
rows, err := tx.Query(ctx, "SELECT * FROM subscriptions WHERE subscriber_user_id = :suid"+cond+order, sq.PP{"suid": subscriberUserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -16,7 +16,10 @@ func (db *Database) CreateUser(ctx TxContext, readKey string, sendKey string, ad
|
||||
|
||||
now := time.Now().UTC()
|
||||
|
||||
res, err := tx.Exec(ctx, "INSERT INTO users (username, read_key, send_key, admin_key, is_pro, pro_token, timestamp_created) VALUES (:un, :rk, :sk, :ak, :pro, :tok, :ts)", sq.PP{
|
||||
userid := models.NewUserID()
|
||||
|
||||
_, err = tx.Exec(ctx, "INSERT INTO users (user_id, username, read_key, send_key, admin_key, is_pro, pro_token, timestamp_created) VALUES (:uid, :un, :rk, :sk, :ak, :pro, :tok, :ts)", sq.PP{
|
||||
"uid": userid,
|
||||
"un": username,
|
||||
"rk": readKey,
|
||||
"sk": sendKey,
|
||||
@ -29,13 +32,8 @@ func (db *Database) CreateUser(ctx TxContext, readKey string, sendKey string, ad
|
||||
return models.User{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.User{}, err
|
||||
}
|
||||
|
||||
return models.User{
|
||||
UserID: models.UserID(liid),
|
||||
UserID: userid,
|
||||
Username: username,
|
||||
ReadKey: readKey,
|
||||
SendKey: sendKey,
|
||||
|
@ -24,7 +24,7 @@ type Database struct {
|
||||
func NewRequestsDatabase(cfg server.Config) (*Database, error) {
|
||||
conf := cfg.DBRequests
|
||||
|
||||
url := fmt.Sprintf("file:%s?_journal=%s&_timeout=%d&_fk=%s", conf.File, conf.Journal, conf.Timeout.Milliseconds(), langext.FormatBool(conf.CheckForeignKeys, "true", "false"))
|
||||
url := fmt.Sprintf("file:%s?_journal=%s&_timeout=%d&_fk=%s&_busy_timeout=%d", conf.File, conf.Journal, conf.Timeout.Milliseconds(), langext.FormatBool(conf.CheckForeignKeys, "true", "false"), conf.BusyTimeout.Milliseconds())
|
||||
|
||||
xdb, err := sqlx.Open("sqlite3", url)
|
||||
if err != nil {
|
||||
|
@ -7,11 +7,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func (db *Database) InsertRequestLog(ctx context.Context, data models.RequestLogDB) (models.RequestLogDB, error) {
|
||||
func (db *Database) InsertRequestLog(ctx context.Context, requestid models.RequestID, data models.RequestLogDB) (models.RequestLogDB, error) {
|
||||
|
||||
now := time.Now()
|
||||
|
||||
res, err := db.db.Exec(ctx, "INSERT INTO requests (method, uri, user_agent, authentication, request_body, request_body_size, request_content_type, remote_ip, userid, permissions, response_statuscode, response_body_size, response_body, response_content_type, retry_count, panicked, panic_str, processing_time, timestamp_created, timestamp_start, timestamp_finish) VALUES (:method, :uri, :user_agent, :authentication, :request_body, :request_body_size, :request_content_type, :remote_ip, :userid, :permissions, :response_statuscode, :response_body_size, :response_body, :response_content_type, :retry_count, :panicked, :panic_str, :processing_time, :timestamp_created, :timestamp_start, :timestamp_finish)", sq.PP{
|
||||
_, err := db.db.Exec(ctx, "INSERT INTO requests (request_id, method, uri, user_agent, authentication, request_body, request_body_size, request_content_type, remote_ip, userid, permissions, response_statuscode, response_body_size, response_body, response_content_type, retry_count, panicked, panic_str, processing_time, timestamp_created, timestamp_start, timestamp_finish) VALUES (:request_id, :method, :uri, :user_agent, :authentication, :request_body, :request_body_size, :request_content_type, :remote_ip, :userid, :permissions, :response_statuscode, :response_body_size, :response_body, :response_content_type, :retry_count, :panicked, :panic_str, :processing_time, :timestamp_created, :timestamp_start, :timestamp_finish)", sq.PP{
|
||||
"request_id": requestid,
|
||||
"method": data.Method,
|
||||
"uri": data.URI,
|
||||
"user_agent": data.UserAgent,
|
||||
@ -38,13 +39,8 @@ func (db *Database) InsertRequestLog(ctx context.Context, data models.RequestLog
|
||||
return models.RequestLogDB{}, err
|
||||
}
|
||||
|
||||
liid, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return models.RequestLogDB{}, err
|
||||
}
|
||||
|
||||
return models.RequestLogDB{
|
||||
RequestID: models.RequestID(liid),
|
||||
RequestID: requestid,
|
||||
Method: data.Method,
|
||||
URI: data.URI,
|
||||
UserAgent: data.UserAgent,
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
CREATE TABLE `requests`
|
||||
(
|
||||
request_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
request_id TEXT NOT NULL,
|
||||
|
||||
method TEXT NOT NULL,
|
||||
uri TEXT NOT NULL,
|
||||
@ -15,8 +15,8 @@ CREATE TABLE `requests`
|
||||
userid TEXT NULL,
|
||||
permissions TEXT NULL,
|
||||
|
||||
response_statuscode INTEGER NOT NULL,
|
||||
response_body_size INTEGER NOT NULL,
|
||||
response_statuscode INTEGER NULL,
|
||||
response_body_size INTEGER NULL,
|
||||
response_body TEXT NULL,
|
||||
response_content_type TEXT NOT NULL,
|
||||
processing_time INTEGER NOT NULL,
|
||||
@ -26,8 +26,9 @@ CREATE TABLE `requests`
|
||||
|
||||
timestamp_created INTEGER NOT NULL,
|
||||
timestamp_start INTEGER NOT NULL,
|
||||
timestamp_finish INTEGER NOT NULL
|
||||
timestamp_finish INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY (request_id)
|
||||
) STRICT;
|
||||
|
||||
|
||||
|
@ -134,14 +134,14 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
|
||||
|
||||
client, err := j.app.Database.Primary.GetClient(ctx, delivery.ReceiverUserID, delivery.ReceiverClientID)
|
||||
if err != nil {
|
||||
log.Err(err).Int64("ReceiverUserID", delivery.ReceiverUserID.IntID()).Int64("ReceiverClientID", delivery.ReceiverClientID.IntID()).Msg("Failed to get client")
|
||||
log.Err(err).Str("ReceiverUserID", delivery.ReceiverUserID.String()).Str("ReceiverClientID", delivery.ReceiverClientID.String()).Msg("Failed to get client")
|
||||
ctx.RollbackTransaction()
|
||||
return
|
||||
}
|
||||
|
||||
msg, err := j.app.Database.Primary.GetMessage(ctx, delivery.SCNMessageID, true)
|
||||
msg, err := j.app.Database.Primary.GetMessage(ctx, delivery.MessageID, true)
|
||||
if err != nil {
|
||||
log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Msg("Failed to get message")
|
||||
log.Err(err).Str("MessageID", delivery.MessageID.String()).Msg("Failed to get message")
|
||||
ctx.RollbackTransaction()
|
||||
return
|
||||
}
|
||||
@ -149,7 +149,7 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
|
||||
if msg.Deleted {
|
||||
err = j.app.Database.Primary.SetDeliveryFailed(ctx, delivery)
|
||||
if err != nil {
|
||||
log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery")
|
||||
log.Err(err).Str("MessageID", delivery.MessageID.String()).Str("DeliveryID", delivery.DeliveryID.String()).Msg("Failed to update delivery")
|
||||
ctx.RollbackTransaction()
|
||||
return
|
||||
}
|
||||
@ -159,22 +159,22 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
|
||||
if err == nil {
|
||||
err = j.app.Database.Primary.SetDeliverySuccess(ctx, delivery, *fcmDelivID)
|
||||
if err != nil {
|
||||
log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery")
|
||||
log.Err(err).Str("MessageID", delivery.MessageID.String()).Str("DeliveryID", delivery.DeliveryID.String()).Msg("Failed to update delivery")
|
||||
ctx.RollbackTransaction()
|
||||
return
|
||||
}
|
||||
} else if delivery.RetryCount+1 > delivery.MaxRetryCount() {
|
||||
err = j.app.Database.Primary.SetDeliveryFailed(ctx, delivery)
|
||||
if err != nil {
|
||||
log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery")
|
||||
log.Err(err).Str("MessageID", delivery.MessageID.String()).Str("DeliveryID", delivery.DeliveryID.String()).Msg("Failed to update delivery")
|
||||
ctx.RollbackTransaction()
|
||||
return
|
||||
}
|
||||
log.Warn().Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Delivery failed after <max> retries (set to FAILURE)")
|
||||
log.Warn().Str("MessageID", delivery.MessageID.String()).Str("DeliveryID", delivery.DeliveryID.String()).Msg("Delivery failed after <max> retries (set to FAILURE)")
|
||||
} else {
|
||||
err = j.app.Database.Primary.SetDeliveryRetry(ctx, delivery)
|
||||
if err != nil {
|
||||
log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery")
|
||||
log.Err(err).Str("MessageID", delivery.MessageID.String()).Str("DeliveryID", delivery.DeliveryID.String()).Msg("Failed to update delivery")
|
||||
ctx.RollbackTransaction()
|
||||
return
|
||||
}
|
||||
|
@ -72,11 +72,12 @@ mainLoop:
|
||||
log.Error().Msg(fmt.Sprintf("Received unknown job signal: <%s> in job [%s]", signal, j.name))
|
||||
}
|
||||
case obj := <-j.app.RequestLogQueue:
|
||||
err := j.insertLog(obj)
|
||||
requestid := models.NewRequestID()
|
||||
err := j.insertLog(requestid, obj)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg(fmt.Sprintf("Failed to insert RequestLog {%s} into DB", obj.RequestID))
|
||||
log.Error().Err(err).Msg(fmt.Sprintf("Failed to insert RequestLog {%s} into DB", requestid))
|
||||
} else {
|
||||
log.Debug().Msg(fmt.Sprintf("Inserted RequestLog '%s' into DB", obj.RequestID))
|
||||
log.Debug().Msg(fmt.Sprintf("Inserted RequestLog '%s' into DB", requestid))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,12 +87,12 @@ mainLoop:
|
||||
j.isRunning.Set(false)
|
||||
}
|
||||
|
||||
func (j *RequestLogCollectorJob) insertLog(rl models.RequestLog) error {
|
||||
func (j *RequestLogCollectorJob) insertLog(requestid models.RequestID, rl models.RequestLog) error {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err := j.app.Database.Requests.InsertRequestLog(ctx, rl.DB())
|
||||
_, err := j.app.Database.Requests.InsertRequestLog(ctx, requestid, rl.DB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ func (app *Application) DeliverMessage(ctx context.Context, client models.Client
|
||||
if client.FCMToken != nil {
|
||||
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")
|
||||
log.Warn().Str("MessageID", msg.MessageID.String()).Str("ClientID", client.ClientID.String()).Err(err).Msg("FCM Delivery failed")
|
||||
return nil, err
|
||||
}
|
||||
return langext.Ptr(fcmDelivID), nil
|
||||
|
@ -17,7 +17,7 @@ const (
|
||||
|
||||
type Delivery struct {
|
||||
DeliveryID DeliveryID
|
||||
SCNMessageID SCNMessageID
|
||||
MessageID MessageID
|
||||
ReceiverUserID UserID
|
||||
ReceiverClientID ClientID
|
||||
TimestampCreated time.Time
|
||||
@ -31,7 +31,7 @@ type Delivery struct {
|
||||
func (d Delivery) JSON() DeliveryJSON {
|
||||
return DeliveryJSON{
|
||||
DeliveryID: d.DeliveryID,
|
||||
SCNMessageID: d.SCNMessageID,
|
||||
MessageID: d.MessageID,
|
||||
ReceiverUserID: d.ReceiverUserID,
|
||||
ReceiverClientID: d.ReceiverClientID,
|
||||
TimestampCreated: d.TimestampCreated.Format(time.RFC3339Nano),
|
||||
@ -49,7 +49,7 @@ func (d Delivery) MaxRetryCount() int {
|
||||
|
||||
type DeliveryJSON struct {
|
||||
DeliveryID DeliveryID `json:"delivery_id"`
|
||||
SCNMessageID SCNMessageID `json:"scn_message_id"`
|
||||
MessageID MessageID `json:"message_id"`
|
||||
ReceiverUserID UserID `json:"receiver_user_id"`
|
||||
ReceiverClientID ClientID `json:"receiver_client_id"`
|
||||
TimestampCreated string `json:"timestamp_created"`
|
||||
@ -62,7 +62,7 @@ type DeliveryJSON struct {
|
||||
|
||||
type DeliveryDB struct {
|
||||
DeliveryID DeliveryID `db:"delivery_id"`
|
||||
SCNMessageID SCNMessageID `db:"scn_message_id"`
|
||||
MessageID MessageID `db:"message_id"`
|
||||
ReceiverUserID UserID `db:"receiver_user_id"`
|
||||
ReceiverClientID ClientID `db:"receiver_client_id"`
|
||||
TimestampCreated int64 `db:"timestamp_created"`
|
||||
@ -76,7 +76,7 @@ type DeliveryDB struct {
|
||||
func (d DeliveryDB) Model() Delivery {
|
||||
return Delivery{
|
||||
DeliveryID: d.DeliveryID,
|
||||
SCNMessageID: d.SCNMessageID,
|
||||
MessageID: d.MessageID,
|
||||
ReceiverUserID: d.ReceiverUserID,
|
||||
ReceiverClientID: d.ReceiverClientID,
|
||||
TimestampCreated: time.UnixMilli(d.TimestampCreated),
|
||||
|
@ -1,78 +1,376 @@
|
||||
package models
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type EntityID interface {
|
||||
IntID() int64
|
||||
String() string
|
||||
Valid() error
|
||||
Prefix() string
|
||||
Raw() string
|
||||
CheckString() string
|
||||
Regex() *regexp.Regexp
|
||||
}
|
||||
|
||||
type UserID int64
|
||||
const idlen = 24
|
||||
|
||||
func (id UserID) IntID() int64 {
|
||||
return int64(id)
|
||||
const checklen = 1
|
||||
|
||||
const idCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
const idCharsetLen = len(idCharset)
|
||||
|
||||
var charSetReverseMap = generateCharsetMap()
|
||||
|
||||
const (
|
||||
prefixUserID = "USR"
|
||||
prefixChannelID = "CHA"
|
||||
prefixDeliveryID = "DEL"
|
||||
prefixMessageID = "MSG"
|
||||
prefixSubscriptionID = "SUB"
|
||||
prefixClientID = "CLN"
|
||||
prefixRequestID = "REQ"
|
||||
)
|
||||
|
||||
var (
|
||||
regexUserID = generateRegex(prefixUserID)
|
||||
regexChannelID = generateRegex(prefixChannelID)
|
||||
regexDeliveryID = generateRegex(prefixDeliveryID)
|
||||
regexMessageID = generateRegex(prefixMessageID)
|
||||
regexSubscriptionID = generateRegex(prefixSubscriptionID)
|
||||
regexClientID = generateRegex(prefixClientID)
|
||||
regexRequestID = generateRegex(prefixRequestID)
|
||||
)
|
||||
|
||||
func generateRegex(prefix string) *regexp.Regexp {
|
||||
return regexp.MustCompile(fmt.Sprintf("^%s[%s]{%d}[%s]{%d}$", prefix, idCharset, idlen-len(prefix)-checklen, idCharset, checklen))
|
||||
}
|
||||
|
||||
func generateCharsetMap() []int {
|
||||
result := make([]int, 128)
|
||||
for i := 0; i < len(result); i++ {
|
||||
result[i] = -1
|
||||
}
|
||||
for idx, chr := range idCharset {
|
||||
result[int(chr)] = idx
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func generateID(prefix string) string {
|
||||
k := ""
|
||||
max := big.NewInt(int64(idCharsetLen))
|
||||
checksum := 0
|
||||
for i := 0; i < idlen-len(prefix)-checklen; i++ {
|
||||
v, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
v64 := v.Int64()
|
||||
k += string(idCharset[v64])
|
||||
checksum = (checksum + int(v64)) % (idCharsetLen)
|
||||
}
|
||||
checkstr := string(idCharset[checksum%idCharsetLen])
|
||||
return prefix + k + checkstr
|
||||
}
|
||||
|
||||
func validateID(prefix string, value string) error {
|
||||
if len(value) != idlen {
|
||||
return errors.New("id has the wrong length")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(value, prefix) {
|
||||
return errors.New("id is missing the correct prefix")
|
||||
}
|
||||
|
||||
checksum := 0
|
||||
for i := len(prefix); i < len(value)-checklen; i++ {
|
||||
ichr := int(value[i])
|
||||
if ichr < 0 || ichr >= len(charSetReverseMap) || charSetReverseMap[ichr] == -1 {
|
||||
return errors.New("id contains invalid characters")
|
||||
}
|
||||
checksum = (checksum + charSetReverseMap[ichr]) % (idCharsetLen)
|
||||
}
|
||||
|
||||
checkstr := string(idCharset[checksum%idCharsetLen])
|
||||
|
||||
if !strings.HasSuffix(value, checkstr) {
|
||||
return errors.New("id checkstring is invalid")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRawData(prefix string, value string) string {
|
||||
if len(value) != idlen {
|
||||
return ""
|
||||
}
|
||||
return value[len(prefix) : idlen-checklen]
|
||||
}
|
||||
|
||||
func getCheckString(prefix string, value string) string {
|
||||
if len(value) != idlen {
|
||||
return ""
|
||||
}
|
||||
return value[idlen-checklen:]
|
||||
}
|
||||
|
||||
func ValidateEntityID(vfl validator.FieldLevel) bool {
|
||||
if !vfl.Field().CanInterface() {
|
||||
log.Error().Msgf("Failed to validate EntityID (cannot interface ?!?)")
|
||||
return false
|
||||
}
|
||||
|
||||
ifvalue := vfl.Field().Interface()
|
||||
|
||||
if value1, ok := ifvalue.(EntityID); ok {
|
||||
|
||||
if vfl.Field().Type().Kind() == reflect.Pointer && langext.IsNil(value1) {
|
||||
return true
|
||||
}
|
||||
|
||||
if err := value1.Valid(); err != nil {
|
||||
log.Debug().Msgf("Failed to validate EntityID '%s' (%s)", value1.String(), err.Error())
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Error().Msgf("Failed to validate EntityID (wrong type: %T)", ifvalue)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type UserID string
|
||||
|
||||
func NewUserID() UserID {
|
||||
return UserID(generateID(prefixUserID))
|
||||
}
|
||||
|
||||
func (id UserID) Valid() error {
|
||||
return validateID(prefixUserID, string(id))
|
||||
}
|
||||
|
||||
func (id UserID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
type ChannelID int64
|
||||
func (id UserID) Prefix() string {
|
||||
return prefixUserID
|
||||
}
|
||||
|
||||
func (id ChannelID) IntID() int64 {
|
||||
return int64(id)
|
||||
func (id UserID) Raw() string {
|
||||
return getRawData(prefixUserID, string(id))
|
||||
}
|
||||
|
||||
func (id UserID) CheckString() string {
|
||||
return getCheckString(prefixUserID, string(id))
|
||||
}
|
||||
|
||||
func (id UserID) Regex() *regexp.Regexp {
|
||||
return regexUserID
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type ChannelID string
|
||||
|
||||
func NewChannelID() ChannelID {
|
||||
return ChannelID(generateID(prefixChannelID))
|
||||
}
|
||||
|
||||
func (id ChannelID) Valid() error {
|
||||
return validateID(prefixChannelID, string(id))
|
||||
}
|
||||
|
||||
func (id ChannelID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
type DeliveryID int64
|
||||
func (id ChannelID) Prefix() string {
|
||||
return prefixChannelID
|
||||
}
|
||||
|
||||
func (id DeliveryID) IntID() int64 {
|
||||
return int64(id)
|
||||
func (id ChannelID) Raw() string {
|
||||
return getRawData(prefixChannelID, string(id))
|
||||
}
|
||||
|
||||
func (id ChannelID) CheckString() string {
|
||||
return getCheckString(prefixChannelID, string(id))
|
||||
}
|
||||
|
||||
func (id ChannelID) Regex() *regexp.Regexp {
|
||||
return regexChannelID
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type DeliveryID string
|
||||
|
||||
func NewDeliveryID() DeliveryID {
|
||||
return DeliveryID(generateID(prefixDeliveryID))
|
||||
}
|
||||
|
||||
func (id DeliveryID) Valid() error {
|
||||
return validateID(prefixDeliveryID, string(id))
|
||||
}
|
||||
|
||||
func (id DeliveryID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
type SCNMessageID int64
|
||||
|
||||
func (id SCNMessageID) IntID() int64 {
|
||||
return int64(id)
|
||||
func (id DeliveryID) Prefix() string {
|
||||
return prefixDeliveryID
|
||||
}
|
||||
|
||||
func (id SCNMessageID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
func (id DeliveryID) Raw() string {
|
||||
return getRawData(prefixDeliveryID, string(id))
|
||||
}
|
||||
|
||||
type SubscriptionID int64
|
||||
func (id DeliveryID) CheckString() string {
|
||||
return getCheckString(prefixDeliveryID, string(id))
|
||||
}
|
||||
|
||||
func (id SubscriptionID) IntID() int64 {
|
||||
return int64(id)
|
||||
func (id DeliveryID) Regex() *regexp.Regexp {
|
||||
return regexDeliveryID
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type MessageID string
|
||||
|
||||
func NewMessageID() MessageID {
|
||||
return MessageID(generateID(prefixMessageID))
|
||||
}
|
||||
|
||||
func (id MessageID) Valid() error {
|
||||
return validateID(prefixMessageID, string(id))
|
||||
}
|
||||
|
||||
func (id MessageID) String() string {
|
||||
return string(id)
|
||||
}
|
||||
|
||||
func (id MessageID) Prefix() string {
|
||||
return prefixMessageID
|
||||
}
|
||||
|
||||
func (id MessageID) Raw() string {
|
||||
return getRawData(prefixMessageID, string(id))
|
||||
}
|
||||
|
||||
func (id MessageID) CheckString() string {
|
||||
return getCheckString(prefixMessageID, string(id))
|
||||
}
|
||||
|
||||
func (id MessageID) Regex() *regexp.Regexp {
|
||||
return regexMessageID
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type SubscriptionID string
|
||||
|
||||
func NewSubscriptionID() SubscriptionID {
|
||||
return SubscriptionID(generateID(prefixSubscriptionID))
|
||||
}
|
||||
|
||||
func (id SubscriptionID) Valid() error {
|
||||
return validateID(prefixSubscriptionID, string(id))
|
||||
}
|
||||
|
||||
func (id SubscriptionID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
type ClientID int64
|
||||
func (id SubscriptionID) Prefix() string {
|
||||
return prefixSubscriptionID
|
||||
}
|
||||
|
||||
func (id ClientID) IntID() int64 {
|
||||
return int64(id)
|
||||
func (id SubscriptionID) Raw() string {
|
||||
return getRawData(prefixSubscriptionID, string(id))
|
||||
}
|
||||
|
||||
func (id SubscriptionID) CheckString() string {
|
||||
return getCheckString(prefixSubscriptionID, string(id))
|
||||
}
|
||||
|
||||
func (id SubscriptionID) Regex() *regexp.Regexp {
|
||||
return regexSubscriptionID
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type ClientID string
|
||||
|
||||
func NewClientID() ClientID {
|
||||
return ClientID(generateID(prefixClientID))
|
||||
}
|
||||
|
||||
func (id ClientID) Valid() error {
|
||||
return validateID(prefixClientID, string(id))
|
||||
}
|
||||
|
||||
func (id ClientID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
type RequestID int64
|
||||
func (id ClientID) Prefix() string {
|
||||
return prefixClientID
|
||||
}
|
||||
|
||||
func (id RequestID) IntID() int64 {
|
||||
return int64(id)
|
||||
func (id ClientID) Raw() string {
|
||||
return getRawData(prefixClientID, string(id))
|
||||
}
|
||||
|
||||
func (id ClientID) CheckString() string {
|
||||
return getCheckString(prefixClientID, string(id))
|
||||
}
|
||||
|
||||
func (id ClientID) Regex() *regexp.Regexp {
|
||||
return regexClientID
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
type RequestID string
|
||||
|
||||
func NewRequestID() RequestID {
|
||||
return RequestID(generateID(prefixRequestID))
|
||||
}
|
||||
|
||||
func (id RequestID) Valid() error {
|
||||
return validateID(prefixRequestID, string(id))
|
||||
}
|
||||
|
||||
func (id RequestID) String() string {
|
||||
return strconv.FormatInt(int64(id), 10)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
func (id RequestID) Prefix() string {
|
||||
return prefixRequestID
|
||||
}
|
||||
|
||||
func (id RequestID) Raw() string {
|
||||
return getRawData(prefixRequestID, string(id))
|
||||
}
|
||||
|
||||
func (id RequestID) CheckString() string {
|
||||
return getCheckString(prefixRequestID, string(id))
|
||||
}
|
||||
|
||||
func (id RequestID) Regex() *regexp.Regexp {
|
||||
return regexRequestID
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ const (
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
SCNMessageID SCNMessageID
|
||||
MessageID MessageID
|
||||
SenderUserID UserID
|
||||
OwnerUserID UserID
|
||||
ChannelInternalName string
|
||||
@ -31,7 +31,7 @@ type Message struct {
|
||||
|
||||
func (m Message) FullJSON() MessageJSON {
|
||||
return MessageJSON{
|
||||
SCNMessageID: m.SCNMessageID,
|
||||
MessageID: m.MessageID,
|
||||
SenderUserID: m.SenderUserID,
|
||||
OwnerUserID: m.OwnerUserID,
|
||||
ChannelInternalName: m.ChannelInternalName,
|
||||
@ -49,7 +49,7 @@ func (m Message) FullJSON() MessageJSON {
|
||||
|
||||
func (m Message) TrimmedJSON() MessageJSON {
|
||||
return MessageJSON{
|
||||
SCNMessageID: m.SCNMessageID,
|
||||
MessageID: m.MessageID,
|
||||
SenderUserID: m.SenderUserID,
|
||||
OwnerUserID: m.OwnerUserID,
|
||||
ChannelInternalName: m.ChannelInternalName,
|
||||
@ -94,41 +94,41 @@ func (m Message) ShortContent() string {
|
||||
}
|
||||
|
||||
type MessageJSON struct {
|
||||
SCNMessageID SCNMessageID `json:"scn_message_id"`
|
||||
SenderUserID UserID `json:"sender_user_id"`
|
||||
OwnerUserID UserID `json:"owner_user_id"`
|
||||
ChannelInternalName string `json:"channel_internal_name"`
|
||||
ChannelID ChannelID `json:"channel_id"`
|
||||
SenderName *string `json:"sender_name"`
|
||||
SenderIP string `json:"sender_ip"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Title string `json:"title"`
|
||||
Content *string `json:"content"`
|
||||
Priority int `json:"priority"`
|
||||
UserMessageID *string `json:"usr_message_id"`
|
||||
Trimmed bool `json:"trimmed"`
|
||||
MessageID MessageID `json:"message_id"`
|
||||
SenderUserID UserID `json:"sender_user_id"`
|
||||
OwnerUserID UserID `json:"owner_user_id"`
|
||||
ChannelInternalName string `json:"channel_internal_name"`
|
||||
ChannelID ChannelID `json:"channel_id"`
|
||||
SenderName *string `json:"sender_name"`
|
||||
SenderIP string `json:"sender_ip"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Title string `json:"title"`
|
||||
Content *string `json:"content"`
|
||||
Priority int `json:"priority"`
|
||||
UserMessageID *string `json:"usr_message_id"`
|
||||
Trimmed bool `json:"trimmed"`
|
||||
}
|
||||
|
||||
type MessageDB struct {
|
||||
SCNMessageID SCNMessageID `db:"scn_message_id"`
|
||||
SenderUserID UserID `db:"sender_user_id"`
|
||||
OwnerUserID UserID `db:"owner_user_id"`
|
||||
ChannelInternalName string `db:"channel_internal_name"`
|
||||
ChannelID ChannelID `db:"channel_id"`
|
||||
SenderName *string `db:"sender_name"`
|
||||
SenderIP string `db:"sender_ip"`
|
||||
TimestampReal int64 `db:"timestamp_real"`
|
||||
TimestampClient *int64 `db:"timestamp_client"`
|
||||
Title string `db:"title"`
|
||||
Content *string `db:"content"`
|
||||
Priority int `db:"priority"`
|
||||
UserMessageID *string `db:"usr_message_id"`
|
||||
Deleted int `db:"deleted"`
|
||||
MessageID MessageID `db:"message_id"`
|
||||
SenderUserID UserID `db:"sender_user_id"`
|
||||
OwnerUserID UserID `db:"owner_user_id"`
|
||||
ChannelInternalName string `db:"channel_internal_name"`
|
||||
ChannelID ChannelID `db:"channel_id"`
|
||||
SenderName *string `db:"sender_name"`
|
||||
SenderIP string `db:"sender_ip"`
|
||||
TimestampReal int64 `db:"timestamp_real"`
|
||||
TimestampClient *int64 `db:"timestamp_client"`
|
||||
Title string `db:"title"`
|
||||
Content *string `db:"content"`
|
||||
Priority int `db:"priority"`
|
||||
UserMessageID *string `db:"usr_message_id"`
|
||||
Deleted int `db:"deleted"`
|
||||
}
|
||||
|
||||
func (m MessageDB) Model() Message {
|
||||
return Message{
|
||||
SCNMessageID: m.SCNMessageID,
|
||||
MessageID: m.MessageID,
|
||||
SenderUserID: m.SenderUserID,
|
||||
OwnerUserID: m.OwnerUserID,
|
||||
ChannelInternalName: m.ChannelInternalName,
|
||||
|
@ -48,7 +48,7 @@ func (f MessageFilter) SQL() (string, string, sq.PP, error) {
|
||||
joinClause += " LEFT JOIN subscriptions AS subs on messages.channel_id = subs.channel_id "
|
||||
}
|
||||
if f.SearchString != nil {
|
||||
joinClause += " JOIN messages_fts AS mfts on (mfts.rowid = messages.scn_message_id) "
|
||||
joinClause += " JOIN messages_fts AS mfts on (mfts.rowid = messages.rowid) "
|
||||
}
|
||||
|
||||
sqlClauses := make([]string, 0)
|
||||
|
@ -56,7 +56,7 @@ func (fb FirebaseConnector) SendNotification(ctx context.Context, client models.
|
||||
|
||||
jsonBody := gin.H{
|
||||
"data": gin.H{
|
||||
"scn_msg_id": msg.SCNMessageID.String(),
|
||||
"scn_msg_id": msg.MessageID.String(),
|
||||
"usr_msg_id": langext.Coalesce(msg.UserMessageID, ""),
|
||||
"client_id": client.ClientID.String(),
|
||||
"timestamp": strconv.FormatInt(msg.Timestamp().Unix(), 10),
|
||||
|
@ -71,8 +71,8 @@
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"type": "string",
|
||||
"example": "7725",
|
||||
"name": "user_id",
|
||||
"in": "query"
|
||||
},
|
||||
@ -144,8 +144,8 @@
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"type": "string",
|
||||
"example": "7725",
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
@ -478,7 +478,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "SCNMessageID",
|
||||
"description": "MessageID",
|
||||
"name": "mid",
|
||||
"in": "path",
|
||||
"required": true
|
||||
@ -527,7 +527,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "SCNMessageID",
|
||||
"description": "MessageID",
|
||||
"name": "mid",
|
||||
"in": "path",
|
||||
"required": true
|
||||
@ -2093,8 +2093,8 @@
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"type": "string",
|
||||
"example": "7725",
|
||||
"name": "user_id",
|
||||
"in": "query"
|
||||
},
|
||||
@ -2166,8 +2166,8 @@
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"example": 7725,
|
||||
"type": "string",
|
||||
"example": "7725",
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
@ -2414,13 +2414,13 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"channel_internal_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"channel_owner_user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2686,8 +2686,8 @@
|
||||
"example": "Hello World"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer",
|
||||
"example": 7725
|
||||
"type": "string",
|
||||
"example": "7725"
|
||||
},
|
||||
"user_key": {
|
||||
"type": "string",
|
||||
@ -2828,7 +2828,7 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"scn_msg_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
@ -2842,7 +2842,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"description_name": {
|
||||
"type": "string"
|
||||
@ -2857,7 +2857,7 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"owner_user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"send_key": {
|
||||
"description": "can be nil, depending on endpoint",
|
||||
@ -2888,7 +2888,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"client_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"fcm_token": {
|
||||
"type": "string"
|
||||
@ -2900,7 +2900,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2934,7 +2934,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"channel_internal_name": {
|
||||
"type": "string"
|
||||
@ -2942,15 +2942,15 @@
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"message_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner_user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer"
|
||||
},
|
||||
"scn_message_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"sender_ip": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -2958,7 +2958,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"sender_user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string"
|
||||
@ -2978,22 +2978,22 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"channel_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"channel_internal_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"channel_owner_user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"confirmed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"subscriber_user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"subscription_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp_created": {
|
||||
"type": "string"
|
||||
@ -3040,7 +3040,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
@ -3093,7 +3093,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
|
@ -57,11 +57,11 @@ definitions:
|
||||
handler.CreateSubscription.body:
|
||||
properties:
|
||||
channel_id:
|
||||
type: integer
|
||||
type: string
|
||||
channel_internal_name:
|
||||
type: string
|
||||
channel_owner_user_id:
|
||||
type: integer
|
||||
type: string
|
||||
type: object
|
||||
handler.CreateUser.body:
|
||||
properties:
|
||||
@ -237,8 +237,8 @@ definitions:
|
||||
example: Hello World
|
||||
type: string
|
||||
user_id:
|
||||
example: 7725
|
||||
type: integer
|
||||
example: "7725"
|
||||
type: string
|
||||
user_key:
|
||||
example: P3TNH8mvv14fm
|
||||
type: string
|
||||
@ -330,7 +330,7 @@ definitions:
|
||||
quota_max:
|
||||
type: integer
|
||||
scn_msg_id:
|
||||
type: integer
|
||||
type: string
|
||||
success:
|
||||
type: boolean
|
||||
suppress_send:
|
||||
@ -339,7 +339,7 @@ definitions:
|
||||
models.ChannelWithSubscriptionJSON:
|
||||
properties:
|
||||
channel_id:
|
||||
type: integer
|
||||
type: string
|
||||
description_name:
|
||||
type: string
|
||||
display_name:
|
||||
@ -349,7 +349,7 @@ definitions:
|
||||
messages_sent:
|
||||
type: integer
|
||||
owner_user_id:
|
||||
type: integer
|
||||
type: string
|
||||
send_key:
|
||||
description: can be nil, depending on endpoint
|
||||
type: string
|
||||
@ -370,7 +370,7 @@ definitions:
|
||||
agent_version:
|
||||
type: string
|
||||
client_id:
|
||||
type: integer
|
||||
type: string
|
||||
fcm_token:
|
||||
type: string
|
||||
timestamp_created:
|
||||
@ -378,7 +378,7 @@ definitions:
|
||||
type:
|
||||
type: string
|
||||
user_id:
|
||||
type: integer
|
||||
type: string
|
||||
type: object
|
||||
models.CompatMessage:
|
||||
properties:
|
||||
@ -400,23 +400,23 @@ definitions:
|
||||
models.MessageJSON:
|
||||
properties:
|
||||
channel_id:
|
||||
type: integer
|
||||
type: string
|
||||
channel_internal_name:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
message_id:
|
||||
type: string
|
||||
owner_user_id:
|
||||
type: integer
|
||||
type: string
|
||||
priority:
|
||||
type: integer
|
||||
scn_message_id:
|
||||
type: integer
|
||||
sender_ip:
|
||||
type: string
|
||||
sender_name:
|
||||
type: string
|
||||
sender_user_id:
|
||||
type: integer
|
||||
type: string
|
||||
timestamp:
|
||||
type: string
|
||||
title:
|
||||
@ -429,17 +429,17 @@ definitions:
|
||||
models.SubscriptionJSON:
|
||||
properties:
|
||||
channel_id:
|
||||
type: integer
|
||||
type: string
|
||||
channel_internal_name:
|
||||
type: string
|
||||
channel_owner_user_id:
|
||||
type: integer
|
||||
type: string
|
||||
confirmed:
|
||||
type: boolean
|
||||
subscriber_user_id:
|
||||
type: integer
|
||||
type: string
|
||||
subscription_id:
|
||||
type: integer
|
||||
type: string
|
||||
timestamp_created:
|
||||
type: string
|
||||
type: object
|
||||
@ -470,7 +470,7 @@ definitions:
|
||||
timestamp_lastsent:
|
||||
type: string
|
||||
user_id:
|
||||
type: integer
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
@ -505,7 +505,7 @@ definitions:
|
||||
timestamp_lastsent:
|
||||
type: string
|
||||
user_id:
|
||||
type: integer
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
@ -557,10 +557,10 @@ paths:
|
||||
in: query
|
||||
name: title
|
||||
type: string
|
||||
- example: 7725
|
||||
- example: "7725"
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
type: string
|
||||
- example: P3TNH8mvv14fm
|
||||
in: query
|
||||
name: user_key
|
||||
@ -606,10 +606,10 @@ paths:
|
||||
in: formData
|
||||
name: title
|
||||
type: string
|
||||
- example: 7725
|
||||
- example: "7725"
|
||||
in: formData
|
||||
name: user_id
|
||||
type: integer
|
||||
type: string
|
||||
- example: P3TNH8mvv14fm
|
||||
in: formData
|
||||
name: user_key
|
||||
@ -836,7 +836,7 @@ paths:
|
||||
ADMIN Key
|
||||
operationId: api-messages-delete
|
||||
parameters:
|
||||
- description: SCNMessageID
|
||||
- description: MessageID
|
||||
in: path
|
||||
name: mid
|
||||
required: true
|
||||
@ -872,7 +872,7 @@ paths:
|
||||
The returned message is never trimmed
|
||||
operationId: api-messages-get
|
||||
parameters:
|
||||
- description: SCNMessageID
|
||||
- description: MessageID
|
||||
in: path
|
||||
name: mid
|
||||
required: true
|
||||
@ -1941,10 +1941,10 @@ paths:
|
||||
in: query
|
||||
name: title
|
||||
type: string
|
||||
- example: 7725
|
||||
- example: "7725"
|
||||
in: query
|
||||
name: user_id
|
||||
type: integer
|
||||
type: string
|
||||
- example: P3TNH8mvv14fm
|
||||
in: query
|
||||
name: user_key
|
||||
@ -1990,10 +1990,10 @@ paths:
|
||||
in: formData
|
||||
name: title
|
||||
type: string
|
||||
- example: 7725
|
||||
- example: "7725"
|
||||
in: formData
|
||||
name: user_id
|
||||
type: integer
|
||||
type: string
|
||||
- example: P3TNH8mvv14fm
|
||||
in: formData
|
||||
name: user_key
|
||||
|
@ -21,7 +21,7 @@ func TestCreateChannel(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
type chanlist struct {
|
||||
@ -29,28 +29,28 @@ func TestCreateChannel(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_name")
|
||||
}
|
||||
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "test",
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertEqual(t, "chan.len", 1, len(clist.Channels))
|
||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "asdf",
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"asdf", "test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"asdf", "test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -67,10 +67,10 @@ func TestCreateChannelNameTooLong(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": langext.StrRepeat("X", 121),
|
||||
}, 400, apierr.CHANNEL_TOO_LONG)
|
||||
}
|
||||
@ -86,7 +86,7 @@ func TestChannelNameNormalization(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
type chanlist struct {
|
||||
@ -94,57 +94,57 @@ func TestChannelNameNormalization(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_name")
|
||||
}
|
||||
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "tESt",
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"tESt"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "test",
|
||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "TEST",
|
||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "Test",
|
||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "Test ",
|
||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": " Test",
|
||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
||||
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPostShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "\rTeSt\n",
|
||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"tESt"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": " WeiRD_[\uF5FF]\\stUFf\r\n\t ",
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"tESt", "WeiRD_[\uF5FF]\\stUFf"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"test", "weird_[\uF5FF]\\stuff"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -181,7 +181,7 @@ func TestListChannelsDefault(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testdata {
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels", data.User[k].UID))
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels", data.User[k].UID))
|
||||
tt.AssertMappedSet(t, fmt.Sprintf("%d->chanlist", k), v, r0.Channels, "internal_name")
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ func TestListChannelsOwned(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testdata {
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels?selector=%s", data.User[k].UID, "owned"))
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels?selector=%s", data.User[k].UID, "owned"))
|
||||
tt.AssertMappedSet(t, fmt.Sprintf("%d->chanlist", k), v, r0.Channels, "internal_name")
|
||||
}
|
||||
}
|
||||
@ -251,7 +251,7 @@ func TestListChannelsSubscribedAny(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testdata {
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels?selector=%s", data.User[k].UID, "subscribed_any"))
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels?selector=%s", data.User[k].UID, "subscribed_any"))
|
||||
tt.AssertMappedSet(t, fmt.Sprintf("%d->chanlist", k), v, r0.Channels, "internal_name")
|
||||
}
|
||||
}
|
||||
@ -286,7 +286,7 @@ func TestListChannelsAllAny(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testdata {
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels?selector=%s", data.User[k].UID, "all_any"))
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels?selector=%s", data.User[k].UID, "all_any"))
|
||||
tt.AssertMappedSet(t, fmt.Sprintf("%d->chanlist", k), v, r0.Channels, "internal_name")
|
||||
}
|
||||
}
|
||||
@ -321,7 +321,7 @@ func TestListChannelsSubscribed(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testdata {
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels?selector=%s", data.User[k].UID, "subscribed"))
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels?selector=%s", data.User[k].UID, "subscribed"))
|
||||
tt.AssertMappedSet(t, fmt.Sprintf("%d->chanlist", k), v, r0.Channels, "internal_name")
|
||||
}
|
||||
}
|
||||
@ -356,7 +356,7 @@ func TestListChannelsAll(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testdata {
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels?selector=%s", data.User[k].UID, "all"))
|
||||
r0 := tt.RequestAuthGet[chanlist](t, data.User[k].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels?selector=%s", data.User[k].UID, "all"))
|
||||
tt.AssertMappedSet(t, fmt.Sprintf("%d->chanlist", k), v, r0.Channels, "internal_name")
|
||||
}
|
||||
}
|
||||
@ -372,7 +372,7 @@ func TestChannelUpdate(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
type chanlist struct {
|
||||
@ -380,25 +380,25 @@ func TestChannelUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_name")
|
||||
}
|
||||
|
||||
chan0 := tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
chan0 := tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "server-alerts",
|
||||
})
|
||||
chanid := fmt.Sprintf("%v", chan0["channel_id"])
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"server-alerts"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"server-alerts"}, clist.Channels, "internal_name")
|
||||
tt.AssertEqual(t, "channels.descr", nil, clist.Channels[0]["description_name"])
|
||||
}
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertEqual(t, "channels.display_name", "server-alerts", chan1["display_name"])
|
||||
tt.AssertEqual(t, "channels.internal_name", "server-alerts", chan1["internal_name"])
|
||||
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_name"])
|
||||
@ -408,12 +408,12 @@ func TestChannelUpdate(t *testing.T) {
|
||||
|
||||
// [1] update display_name
|
||||
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"display_name": "SERVER-ALERTS",
|
||||
})
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertEqual(t, "channels.display_name", "SERVER-ALERTS", chan1["display_name"])
|
||||
tt.AssertEqual(t, "channels.internal_name", "server-alerts", chan1["internal_name"])
|
||||
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_name"])
|
||||
@ -423,70 +423,70 @@ func TestChannelUpdate(t *testing.T) {
|
||||
|
||||
// [2] fail to update display_name
|
||||
|
||||
tt.RequestAuthPatchShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatchShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"display_name": "SERVER-ALERTS2",
|
||||
}, 400, apierr.CHANNEL_NAME_WOULD_CHANGE)
|
||||
|
||||
// [3] renew subscribe_key
|
||||
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"subscribe_key": true,
|
||||
})
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertNotEqual(t, "channels.subscribe_key", chan0["subscribe_key"], chan1["subscribe_key"])
|
||||
tt.AssertEqual(t, "channels.send_key", chan0["send_key"], chan1["send_key"])
|
||||
}
|
||||
|
||||
// [4] renew send_key
|
||||
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"send_key": true,
|
||||
})
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertNotEqual(t, "channels.subscribe_key", chan0["subscribe_key"], chan1["subscribe_key"])
|
||||
tt.AssertNotEqual(t, "channels.send_key", chan0["send_key"], chan1["send_key"])
|
||||
}
|
||||
|
||||
// [5] update description_name
|
||||
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"description_name": "hello World",
|
||||
})
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertEqual(t, "channels.description_name", "hello World", chan1["description_name"])
|
||||
}
|
||||
|
||||
// [6] update description_name
|
||||
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"description_name": " AXXhello World9 ",
|
||||
})
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertEqual(t, "channels.description_name", "AXXhello World9", chan1["description_name"])
|
||||
}
|
||||
|
||||
// [7] clear description_name
|
||||
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatch[tt.Void](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"description_name": "",
|
||||
})
|
||||
|
||||
{
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid))
|
||||
chan1 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid))
|
||||
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_name"])
|
||||
}
|
||||
|
||||
// [8] fail to update description_name
|
||||
|
||||
tt.RequestAuthPatchShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels/%s", uid, chanid), gin.H{
|
||||
tt.RequestAuthPatchShouldFail(t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels/%s", uid, chanid), gin.H{
|
||||
"description_name": strings.Repeat("0123456789", 48),
|
||||
}, 400, apierr.CHANNEL_DESCRIPTION_TOO_LONG)
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
package test
|
||||
|
||||
//TODO test compat methods
|
||||
|
||||
//TODO also test compat_id mapping
|
||||
|
@ -2,6 +2,7 @@ package test
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -48,7 +49,7 @@ func TestDeleteMessage(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -76,7 +77,7 @@ func TestDeleteMessageAndResendUsrMsgId(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -138,7 +139,18 @@ func TestGetMessageNotFound(t *testing.T) {
|
||||
|
||||
data := tt.InitDefaultData(t, ws)
|
||||
|
||||
tt.RequestAuthGetShouldFail(t, data.User[0].AdminKey, baseUrl, "/api/messages/8963586", 404, apierr.MESSAGE_NOT_FOUND)
|
||||
tt.RequestAuthGetShouldFail(t, data.User[0].AdminKey, baseUrl, "/api/messages/"+models.NewMessageID().String(), 404, apierr.MESSAGE_NOT_FOUND)
|
||||
}
|
||||
|
||||
func TestGetMessageInvalidID(t *testing.T) {
|
||||
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||
defer stop()
|
||||
|
||||
data := tt.InitDefaultData(t, ws)
|
||||
|
||||
tt.RequestAuthGetShouldFail(t, data.User[0].AdminKey, baseUrl, "/api/messages/"+models.NewUserID().String(), 400, apierr.BINDFAIL_URI_PARAM)
|
||||
|
||||
tt.RequestAuthGetShouldFail(t, data.User[0].AdminKey, baseUrl, "/api/messages/"+"asdfxxx", 400, apierr.BINDFAIL_URI_PARAM)
|
||||
}
|
||||
|
||||
func TestGetMessageFull(t *testing.T) {
|
||||
|
@ -2,6 +2,7 @@ package test
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"blackforestbytes.com/simplecloudnotifier/push"
|
||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||
"fmt"
|
||||
@ -24,7 +25,7 @@ func TestSendSimpleMessageJSON(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
@ -50,7 +51,7 @@ func TestSendSimpleMessageJSON(t *testing.T) {
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -77,16 +78,16 @@ func TestSendSimpleMessageQuery(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%d&user_key=%s&title=%s", uid, sendtok, url.QueryEscape("Hello World 2134")), nil)
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%s&user_key=%s&title=%s", uid, sendtok, url.QueryEscape("Hello World 2134")), nil)
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "Hello World 2134", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -113,20 +114,20 @@ func TestSendSimpleMessageForm(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": uid,
|
||||
"title": "Hello World 9999 [$$$]",
|
||||
})
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "Hello World 9999 [$$$]", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -153,10 +154,10 @@ func TestSendSimpleMessageFormAndQuery(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%d&user_key=%s&title=%s", uid, sendtok, url.QueryEscape("1111111")), tt.FormData{
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%s&user_key=%s&title=%s", uid, sendtok, url.QueryEscape("1111111")), tt.FormData{
|
||||
"user_key": "ERR",
|
||||
"user_id": "999999",
|
||||
"title": "2222222",
|
||||
@ -164,7 +165,7 @@ func TestSendSimpleMessageFormAndQuery(t *testing.T) {
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "1111111", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
}
|
||||
|
||||
func TestSendSimpleMessageJSONAndQuery(t *testing.T) {
|
||||
@ -180,18 +181,19 @@ func TestSendSimpleMessageJSONAndQuery(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%d&user_key=%s&title=%s", uid, sendtok, url.QueryEscape("1111111")), gin.H{
|
||||
// query overwrite body
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/?user_id=%s&user_key=%s&title=%s", uid, sendtok, url.QueryEscape("1111111")), gin.H{
|
||||
"user_key": "ERR",
|
||||
"user_id": 999999,
|
||||
"user_id": models.NewUserID(),
|
||||
"title": "2222222",
|
||||
})
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "1111111", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
}
|
||||
|
||||
func TestSendSimpleMessageAlt1(t *testing.T) {
|
||||
@ -207,7 +209,7 @@ func TestSendSimpleMessageAlt1(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
@ -227,7 +229,7 @@ func TestSendSimpleMessageAlt1(t *testing.T) {
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -254,7 +256,7 @@ func TestSendContentMessage(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
@ -268,7 +270,7 @@ func TestSendContentMessage(t *testing.T) {
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_042", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", "I am Content\nasdf", pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -299,7 +301,7 @@ func TestSendWithSendername(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -315,7 +317,7 @@ func TestSendWithSendername(t *testing.T) {
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_xyz", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", "Unicode: 日本 - yäy\000\n\t\x00...", pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.SenderName", "localhorst", pusher.Last().Message.SenderName)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -348,7 +350,7 @@ func TestSendLongContent(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
@ -367,7 +369,7 @@ func TestSendLongContent(t *testing.T) {
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_042", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", longContent, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -405,7 +407,7 @@ func TestSendTooLongContent(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
longContent := ""
|
||||
@ -433,7 +435,7 @@ func TestSendLongContentPro(t *testing.T) {
|
||||
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
{
|
||||
@ -519,7 +521,7 @@ func TestSendTooLongTitle(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||
@ -542,7 +544,7 @@ func TestSendIdempotent(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
readtok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
@ -555,7 +557,7 @@ func TestSendIdempotent(t *testing.T) {
|
||||
})
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.suppress_send", msg1["suppress_send"], false)
|
||||
tt.AssertStrRepEqual(t, "msg.msg_id", "c0235a49-dabc-4cdc-a0ce-453966e0c2d5", pusher.Last().Message.UserMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.title", "Hello SCN", pusher.Last().Message.Title)
|
||||
@ -578,7 +580,7 @@ func TestSendIdempotent(t *testing.T) {
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], msg2["scn_msg_id"])
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg2["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg2["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.suppress_send", msg2["suppress_send"], true)
|
||||
tt.AssertStrRepEqual(t, "msg.msg_id", "c0235a49-dabc-4cdc-a0ce-453966e0c2d5", pusher.Last().Message.UserMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.title", "Hello SCN", pusher.Last().Message.Title)
|
||||
@ -620,7 +622,7 @@ func TestSendWithPriority(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -713,7 +715,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -765,11 +767,9 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
"priority": 9999,
|
||||
}, 400, apierr.INVALID_PRIO)
|
||||
|
||||
struid := fmt.Sprintf("%d", uid)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": struid,
|
||||
"user_id": uid,
|
||||
"title": "(title)",
|
||||
"content": "(content)",
|
||||
"priority": "-1",
|
||||
@ -777,7 +777,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": struid,
|
||||
"user_id": uid,
|
||||
"title": "(title)",
|
||||
"content": "(content)",
|
||||
"priority": "4",
|
||||
@ -785,7 +785,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": struid,
|
||||
"user_id": uid,
|
||||
"title": "(title)",
|
||||
"content": "(content)",
|
||||
"priority": "9999",
|
||||
@ -793,7 +793,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": admintok,
|
||||
"user_id": struid,
|
||||
"user_id": uid,
|
||||
"title": "(title)",
|
||||
"content": "(content)",
|
||||
"priority": "-1",
|
||||
@ -801,7 +801,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": admintok,
|
||||
"user_id": struid,
|
||||
"user_id": uid,
|
||||
"title": "(title)",
|
||||
"content": "(content)",
|
||||
"priority": "4",
|
||||
@ -809,7 +809,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": admintok,
|
||||
"user_id": struid,
|
||||
"user_id": uid,
|
||||
"title": "(title)",
|
||||
"content": "(content)",
|
||||
"priority": "9999",
|
||||
@ -831,7 +831,7 @@ func TestSendWithTimestamp(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -839,7 +839,7 @@ func TestSendWithTimestamp(t *testing.T) {
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": fmt.Sprintf("%s", uid),
|
||||
"title": "TTT",
|
||||
"timestamp": fmt.Sprintf("%d", ts),
|
||||
})
|
||||
@ -849,7 +849,7 @@ func TestSendWithTimestamp(t *testing.T) {
|
||||
tt.AssertStrRepEqual(t, "msg.TimestampClient", ts, pusher.Last().Message.TimestampClient.Unix())
|
||||
tt.AssertStrRepEqual(t, "msg.Timestamp", ts, pusher.Last().Message.Timestamp().Unix())
|
||||
tt.AssertNotStrRepEqual(t, "msg.ts", pusher.Last().Message.TimestampClient, pusher.Last().Message.TimestampReal)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -888,33 +888,33 @@ func TestSendInvalidTimestamp(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": fmt.Sprintf("%s", uid),
|
||||
"title": "TTT",
|
||||
"timestamp": "-10000",
|
||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": fmt.Sprintf("%s", uid),
|
||||
"title": "TTT",
|
||||
"timestamp": "0",
|
||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": fmt.Sprintf("%s", uid),
|
||||
"title": "TTT",
|
||||
"timestamp": fmt.Sprintf("%d", time.Now().Unix()-int64(25*time.Hour.Seconds())),
|
||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": fmt.Sprintf("%s", uid),
|
||||
"title": "TTT",
|
||||
"timestamp": fmt.Sprintf("%d", time.Now().Unix()+int64(25*time.Hour.Seconds())),
|
||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
@ -947,28 +947,28 @@ func TestSendInvalidTimestamp(t *testing.T) {
|
||||
"timestamp": time.Now().Unix() + int64(25*time.Hour.Seconds()),
|
||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%d&title=%s×tamp=%d",
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%s&title=%s×tamp=%d",
|
||||
sendtok,
|
||||
uid,
|
||||
"TTT",
|
||||
-10000,
|
||||
), nil, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%d&title=%s×tamp=%d",
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%s&title=%s×tamp=%d",
|
||||
sendtok,
|
||||
uid,
|
||||
"TTT",
|
||||
0,
|
||||
), nil, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%d&title=%s×tamp=%d",
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%s&title=%s×tamp=%d",
|
||||
sendtok,
|
||||
uid,
|
||||
"TTT",
|
||||
time.Now().Unix()-int64(25*time.Hour.Seconds()),
|
||||
), nil, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%d&title=%s×tamp=%d",
|
||||
tt.RequestPostShouldFail(t, baseUrl, fmt.Sprintf("/?user_key=%s&user_id=%s&title=%s×tamp=%d",
|
||||
sendtok,
|
||||
uid,
|
||||
"TTT",
|
||||
@ -978,40 +978,34 @@ func TestSendInvalidTimestamp(t *testing.T) {
|
||||
tt.AssertEqual(t, "messageCount", 0, len(pusher.Data))
|
||||
}
|
||||
|
||||
func TestSendCompat(t *testing.T) {
|
||||
func TestSendCompatWithOldUser(t *testing.T) {
|
||||
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||
defer stop()
|
||||
|
||||
pusher := ws.Pusher.(*push.TestSink)
|
||||
|
||||
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",
|
||||
})
|
||||
r0 := tt.RequestGet[gin.H](t, baseUrl, "/api/register.php?fcm_token=DUMMY_FCM&pro=0&pro_token=")
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
uidold := int64(r0["user_id"].(float64))
|
||||
admintok := r0["user_key"].(string)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_key": admintok,
|
||||
"user_id": fmt.Sprintf("%d", uidold),
|
||||
"title": "HelloWorld_001",
|
||||
})
|
||||
|
||||
// does not allow json - only form & query
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/send.php", gin.H{
|
||||
"user_key": readtok,
|
||||
"user_id": uid,
|
||||
"user_key": admintok,
|
||||
"user_id": uidold,
|
||||
"title": "HelloWorld_001",
|
||||
}, 0, 0)
|
||||
}, 400, 0)
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
type mglist struct {
|
||||
Messages []gin.H `json:"messages"`
|
||||
@ -1024,12 +1018,103 @@ func TestSendCompat(t *testing.T) {
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", msg1Get["title"])
|
||||
tt.AssertStrRepEqual(t, "msg.channel_internal_name", "main", msg1Get["channel_internal_name"])
|
||||
|
||||
msg2 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_key=%s&user_id=%d&title=%s", sendtok, uid, "HelloWorld_002"), nil)
|
||||
msg2 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_key=%s&user_id=%d&title=%s", admintok, uidold, "HelloWorld_002"), nil)
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 2, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_002", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg2["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg2["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/messages/"+fmt.Sprintf("%v", msg2["scn_msg_id"]))
|
||||
|
||||
content3 := "039c1817-76ee-44ab-972a-4cec0a15a791\n" +
|
||||
"046f59ea-9a49-4060-93e6-8a4e14134faf\n" +
|
||||
"ab566fbe-9020-41b6-afa6-94f3d8d7c7b4\n" +
|
||||
"d52e5f7d-26a8-45b9-befc-da44a3f112da\n" +
|
||||
"d19fae55-d52a-4753-b9f1-66a935d68b1e\n" +
|
||||
"99a4099d-44d5-497a-a69b-18e277400d6e\n" +
|
||||
"a55757aa-afaa-420e-afaf-f3951e9e2434\n" +
|
||||
"ee58f5fc-b384-49f4-bc2c-c5b3c7bd54b7\n" +
|
||||
"5a7008d9-dd15-406a-83d1-fd6209c56141\n"
|
||||
ts3 := time.Now().Unix() - int64(time.Hour.Seconds())
|
||||
|
||||
msg3 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
||||
"user_key": admintok,
|
||||
"user_id": fmt.Sprintf("%d", uidold),
|
||||
"title": "HelloWorld_003",
|
||||
"content": content3,
|
||||
"priority": "2",
|
||||
"msg_id": "8a2c7e92-86f3-4d69-897a-571286954030",
|
||||
"timestamp": fmt.Sprintf("%d", ts3),
|
||||
})
|
||||
|
||||
tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/messages/"+fmt.Sprintf("%v", msg3["scn_msg_id"]))
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 3, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.Title", "HelloWorld_003", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.Content", content3, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.MessageID", msg3["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.Priority", 2, pusher.Last().Message.Priority)
|
||||
tt.AssertStrRepEqual(t, "msg.UserMessageID", "8a2c7e92-86f3-4d69-897a-571286954030", pusher.Last().Message.UserMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.UserMessageID", ts3, pusher.Last().Message.Timestamp().Unix())
|
||||
|
||||
}
|
||||
|
||||
func TestSendCompatWithNewUser(t *testing.T) {
|
||||
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||
defer stop()
|
||||
|
||||
pusher := ws.Pusher.(*push.TestSink)
|
||||
|
||||
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 := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
readtok := r0["read_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
uidold := tt.CreateCompatID(t, ws, "userid", uid)
|
||||
|
||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uidold),
|
||||
"title": "HelloWorld_001",
|
||||
})
|
||||
|
||||
// does not allow json - only form & query
|
||||
tt.RequestPostShouldFail(t, baseUrl, "/send.php", gin.H{
|
||||
"user_key": readtok,
|
||||
"user_id": uidold,
|
||||
"title": "HelloWorld_001",
|
||||
}, 400, 0)
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg1["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
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.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", msg1Get["title"])
|
||||
tt.AssertStrRepEqual(t, "msg.channel_internal_name", "main", msg1Get["channel_internal_name"])
|
||||
|
||||
msg2 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_key=%s&user_id=%d&title=%s", sendtok, uidold, "HelloWorld_002"), nil)
|
||||
|
||||
tt.AssertEqual(t, "messageCount", 2, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_002", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.content", nil, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.scn_msg_id", msg2["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
|
||||
tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/messages/"+fmt.Sprintf("%v", msg2["scn_msg_id"]))
|
||||
|
||||
@ -1046,7 +1131,7 @@ func TestSendCompat(t *testing.T) {
|
||||
|
||||
msg3 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
||||
"user_key": sendtok,
|
||||
"user_id": fmt.Sprintf("%d", uid),
|
||||
"user_id": fmt.Sprintf("%d", uidold),
|
||||
"title": "HelloWorld_003",
|
||||
"content": content3,
|
||||
"priority": "2",
|
||||
@ -1059,7 +1144,7 @@ func TestSendCompat(t *testing.T) {
|
||||
tt.AssertEqual(t, "messageCount", 3, len(pusher.Data))
|
||||
tt.AssertStrRepEqual(t, "msg.Title", "HelloWorld_003", pusher.Last().Message.Title)
|
||||
tt.AssertStrRepEqual(t, "msg.Content", content3, pusher.Last().Message.Content)
|
||||
tt.AssertStrRepEqual(t, "msg.SCNMessageID", msg3["scn_msg_id"], pusher.Last().Message.SCNMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.MessageID", msg3["scn_msg_id"], pusher.Last().Message.MessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.Priority", 2, pusher.Last().Message.Priority)
|
||||
tt.AssertStrRepEqual(t, "msg.UserMessageID", "8a2c7e92-86f3-4d69-897a-571286954030", pusher.Last().Message.UserMessageID)
|
||||
tt.AssertStrRepEqual(t, "msg.UserMessageID", ts3, pusher.Last().Message.Timestamp().Unix())
|
||||
@ -1077,7 +1162,7 @@ func TestSendToNewChannel(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -1086,7 +1171,7 @@ func TestSendToNewChannel(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
chan0 := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
chan0 := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertEqual(t, "chan-count", 0, len(chan0.Channels))
|
||||
}
|
||||
|
||||
@ -1097,7 +1182,7 @@ func TestSendToNewChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1111,7 +1196,7 @@ func TestSendToNewChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1125,7 +1210,7 @@ func TestSendToNewChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1138,7 +1223,7 @@ func TestSendToNewChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1155,7 +1240,7 @@ func TestSendToManualChannel(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
|
||||
@ -1164,7 +1249,7 @@ func TestSendToManualChannel(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1176,7 +1261,7 @@ func TestSendToManualChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1190,18 +1275,18 @@ func TestSendToManualChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertEqual(t, "chan.len", 1, len(clist.Channels))
|
||||
tt.AssertEqual(t, "chan.internal_name", "main", clist.Channels[0]["internal_name"])
|
||||
tt.AssertEqual(t, "chan.display_name", "main", clist.Channels[0]["display_name"])
|
||||
}
|
||||
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid), gin.H{
|
||||
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid), gin.H{
|
||||
"name": "test",
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1215,7 +1300,7 @@ func TestSendToManualChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1228,7 +1313,7 @@ func TestSendToManualChannel(t *testing.T) {
|
||||
})
|
||||
|
||||
{
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d/channels", uid))
|
||||
clist := tt.RequestAuthGet[chanlist](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s/channels", uid))
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "display_name")
|
||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_name")
|
||||
}
|
||||
@ -1245,7 +1330,7 @@ func TestSendToTooLongChannel(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
tt.RequestPost[tt.Void](t, baseUrl, "/", gin.H{
|
||||
@ -1281,7 +1366,7 @@ func TestQuotaExceededNoPro(t *testing.T) {
|
||||
"fcm_token": "DUMMY_FCM",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
@ -1300,7 +1385,7 @@ func TestQuotaExceededNoPro(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d", uid))
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s", uid))
|
||||
|
||||
tt.AssertStrRepEqual(t, "quota.1", 1, usr["quota_used"])
|
||||
tt.AssertStrRepEqual(t, "quota.1", 50, usr["quota_max"])
|
||||
@ -1317,7 +1402,7 @@ func TestQuotaExceededNoPro(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d", uid))
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s", uid))
|
||||
|
||||
tt.AssertStrRepEqual(t, "quota.49", 49, usr["quota_used"])
|
||||
tt.AssertStrRepEqual(t, "quota.49", 50, usr["quota_max"])
|
||||
@ -1333,7 +1418,7 @@ func TestQuotaExceededNoPro(t *testing.T) {
|
||||
tt.AssertStrRepEqual(t, "quota.msg.50", 50, msg50["quota_max"])
|
||||
|
||||
{
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d", uid))
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s", uid))
|
||||
|
||||
tt.AssertStrRepEqual(t, "quota.50", 50, usr["quota_used"])
|
||||
tt.AssertStrRepEqual(t, "quota.50", 50, usr["quota_max"])
|
||||
@ -1359,7 +1444,7 @@ func TestQuotaExceededPro(t *testing.T) {
|
||||
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
admintok := r0["admin_key"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
@ -1378,7 +1463,7 @@ func TestQuotaExceededPro(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d", uid))
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s", uid))
|
||||
|
||||
tt.AssertStrRepEqual(t, "quota.1", 1, usr["quota_used"])
|
||||
tt.AssertStrRepEqual(t, "quota.1", 1000, usr["quota_max"])
|
||||
@ -1395,7 +1480,7 @@ func TestQuotaExceededPro(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d", uid))
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s", uid))
|
||||
|
||||
tt.AssertStrRepEqual(t, "quota.999", 999, usr["quota_used"])
|
||||
tt.AssertStrRepEqual(t, "quota.999", 1000, usr["quota_max"])
|
||||
@ -1411,7 +1496,7 @@ func TestQuotaExceededPro(t *testing.T) {
|
||||
tt.AssertStrRepEqual(t, "quota.msg.1000", 1000, msg50["quota_max"])
|
||||
|
||||
{
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%d", uid))
|
||||
usr := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, fmt.Sprintf("/api/users/%s", uid))
|
||||
|
||||
tt.AssertStrRepEqual(t, "quota.1000", 1000, usr["quota_used"])
|
||||
tt.AssertStrRepEqual(t, "quota.1000", 1000, usr["quota_max"])
|
||||
@ -1437,7 +1522,7 @@ func TestSendParallel(t *testing.T) {
|
||||
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
||||
})
|
||||
|
||||
uid := int(r0["user_id"].(float64))
|
||||
uid := r0["user_id"].(string)
|
||||
sendtok := r0["send_key"].(string)
|
||||
|
||||
count := 128
|
||||
|
@ -59,7 +59,7 @@ type clientex struct {
|
||||
}
|
||||
|
||||
type Userdat struct {
|
||||
UID int64
|
||||
UID string
|
||||
SendKey string
|
||||
AdminKey string
|
||||
ReadKey string
|
||||
@ -319,7 +319,7 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
||||
}
|
||||
|
||||
user0 := RequestPost[gin.H](t, baseUrl, "/api/users", body)
|
||||
uid0 := int64(user0["user_id"].(float64))
|
||||
uid0 := user0["user_id"].(string)
|
||||
readtok0 := user0["read_key"].(string)
|
||||
sendtok0 := user0["send_key"].(string)
|
||||
admintok0 := user0["admin_key"].(string)
|
||||
@ -341,7 +341,7 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
||||
body["agent_version"] = cex.AgentVersion
|
||||
body["client_type"] = cex.ClientType
|
||||
body["fcm_token"] = cex.FCMTok
|
||||
RequestAuthPost[gin.H](t, users[cex.User].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/clients", users[cex.User].UID), body)
|
||||
RequestAuthPost[gin.H](t, users[cex.User].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/clients", users[cex.User].UID), body)
|
||||
}
|
||||
|
||||
// Create Messages
|
||||
@ -378,7 +378,7 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
||||
// create manual channels
|
||||
|
||||
{
|
||||
RequestAuthPost[Void](t, users[9].AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels", users[9].UID), gin.H{"name": "manual@chan"})
|
||||
RequestAuthPost[Void](t, users[9].AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels", users[9].UID), gin.H{"name": "manual@chan"})
|
||||
}
|
||||
|
||||
// Sub/Unsub for Users 12+13
|
||||
@ -399,7 +399,7 @@ func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat,
|
||||
|
||||
if user == chanOwner {
|
||||
|
||||
RequestAuthPost[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels", user.UID), gin.H{
|
||||
RequestAuthPost[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels", user.UID), gin.H{
|
||||
"channel_owner_user_id": chanOwner.UID,
|
||||
"channel_internal_name": chanInternalName,
|
||||
})
|
||||
@ -409,7 +409,7 @@ func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat,
|
||||
Channels []gin.H `json:"channels"`
|
||||
}
|
||||
|
||||
clist := RequestAuthGet[chanlist](t, chanOwner.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/channels?selector=owned", chanOwner.UID))
|
||||
clist := RequestAuthGet[chanlist](t, chanOwner.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/channels?selector=owned", chanOwner.UID))
|
||||
|
||||
var chandat gin.H
|
||||
for _, v := range clist.Channels {
|
||||
@ -419,8 +419,8 @@ func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat,
|
||||
}
|
||||
}
|
||||
|
||||
RequestAuthPost[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/subscriptions?chan_subscribe_key=%s", user.UID, chandat["subscribe_key"].(string)), gin.H{
|
||||
"channel_id": chandat["channel_id"].(float64),
|
||||
RequestAuthPost[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/subscriptions?chan_subscribe_key=%s", user.UID, chandat["subscribe_key"].(string)), gin.H{
|
||||
"channel_id": chandat["channel_id"].(string),
|
||||
})
|
||||
|
||||
}
|
||||
@ -433,17 +433,17 @@ func doUnsubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat
|
||||
Subscriptions []gin.H `json:"subscriptions"`
|
||||
}
|
||||
|
||||
slist := RequestAuthGet[chanlist](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/subscriptions?selector=outgoing_confirmed", user.UID))
|
||||
slist := RequestAuthGet[chanlist](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/subscriptions?selector=outgoing_confirmed", user.UID))
|
||||
|
||||
var subdat gin.H
|
||||
for _, v := range slist.Subscriptions {
|
||||
if v["channel_internal_name"].(string) == chanInternalName && int64(v["channel_owner_user_id"].(float64)) == chanOwner.UID {
|
||||
if v["channel_internal_name"].(string) == chanInternalName && v["channel_owner_user_id"].(string) == chanOwner.UID {
|
||||
subdat = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
RequestAuthDelete[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/subscriptions/%v", user.UID, subdat["subscription_id"]), gin.H{})
|
||||
RequestAuthDelete[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/subscriptions/%v", user.UID, subdat["subscription_id"]), gin.H{})
|
||||
|
||||
}
|
||||
|
||||
@ -453,17 +453,17 @@ func doAcceptSub(t *testing.T, baseUrl string, user Userdat, subscriber Userdat,
|
||||
Subscriptions []gin.H `json:"subscriptions"`
|
||||
}
|
||||
|
||||
slist := RequestAuthGet[chanlist](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/subscriptions?selector=incoming_unconfirmed", user.UID))
|
||||
slist := RequestAuthGet[chanlist](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/subscriptions?selector=incoming_unconfirmed", user.UID))
|
||||
|
||||
var subdat gin.H
|
||||
for _, v := range slist.Subscriptions {
|
||||
if v["channel_internal_name"].(string) == chanInternalName && int64(v["subscriber_user_id"].(float64)) == subscriber.UID {
|
||||
if v["channel_internal_name"].(string) == chanInternalName && v["subscriber_user_id"].(string) == subscriber.UID {
|
||||
subdat = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
RequestAuthPatch[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%d/subscriptions/%v", user.UID, subdat["subscription_id"]), gin.H{
|
||||
RequestAuthPatch[Void](t, user.AdminKey, baseUrl, fmt.Sprintf("/api/users/%s/subscriptions/%v", user.UID, subdat["subscription_id"]), gin.H{
|
||||
"confirmed": true,
|
||||
})
|
||||
|
||||
|
45
scnserver/test/util/internals.go
Normal file
45
scnserver/test/util/internals.go
Normal file
@ -0,0 +1,45 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ConvertToCompatID(t *testing.T, ws *logic.Application, newid string) int64 {
|
||||
|
||||
ctx := ws.NewSimpleTransactionContext(5 * time.Second)
|
||||
defer ctx.Cancel()
|
||||
|
||||
uidold, _, err := ws.Database.Primary.ConvertToCompatID(ctx, newid)
|
||||
TestFailIfErr(t, err)
|
||||
|
||||
if uidold == nil {
|
||||
TestFail(t, "faile to convert newid to oldid (compat)")
|
||||
}
|
||||
|
||||
err = ctx.CommitTransaction()
|
||||
if err != nil {
|
||||
TestFail(t, "failed to commit")
|
||||
return 0
|
||||
}
|
||||
|
||||
return *uidold
|
||||
}
|
||||
|
||||
func CreateCompatID(t *testing.T, ws *logic.Application, idtype string, newid string) int64 {
|
||||
|
||||
ctx := ws.NewSimpleTransactionContext(5 * time.Second)
|
||||
defer ctx.Cancel()
|
||||
|
||||
uidold, err := ws.Database.Primary.CreateCompatID(ctx, idtype, newid)
|
||||
TestFailIfErr(t, err)
|
||||
|
||||
err = ctx.CommitTransaction()
|
||||
if err != nil {
|
||||
TestFail(t, "failed to commit")
|
||||
return 0
|
||||
}
|
||||
|
||||
return uidold
|
||||
}
|
@ -124,14 +124,17 @@ func StartSimpleWebserver(t *testing.T) (*logic.Application, string, func()) {
|
||||
jobs.NewRequestLogCollectorJob(app),
|
||||
})
|
||||
|
||||
router.Init(ginengine)
|
||||
err = router.Init(ginengine)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stop := func() {
|
||||
app.Stop()
|
||||
_ = app.IsRunning.WaitWithTimeout(5*time.Second, false)
|
||||
_ = os.Remove(dbfile1)
|
||||
_ = os.Remove(dbfile2)
|
||||
_ = os.Remove(dbfile3)
|
||||
_ = app.IsRunning.WaitWithTimeout(400*time.Millisecond, false)
|
||||
}
|
||||
|
||||
go func() { app.Run() }()
|
||||
|
Loading…
Reference in New Issue
Block a user