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="processLiterals" value="true" />
|
||||||
<option name="processComments" value="true" />
|
<option name="processComments" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="SqlRedundantOrderingDirectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
@ -23,6 +23,8 @@
|
|||||||
-> how does it work with existing data?
|
-> how does it work with existing data?
|
||||||
-> do i care, there are only 2 active users... (are there?)
|
-> 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,
|
- error logging as goroutine, gets all errors via channel,
|
||||||
(channel buffered - nonblocking send, second channel that gets a message when sender failed )
|
(channel buffered - nonblocking send, second channel that gets a message when sender failed )
|
||||||
(then all errors end up in _second_ sqlite table)
|
(then all errors end up in _second_ sqlite table)
|
||||||
@ -57,8 +59,12 @@
|
|||||||
|
|
||||||
- (?) desktop client for notifications
|
- (?) desktop client for notifications
|
||||||
|
|
||||||
|
- (?) add querylog (similar to requestlog/errorlog) - only for main-db
|
||||||
|
|
||||||
#### LATER
|
#### LATER
|
||||||
|
|
||||||
|
- weblogin, webapp, ...
|
||||||
|
|
||||||
- Pagination for ListChannels / ListSubscriptions / ListClients / ListChannelSubscriptions / ListUserSubscriptions
|
- Pagination for ListChannels / ListSubscriptions / ListClients / ListChannelSubscriptions / ListUserSubscriptions
|
||||||
|
|
||||||
- cannot open sqlite in dbbrowsr (cannot parse schema?)
|
- cannot open sqlite in dbbrowsr (cannot parse schema?)
|
||||||
|
@ -151,7 +151,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid} [GET]
|
// @Router /api/users/{uid} [GET]
|
||||||
func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -200,7 +200,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid} [PATCH]
|
// @Router /api/users/{uid} [PATCH]
|
||||||
func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type body struct {
|
type body struct {
|
||||||
Username *string `json:"username"`
|
Username *string `json:"username"`
|
||||||
@ -306,7 +306,7 @@ func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/clients [GET]
|
// @Router /api/users/{uid}/clients [GET]
|
||||||
func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type response struct {
|
type response struct {
|
||||||
Clients []models.ClientJSON `json:"clients"`
|
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]
|
// @Router /api/users/{uid}/clients/{cid} [GET]
|
||||||
func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
ClientID models.ClientID `uri:"cid"`
|
ClientID models.ClientID `uri:"cid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -395,7 +395,7 @@ func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/clients [POST]
|
// @Router /api/users/{uid}/clients [POST]
|
||||||
func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type body struct {
|
type body struct {
|
||||||
FCMToken string `json:"fcm_token" binding:"required"`
|
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]
|
// @Router /api/users/{uid}/clients/{cid} [DELETE]
|
||||||
func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
ClientID models.ClientID `uri:"cid"`
|
ClientID models.ClientID `uri:"cid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -511,7 +511,7 @@ func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/channels [GET]
|
// @Router /api/users/{uid}/channels [GET]
|
||||||
func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type query struct {
|
type query struct {
|
||||||
Selector *string `json:"selector" form:"selector" enums:"owned,subscribed_any,all_any,subscribed,all"`
|
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]
|
// @Router /api/users/{uid}/channels/{cid} [GET]
|
||||||
func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
ChannelID models.ChannelID `uri:"cid"`
|
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -647,7 +647,7 @@ func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/channels [POST]
|
// @Router /api/users/{uid}/channels [POST]
|
||||||
func (h APIHandler) CreateChannel(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) CreateChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type body struct {
|
type body struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@ -744,8 +744,8 @@ func (h APIHandler) CreateChannel(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/channels/{cid} [PATCH]
|
// @Router /api/users/{uid}/channels/{cid} [PATCH]
|
||||||
func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
ChannelID models.ChannelID `uri:"cid"`
|
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type body struct {
|
type body struct {
|
||||||
RefreshSubscribeKey *bool `json:"subscribe_key"`
|
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]
|
// @Router /api/users/{uid}/channels/{cid}/messages [GET]
|
||||||
func (h APIHandler) ListChannelMessages(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) ListChannelMessages(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
ChannelUserID models.UserID `uri:"uid"`
|
ChannelUserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
ChannelID models.ChannelID `uri:"cid"`
|
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type query struct {
|
type query struct {
|
||||||
PageSize *int `json:"page_size" form:"page_size"`
|
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]
|
// @Router /api/users/{uid}/subscriptions [GET]
|
||||||
func (h APIHandler) ListUserSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) ListUserSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type query struct {
|
type query struct {
|
||||||
Selector *string `json:"selector" form:"selector" enums:"owner_all,owner_confirmed,owner_unconfirmed,incoming_all,incoming_confirmed,incoming_unconfirmed"`
|
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]
|
// @Router /api/users/{uid}/channels/{cid}/subscriptions [GET]
|
||||||
func (h APIHandler) ListChannelSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) ListChannelSubscriptions(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
ChannelID models.ChannelID `uri:"cid"`
|
ChannelID models.ChannelID `uri:"cid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type response struct {
|
type response struct {
|
||||||
Subscriptions []models.SubscriptionJSON `json:"subscriptions"`
|
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]
|
// @Router /api/users/{uid}/subscriptions/{sid} [GET]
|
||||||
func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
SubscriptionID models.SubscriptionID `uri:"sid"`
|
SubscriptionID models.SubscriptionID `uri:"sid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -1170,8 +1170,8 @@ func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/subscriptions/{sid} [DELETE]
|
// @Router /api/users/{uid}/subscriptions/{sid} [DELETE]
|
||||||
func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
SubscriptionID models.SubscriptionID `uri:"sid"`
|
SubscriptionID models.SubscriptionID `uri:"sid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -1223,12 +1223,12 @@ func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Router /api/users/{uid}/subscriptions [POST]
|
// @Router /api/users/{uid}/subscriptions [POST]
|
||||||
func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type body struct {
|
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"`
|
ChannelInternalName *string `json:"channel_internal_name"`
|
||||||
ChannelID *models.ChannelID `json:"channel_id"`
|
ChannelID *models.ChannelID `json:"channel_id" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type query struct {
|
type query struct {
|
||||||
ChanSubscribeKey *string `json:"chan_subscribe_key" form:"chan_subscribe_key"`
|
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]
|
// @Router /api/users/{uid}/subscriptions/{sid} [PATCH]
|
||||||
func (h APIHandler) UpdateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) UpdateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
UserID models.UserID `uri:"uid"`
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
SubscriptionID models.SubscriptionID `uri:"sid"`
|
SubscriptionID models.SubscriptionID `uri:"sid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
type body struct {
|
type body struct {
|
||||||
Confirmed *bool `form:"confirmed"`
|
Confirmed *bool `form:"confirmed"`
|
||||||
@ -1454,7 +1454,7 @@ func (h APIHandler) ListMessages(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-messages-get
|
// @ID api-messages-get
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param mid path int true "SCNMessageID"
|
// @Param mid path int true "MessageID"
|
||||||
//
|
//
|
||||||
// @Success 200 {object} models.MessageJSON
|
// @Success 200 {object} models.MessageJSON
|
||||||
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
// @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]
|
// @Router /api/messages/{mid} [PATCH]
|
||||||
func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
MessageID models.SCNMessageID `uri:"mid"`
|
MessageID models.MessageID `uri:"mid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
var u uri
|
||||||
@ -1524,7 +1524,7 @@ func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-messages-delete
|
// @ID api-messages-delete
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param mid path int true "SCNMessageID"
|
// @Param mid path int true "MessageID"
|
||||||
//
|
//
|
||||||
// @Success 200 {object} models.MessageJSON
|
// @Success 200 {object} models.MessageJSON
|
||||||
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
// @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]
|
// @Router /api/messages/{mid} [DELETE]
|
||||||
func (h APIHandler) DeleteMessage(g *gin.Context) ginresp.HTTPResponse {
|
func (h APIHandler) DeleteMessage(g *gin.Context) ginresp.HTTPResponse {
|
||||||
type uri struct {
|
type uri struct {
|
||||||
MessageID models.SCNMessageID `uri:"mid"`
|
MessageID models.MessageID `uri:"mid" binding:"entityid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var u uri
|
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)
|
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 {
|
if err != nil {
|
||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to delete message", err)
|
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 {
|
if err != nil {
|
||||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to cancel deliveries", err)
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to cancel deliveries", err)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||||
|
hl "blackforestbytes.com/simplecloudnotifier/api/apihighlight"
|
||||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||||
primarydb "blackforestbytes.com/simplecloudnotifier/db/impl/primary"
|
primarydb "blackforestbytes.com/simplecloudnotifier/db/impl/primary"
|
||||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
"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
|
// Register swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Register a new account
|
// @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")
|
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{
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "New user registered",
|
Message: "New user registered",
|
||||||
UserID: user.UserID.IntID(),
|
UserID: oldid,
|
||||||
UserKey: user.AdminKey,
|
UserKey: user.AdminKey,
|
||||||
QuotaUsed: user.QuotaUsedToday(),
|
QuotaUsed: user.QuotaUsedToday(),
|
||||||
QuotaMax: user.QuotaPerDay(),
|
QuotaMax: user.QuotaPerDay(),
|
||||||
@ -184,7 +241,15 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(201, "User not found")
|
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{
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "ok",
|
Message: "ok",
|
||||||
UserID: user.UserID.IntID(),
|
UserID: *data.UserID,
|
||||||
UserKey: user.AdminKey,
|
UserKey: user.AdminKey,
|
||||||
QuotaUsed: user.QuotaUsedToday(),
|
QuotaUsed: user.QuotaUsedToday(),
|
||||||
QuotaMax: user.QuotaPerDay(),
|
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]]")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(201, "User not found")
|
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]]")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(201, "User not found")
|
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]]")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(201, "User not found")
|
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{
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "user updated",
|
Message: "user updated",
|
||||||
UserID: user.UserID.IntID(),
|
UserID: *data.UserID,
|
||||||
UserKey: user.AdminKey,
|
UserKey: user.AdminKey,
|
||||||
QuotaUsed: user.QuotaUsedToday(),
|
QuotaUsed: user.QuotaUsedToday(),
|
||||||
QuotaMax: user.QuotaPerDay(),
|
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]]")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(201, "User not found")
|
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")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(301, "Message not found")
|
return ginresp.CompatAPIError(301, "Message not found")
|
||||||
}
|
}
|
||||||
@ -551,7 +656,7 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
Priority: msg.Priority,
|
Priority: msg.Priority,
|
||||||
Timestamp: msg.Timestamp().Unix(),
|
Timestamp: msg.Timestamp().Unix(),
|
||||||
UserMessageID: msg.UserMessageID,
|
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]]")
|
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 {
|
if err == sql.ErrNoRows {
|
||||||
return ginresp.CompatAPIError(201, "User not found")
|
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{
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "user updated",
|
Message: "user updated",
|
||||||
UserID: user.UserID.IntID(),
|
UserID: *data.UserID,
|
||||||
QuotaUsed: user.QuotaUsedToday(),
|
QuotaUsed: user.QuotaUsedToday(),
|
||||||
QuotaMax: user.QuotaPerDay(),
|
QuotaMax: user.QuotaPerDay(),
|
||||||
IsPro: user.IsPro,
|
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
|
// SendMessage swaggerdoc
|
||||||
//
|
//
|
||||||
// @Summary Send a new message
|
// @Summary Send a new message
|
||||||
@ -132,7 +90,7 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
|||||||
Quota int `json:"quota"`
|
Quota int `json:"quota"`
|
||||||
IsPro bool `json:"is_pro"`
|
IsPro bool `json:"is_pro"`
|
||||||
QuotaMax int `json:"quota_max"`
|
QuotaMax int `json:"quota_max"`
|
||||||
SCNMessageID models.SCNMessageID `json:"scn_msg_id"`
|
SCNMessageID models.MessageID `json:"scn_msg_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if Title != nil {
|
if Title != nil {
|
||||||
@ -212,7 +170,7 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
|||||||
Quota: user.QuotaUsedToday(),
|
Quota: user.QuotaUsedToday(),
|
||||||
IsPro: user.IsPro,
|
IsPro: user.IsPro,
|
||||||
QuotaMax: user.QuotaPerDay(),
|
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,
|
Quota: user.QuotaUsedToday() + 1,
|
||||||
IsPro: user.IsPro,
|
IsPro: user.IsPro,
|
||||||
QuotaMax: user.QuotaPerDay(),
|
QuotaMax: user.QuotaPerDay(),
|
||||||
SCNMessageID: msg.SCNMessageID,
|
SCNMessageID: msg.MessageID,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,12 @@ import (
|
|||||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||||
"blackforestbytes.com/simplecloudnotifier/api/handler"
|
"blackforestbytes.com/simplecloudnotifier/api/handler"
|
||||||
"blackforestbytes.com/simplecloudnotifier/logic"
|
"blackforestbytes.com/simplecloudnotifier/logic"
|
||||||
|
"blackforestbytes.com/simplecloudnotifier/models"
|
||||||
"blackforestbytes.com/simplecloudnotifier/swagger"
|
"blackforestbytes.com/simplecloudnotifier/swagger"
|
||||||
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
@ -44,7 +48,16 @@ func NewRouter(app *logic.Application) *Router {
|
|||||||
// @tag.name Common
|
// @tag.name Common
|
||||||
//
|
//
|
||||||
// @BasePath /
|
// @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 ================
|
// ================ General ================
|
||||||
|
|
||||||
@ -94,7 +107,7 @@ func (r *Router) Init(e *gin.Engine) {
|
|||||||
|
|
||||||
// ================ Compat (v1) ================
|
// ================ Compat (v1) ================
|
||||||
|
|
||||||
compat := e.Group("/api/")
|
compat := e.Group("/api")
|
||||||
{
|
{
|
||||||
compat.GET("/register.php", r.Wrap(r.compatHandler.Register))
|
compat.GET("/register.php", r.Wrap(r.compatHandler.Register))
|
||||||
compat.GET("/info.php", r.Wrap(r.compatHandler.Info))
|
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))
|
e.NoRoute(r.Wrap(r.commonHandler.NoRoute))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ================
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Wrap(fn ginresp.WHandlerFunc) gin.HandlerFunc {
|
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})
|
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()
|
app.Run()
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ type DBConfig struct {
|
|||||||
ConnMaxIdleTime time.Duration `env:"CONNEXTIONMAXIDLETIME"`
|
ConnMaxIdleTime time.Duration `env:"CONNEXTIONMAXIDLETIME"`
|
||||||
CheckForeignKeys bool `env:"CHECKFOREIGNKEYS"`
|
CheckForeignKeys bool `env:"CHECKFOREIGNKEYS"`
|
||||||
SingleConn bool `env:"SINGLECONNECTION"`
|
SingleConn bool `env:"SINGLECONNECTION"`
|
||||||
|
BusyTimeout time.Duration `env:"BUSYTIMEOUT"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var Conf Config
|
var Conf Config
|
||||||
@ -76,6 +77,7 @@ var configLocHost = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 100 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBRequests: DBConfig{
|
DBRequests: DBConfig{
|
||||||
File: ".run-data/loc_requests.sqlite3",
|
File: ".run-data/loc_requests.sqlite3",
|
||||||
@ -87,6 +89,7 @@ var configLocHost = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBLogs: DBConfig{
|
DBLogs: DBConfig{
|
||||||
File: ".run-data/loc_logs.sqlite3",
|
File: ".run-data/loc_logs.sqlite3",
|
||||||
@ -98,6 +101,7 @@ var configLocHost = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
RequestTimeout: 16 * time.Second,
|
RequestTimeout: 16 * time.Second,
|
||||||
RequestMaxRetry: 8,
|
RequestMaxRetry: 8,
|
||||||
@ -142,6 +146,7 @@ var configLocDocker = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 100 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBRequests: DBConfig{
|
DBRequests: DBConfig{
|
||||||
File: "/data/docker_scn_requests.sqlite3",
|
File: "/data/docker_scn_requests.sqlite3",
|
||||||
@ -153,6 +158,7 @@ var configLocDocker = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBLogs: DBConfig{
|
DBLogs: DBConfig{
|
||||||
File: "/data/docker_scn_logs.sqlite3",
|
File: "/data/docker_scn_logs.sqlite3",
|
||||||
@ -164,6 +170,7 @@ var configLocDocker = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
RequestTimeout: 16 * time.Second,
|
RequestTimeout: 16 * time.Second,
|
||||||
RequestMaxRetry: 8,
|
RequestMaxRetry: 8,
|
||||||
@ -207,6 +214,7 @@ var configDev = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 100 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBRequests: DBConfig{
|
DBRequests: DBConfig{
|
||||||
File: "/data/scn_requests.sqlite3",
|
File: "/data/scn_requests.sqlite3",
|
||||||
@ -218,6 +226,7 @@ var configDev = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBLogs: DBConfig{
|
DBLogs: DBConfig{
|
||||||
File: "/data/scn_logs.sqlite3",
|
File: "/data/scn_logs.sqlite3",
|
||||||
@ -229,6 +238,7 @@ var configDev = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
RequestTimeout: 16 * time.Second,
|
RequestTimeout: 16 * time.Second,
|
||||||
RequestMaxRetry: 8,
|
RequestMaxRetry: 8,
|
||||||
@ -272,6 +282,7 @@ var configStag = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 100 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBRequests: DBConfig{
|
DBRequests: DBConfig{
|
||||||
File: "/data/scn_requests.sqlite3",
|
File: "/data/scn_requests.sqlite3",
|
||||||
@ -283,6 +294,7 @@ var configStag = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBLogs: DBConfig{
|
DBLogs: DBConfig{
|
||||||
File: "/data/scn_logs.sqlite3",
|
File: "/data/scn_logs.sqlite3",
|
||||||
@ -294,6 +306,7 @@ var configStag = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
RequestTimeout: 16 * time.Second,
|
RequestTimeout: 16 * time.Second,
|
||||||
RequestMaxRetry: 8,
|
RequestMaxRetry: 8,
|
||||||
@ -337,6 +350,7 @@ var configProd = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 100 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBRequests: DBConfig{
|
DBRequests: DBConfig{
|
||||||
File: "/data/scn_requests.sqlite3",
|
File: "/data/scn_requests.sqlite3",
|
||||||
@ -348,6 +362,7 @@ var configProd = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
DBLogs: DBConfig{
|
DBLogs: DBConfig{
|
||||||
File: "/data/scn_logs.sqlite3",
|
File: "/data/scn_logs.sqlite3",
|
||||||
@ -359,6 +374,7 @@ var configProd = func() Config {
|
|||||||
MaxIdleConns: 5,
|
MaxIdleConns: 5,
|
||||||
ConnMaxLifetime: 60 * time.Minute,
|
ConnMaxLifetime: 60 * time.Minute,
|
||||||
ConnMaxIdleTime: 60 * time.Minute,
|
ConnMaxIdleTime: 60 * time.Minute,
|
||||||
|
BusyTimeout: 500 * time.Millisecond,
|
||||||
},
|
},
|
||||||
RequestTimeout: 16 * time.Second,
|
RequestTimeout: 16 * time.Second,
|
||||||
RequestMaxRetry: 8,
|
RequestMaxRetry: 8,
|
||||||
|
@ -19,14 +19,14 @@ const (
|
|||||||
type CursorToken struct {
|
type CursorToken struct {
|
||||||
Mode Mode
|
Mode Mode
|
||||||
Timestamp int64
|
Timestamp int64
|
||||||
Id int64
|
Id string
|
||||||
Direction string
|
Direction string
|
||||||
FilterHash string
|
FilterHash string
|
||||||
}
|
}
|
||||||
|
|
||||||
type cursorTokenSerialize struct {
|
type cursorTokenSerialize struct {
|
||||||
Timestamp *int64 `json:"ts,omitempty"`
|
Timestamp *int64 `json:"ts,omitempty"`
|
||||||
Id *int64 `json:"id,omitempty"`
|
Id *string `json:"id,omitempty"`
|
||||||
Direction *string `json:"dir,omitempty"`
|
Direction *string `json:"dir,omitempty"`
|
||||||
FilterHash *string `json:"f,omitempty"`
|
FilterHash *string `json:"f,omitempty"`
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func Start() CursorToken {
|
|||||||
return CursorToken{
|
return CursorToken{
|
||||||
Mode: CTMStart,
|
Mode: CTMStart,
|
||||||
Timestamp: 0,
|
Timestamp: 0,
|
||||||
Id: 0,
|
Id: "",
|
||||||
Direction: "",
|
Direction: "",
|
||||||
FilterHash: "",
|
FilterHash: "",
|
||||||
}
|
}
|
||||||
@ -45,13 +45,13 @@ func End() CursorToken {
|
|||||||
return CursorToken{
|
return CursorToken{
|
||||||
Mode: CTMEnd,
|
Mode: CTMEnd,
|
||||||
Timestamp: 0,
|
Timestamp: 0,
|
||||||
Id: 0,
|
Id: "",
|
||||||
Direction: "",
|
Direction: "",
|
||||||
FilterHash: "",
|
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{
|
return CursorToken{
|
||||||
Mode: CTMNormal,
|
Mode: CTMNormal,
|
||||||
Timestamp: ts.UnixMilli(),
|
Timestamp: ts.UnixMilli(),
|
||||||
@ -76,7 +76,7 @@ func (c *CursorToken) Token() string {
|
|||||||
|
|
||||||
sertok := cursorTokenSerialize{}
|
sertok := cursorTokenSerialize{}
|
||||||
|
|
||||||
if c.Id != 0 {
|
if c.Id != "" {
|
||||||
sertok.Id = &c.Id
|
sertok.Id = &c.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ type Database struct {
|
|||||||
func NewLogsDatabase(cfg server.Config) (*Database, error) {
|
func NewLogsDatabase(cfg server.Config) (*Database, error) {
|
||||||
conf := cfg.DBLogs
|
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)
|
xdb, err := sqlx.Open("sqlite3", url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
CREATE TABLE `logs`
|
CREATE TABLE `logs`
|
||||||
(
|
(
|
||||||
log_id INTEGER PRIMARY KEY,
|
log_id TEXT NOT NULL,
|
||||||
timestamp_created INTEGER NOT NULL
|
timestamp_created INTEGER NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (log_id)
|
||||||
) STRICT;
|
) STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +89,10 @@ func (db *Database) CreateChannel(ctx TxContext, userid models.UserID, dispName
|
|||||||
|
|
||||||
now := time.Now().UTC()
|
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,
|
"ouid": userid,
|
||||||
"dnam": dispName,
|
"dnam": dispName,
|
||||||
"inam": intName,
|
"inam": intName,
|
||||||
@ -101,13 +104,8 @@ func (db *Database) CreateChannel(ctx TxContext, userid models.UserID, dispName
|
|||||||
return models.Channel{}, err
|
return models.Channel{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.Channel{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Channel{
|
return models.Channel{
|
||||||
ChannelID: models.ChannelID(liid),
|
ChannelID: channelid,
|
||||||
OwnerUserID: userid,
|
OwnerUserID: userid,
|
||||||
DisplayName: dispName,
|
DisplayName: dispName,
|
||||||
InternalName: intName,
|
InternalName: intName,
|
||||||
@ -125,7 +123,9 @@ func (db *Database) ListChannelsByOwner(ctx TxContext, userid models.UserID, sub
|
|||||||
return nil, err
|
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,
|
"ouid": userid,
|
||||||
"subuid": subUserID,
|
"subuid": subUserID,
|
||||||
})
|
})
|
||||||
@ -154,7 +154,9 @@ func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid models.UserID
|
|||||||
confCond = " AND sub.confirmed = 0"
|
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,
|
"subuid": userid,
|
||||||
})
|
})
|
||||||
if err != nil {
|
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)"
|
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,
|
"ouid": userid,
|
||||||
"subuid": userid,
|
"subuid": userid,
|
||||||
})
|
})
|
||||||
|
@ -15,7 +15,10 @@ func (db *Database) CreateClient(ctx TxContext, userid models.UserID, ctype mode
|
|||||||
|
|
||||||
now := time.Now().UTC()
|
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,
|
"uid": userid,
|
||||||
"typ": string(ctype),
|
"typ": string(ctype),
|
||||||
"fcm": fcmToken,
|
"fcm": fcmToken,
|
||||||
@ -27,13 +30,8 @@ func (db *Database) CreateClient(ctx TxContext, userid models.UserID, ctype mode
|
|||||||
return models.Client{}, err
|
return models.Client{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.Client{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Client{
|
return models.Client{
|
||||||
ClientID: models.ClientID(liid),
|
ClientID: clientid,
|
||||||
UserID: userid,
|
UserID: userid,
|
||||||
Type: ctype,
|
Type: ctype,
|
||||||
FCMToken: langext.Ptr(fcmToken),
|
FCMToken: langext.Ptr(fcmToken),
|
||||||
@ -63,7 +61,7 @@ func (db *Database) ListClients(ctx TxContext, userid models.UserID) ([]models.C
|
|||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
func NewPrimaryDatabase(cfg server.Config) (*Database, error) {
|
||||||
conf := cfg.DBMain
|
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)
|
xdb, err := sqlx.Open("sqlite3", url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -17,8 +17,11 @@ func (db *Database) CreateRetryDelivery(ctx TxContext, client models.Client, msg
|
|||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
next := scn.NextDeliveryTimestamp(now)
|
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{
|
deliveryid := models.NewDeliveryID()
|
||||||
"mid": msg.SCNMessageID,
|
|
||||||
|
_, 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,
|
"ruid": client.UserID,
|
||||||
"rcid": client.ClientID,
|
"rcid": client.ClientID,
|
||||||
"tsc": time2DB(now),
|
"tsc": time2DB(now),
|
||||||
@ -31,14 +34,9 @@ func (db *Database) CreateRetryDelivery(ctx TxContext, client models.Client, msg
|
|||||||
return models.Delivery{}, err
|
return models.Delivery{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.Delivery{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Delivery{
|
return models.Delivery{
|
||||||
DeliveryID: models.DeliveryID(liid),
|
DeliveryID: deliveryid,
|
||||||
SCNMessageID: msg.SCNMessageID,
|
MessageID: msg.MessageID,
|
||||||
ReceiverUserID: client.UserID,
|
ReceiverUserID: client.UserID,
|
||||||
ReceiverClientID: client.ClientID,
|
ReceiverClientID: client.ClientID,
|
||||||
TimestampCreated: now,
|
TimestampCreated: now,
|
||||||
@ -58,8 +56,11 @@ func (db *Database) CreateSuccessDelivery(ctx TxContext, client models.Client, m
|
|||||||
|
|
||||||
now := time.Now().UTC()
|
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{
|
deliveryid := models.NewDeliveryID()
|
||||||
"mid": msg.SCNMessageID,
|
|
||||||
|
_, 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,
|
"ruid": client.UserID,
|
||||||
"rcid": client.ClientID,
|
"rcid": client.ClientID,
|
||||||
"tsc": time2DB(now),
|
"tsc": time2DB(now),
|
||||||
@ -72,14 +73,9 @@ func (db *Database) CreateSuccessDelivery(ctx TxContext, client models.Client, m
|
|||||||
return models.Delivery{}, err
|
return models.Delivery{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.Delivery{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Delivery{
|
return models.Delivery{
|
||||||
DeliveryID: models.DeliveryID(liid),
|
DeliveryID: deliveryid,
|
||||||
SCNMessageID: msg.SCNMessageID,
|
MessageID: msg.MessageID,
|
||||||
ReceiverUserID: client.UserID,
|
ReceiverUserID: client.UserID,
|
||||||
ReceiverClientID: client.ClientID,
|
ReceiverClientID: client.ClientID,
|
||||||
TimestampCreated: now,
|
TimestampCreated: now,
|
||||||
@ -97,7 +93,7 @@ func (db *Database) ListRetrieableDeliveries(ctx TxContext, pageSize int) ([]mod
|
|||||||
return nil, err
|
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()),
|
"next": time2DB(time.Now()),
|
||||||
"lim": pageSize,
|
"lim": pageSize,
|
||||||
})
|
})
|
||||||
@ -169,15 +165,15 @@ func (db *Database) SetDeliveryRetry(ctx TxContext, delivery models.Delivery) er
|
|||||||
return nil
|
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)
|
tx, err := ctx.GetOrCreateTransaction(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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(),
|
"ts": time.Now(),
|
||||||
"mid": scnMessageID,
|
"mid": messageID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,7 +30,7 @@ func (db *Database) GetMessageByUserMessageID(ctx TxContext, usrMsgId string) (*
|
|||||||
return &msg, nil
|
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)
|
tx, err := ctx.GetOrCreateTransaction(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Message{}, err
|
return models.Message{}, err
|
||||||
@ -38,9 +38,9 @@ func (db *Database) GetMessage(ctx TxContext, scnMessageID models.SCNMessageID,
|
|||||||
|
|
||||||
var sqlcmd string
|
var sqlcmd string
|
||||||
if allowDeleted {
|
if allowDeleted {
|
||||||
sqlcmd = "SELECT * FROM messages WHERE scn_message_id = :mid LIMIT 1"
|
sqlcmd = "SELECT * FROM messages WHERE message_id = :mid LIMIT 1"
|
||||||
} else {
|
} 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})
|
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()
|
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,
|
"suid": senderUserID,
|
||||||
"ouid": channel.OwnerUserID,
|
"ouid": channel.OwnerUserID,
|
||||||
"cnam": channel.InternalName,
|
"cnam": channel.InternalName,
|
||||||
@ -82,13 +85,8 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID models.UserID, cha
|
|||||||
return models.Message{}, err
|
return models.Message{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.Message{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Message{
|
return models.Message{
|
||||||
SCNMessageID: models.SCNMessageID(liid),
|
MessageID: messageid,
|
||||||
SenderUserID: senderUserID,
|
SenderUserID: senderUserID,
|
||||||
OwnerUserID: channel.OwnerUserID,
|
OwnerUserID: channel.OwnerUserID,
|
||||||
ChannelInternalName: channel.InternalName,
|
ChannelInternalName: channel.InternalName,
|
||||||
@ -104,13 +102,13 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID models.UserID, cha
|
|||||||
}, nil
|
}, 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)
|
tx, err := ctx.GetOrCreateTransaction(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -130,12 +128,12 @@ func (db *Database) ListMessages(ctx TxContext, filter models.MessageFilter, pag
|
|||||||
|
|
||||||
pageCond := "1=1"
|
pageCond := "1=1"
|
||||||
if inTok.Mode == cursortoken.CTMNormal {
|
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()
|
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
|
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 {
|
if len(data) <= pageSize {
|
||||||
return data, cursortoken.End(), nil
|
return data, cursortoken.End(), nil
|
||||||
} else {
|
} 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
|
return data[0:pageSize], outToken, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ CREATE TABLE `users`
|
|||||||
DROP TABLE IF EXISTS `messages`;
|
DROP TABLE IF EXISTS `messages`;
|
||||||
CREATE TABLE `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,
|
`sender_user_id` INT(11) NOT NULL,
|
||||||
|
|
||||||
`timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@ -34,5 +34,5 @@ CREATE TABLE `messages`
|
|||||||
`fcm_message_id` VARCHAR(256) NULL,
|
`fcm_message_id` VARCHAR(256) NULL,
|
||||||
`usr_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`
|
CREATE TABLE `messages`
|
||||||
(
|
(
|
||||||
`scn_message_id` INTEGER AUTO_INCREMENT,
|
`message_id` INTEGER AUTO_INCREMENT,
|
||||||
`sender_user_id` INTEGER NOT NULL,
|
`sender_user_id` INTEGER NOT NULL,
|
||||||
|
|
||||||
`timestamp_real` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`timestamp_real` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@ -32,7 +32,7 @@ CREATE TABLE `messages`
|
|||||||
`fcm_message_id` TEXT NULL,
|
`fcm_message_id` TEXT NULL,
|
||||||
`usr_message_id` TEXT NULL,
|
`usr_message_id` TEXT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`scn_message_id`)
|
PRIMARY KEY (`message_id`)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE `meta`
|
CREATE TABLE `meta`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
CREATE TABLE users
|
CREATE TABLE users
|
||||||
(
|
(
|
||||||
user_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
user_id TEXT NOT NULL,
|
||||||
|
|
||||||
username TEXT NULL DEFAULT NULL,
|
username TEXT NULL DEFAULT NULL,
|
||||||
|
|
||||||
@ -18,23 +18,27 @@ CREATE TABLE users
|
|||||||
quota_used_day TEXT NULL DEFAULT NULL,
|
quota_used_day TEXT NULL DEFAULT NULL,
|
||||||
|
|
||||||
is_pro INTEGER CHECK(is_pro IN (0, 1)) NOT NULL DEFAULT 0,
|
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;
|
) STRICT;
|
||||||
CREATE UNIQUE INDEX "idx_users_protoken" ON users (pro_token) WHERE pro_token IS NOT NULL;
|
CREATE UNIQUE INDEX "idx_users_protoken" ON users (pro_token) WHERE pro_token IS NOT NULL;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE clients
|
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,
|
type TEXT CHECK(type IN ('ANDROID', 'IOS')) NOT NULL,
|
||||||
fcm_token TEXT NULL,
|
fcm_token TEXT NULL,
|
||||||
|
|
||||||
timestamp_created INTEGER NOT NULL,
|
timestamp_created INTEGER NOT NULL,
|
||||||
|
|
||||||
agent_model TEXT NOT NULL,
|
agent_model TEXT NOT NULL,
|
||||||
agent_version TEXT NOT NULL
|
agent_version TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (client_id)
|
||||||
) STRICT;
|
) STRICT;
|
||||||
CREATE INDEX "idx_clients_userid" ON clients (user_id);
|
CREATE INDEX "idx_clients_userid" ON clients (user_id);
|
||||||
CREATE UNIQUE INDEX "idx_clients_fcmtoken" ON clients (fcm_token);
|
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
|
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,
|
internal_name TEXT NOT NULL,
|
||||||
display_name TEXT NOT NULL,
|
display_name TEXT NOT NULL,
|
||||||
@ -56,22 +60,26 @@ CREATE TABLE channels
|
|||||||
timestamp_created INTEGER NOT NULL,
|
timestamp_created INTEGER NOT NULL,
|
||||||
timestamp_lastsent INTEGER NULL DEFAULT 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;
|
) STRICT;
|
||||||
CREATE UNIQUE INDEX "idx_channels_identity" ON channels (owner_user_id, internal_name);
|
CREATE UNIQUE INDEX "idx_channels_identity" ON channels (owner_user_id, internal_name);
|
||||||
|
|
||||||
CREATE TABLE subscriptions
|
CREATE TABLE subscriptions
|
||||||
(
|
(
|
||||||
subscription_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
subscription_id TEXT NOT NULL,
|
||||||
|
|
||||||
subscriber_user_id INTEGER NOT NULL,
|
subscriber_user_id TEXT NOT NULL,
|
||||||
channel_owner_user_id INTEGER NOT NULL,
|
channel_owner_user_id TEXT NOT NULL,
|
||||||
channel_internal_name TEXT NOT NULL,
|
channel_internal_name TEXT NOT NULL,
|
||||||
channel_id INTEGER NOT NULL,
|
channel_id TEXT NOT NULL,
|
||||||
|
|
||||||
timestamp_created INTEGER 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;
|
) STRICT;
|
||||||
CREATE UNIQUE INDEX "idx_subscriptions_ref" ON subscriptions (subscriber_user_id, channel_owner_user_id, channel_internal_name);
|
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);
|
CREATE INDEX "idx_subscriptions_chan" ON subscriptions (channel_id);
|
||||||
@ -83,11 +91,11 @@ CREATE INDEX "idx_subscriptions_conf" ON subscriptions (confirmed);
|
|||||||
|
|
||||||
CREATE TABLE messages
|
CREATE TABLE messages
|
||||||
(
|
(
|
||||||
scn_message_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
message_id TEXT NOT NULL,
|
||||||
sender_user_id INTEGER NOT NULL,
|
sender_user_id TEXT NOT NULL,
|
||||||
owner_user_id INTEGER NOT NULL,
|
owner_user_id TEXT NOT NULL,
|
||||||
channel_internal_name 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_ip TEXT NOT NULL,
|
||||||
sender_name TEXT NULL,
|
sender_name TEXT NULL,
|
||||||
|
|
||||||
@ -99,7 +107,9 @@ CREATE TABLE messages
|
|||||||
priority INTEGER CHECK(priority IN (0, 1, 2)) NOT NULL,
|
priority INTEGER CHECK(priority IN (0, 1, 2)) NOT NULL,
|
||||||
usr_message_id TEXT 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;
|
) STRICT;
|
||||||
CREATE INDEX "idx_messages_owner_channel" ON messages (owner_user_id, channel_internal_name COLLATE BINARY);
|
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);
|
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,
|
tokenize = unicode61,
|
||||||
content = 'messages',
|
content = 'messages',
|
||||||
content_rowid = 'scn_message_id'
|
content_rowid = 'rowid'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TRIGGER fts_insert AFTER INSERT ON messages BEGIN
|
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;
|
END;
|
||||||
|
|
||||||
CREATE TRIGGER fts_update AFTER UPDATE ON messages BEGIN
|
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 (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.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;
|
END;
|
||||||
|
|
||||||
CREATE TRIGGER fts_delete AFTER DELETE ON messages BEGIN
|
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;
|
END;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE deliveries
|
CREATE TABLE deliveries
|
||||||
(
|
(
|
||||||
delivery_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
delivery_id TEXT NOT NULL,
|
||||||
|
|
||||||
scn_message_id INTEGER NOT NULL,
|
message_id TEXT NOT NULL,
|
||||||
receiver_user_id INTEGER NOT NULL,
|
receiver_user_id TEXT NOT NULL,
|
||||||
receiver_client_id INTEGER NOT NULL,
|
receiver_client_id TEXT NOT NULL,
|
||||||
|
|
||||||
timestamp_created INTEGER NOT NULL,
|
timestamp_created INTEGER NOT NULL,
|
||||||
timestamp_finalized INTEGER NULL,
|
timestamp_finalized INTEGER NULL,
|
||||||
@ -157,9 +166,21 @@ CREATE TABLE deliveries
|
|||||||
retry_count INTEGER NOT NULL DEFAULT 0,
|
retry_count INTEGER NOT NULL DEFAULT 0,
|
||||||
next_delivery INTEGER NULL DEFAULT NULL,
|
next_delivery INTEGER NULL DEFAULT NULL,
|
||||||
|
|
||||||
fcm_message_id TEXT NULL
|
fcm_message_id TEXT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (delivery_id)
|
||||||
) STRICT;
|
) 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`
|
CREATE TABLE `meta`
|
||||||
|
@ -15,7 +15,10 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID models.UserI
|
|||||||
|
|
||||||
now := time.Now().UTC()
|
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,
|
"suid": subscriberUID,
|
||||||
"ouid": channel.OwnerUserID,
|
"ouid": channel.OwnerUserID,
|
||||||
"cnam": channel.InternalName,
|
"cnam": channel.InternalName,
|
||||||
@ -27,13 +30,8 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID models.UserI
|
|||||||
return models.Subscription{}, err
|
return models.Subscription{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.Subscription{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Subscription{
|
return models.Subscription{
|
||||||
SubscriptionID: models.SubscriptionID(liid),
|
SubscriptionID: subscriptionid,
|
||||||
SubscriberUserID: subscriberUID,
|
SubscriberUserID: subscriberUID,
|
||||||
ChannelOwnerUserID: channel.OwnerUserID,
|
ChannelOwnerUserID: channel.OwnerUserID,
|
||||||
ChannelID: channel.ChannelID,
|
ChannelID: channel.ChannelID,
|
||||||
@ -49,7 +47,9 @@ func (db *Database) ListSubscriptionsByChannel(ctx TxContext, channelID models.C
|
|||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -75,7 +75,9 @@ func (db *Database) ListSubscriptionsByChannelOwner(ctx TxContext, ownerUserID m
|
|||||||
cond = " AND confirmed = 0"
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -101,7 +103,9 @@ func (db *Database) ListSubscriptionsBySubscriber(ctx TxContext, subscriberUserI
|
|||||||
cond = " AND confirmed = 0"
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,10 @@ func (db *Database) CreateUser(ctx TxContext, readKey string, sendKey string, ad
|
|||||||
|
|
||||||
now := time.Now().UTC()
|
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,
|
"un": username,
|
||||||
"rk": readKey,
|
"rk": readKey,
|
||||||
"sk": sendKey,
|
"sk": sendKey,
|
||||||
@ -29,13 +32,8 @@ func (db *Database) CreateUser(ctx TxContext, readKey string, sendKey string, ad
|
|||||||
return models.User{}, err
|
return models.User{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.User{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.User{
|
return models.User{
|
||||||
UserID: models.UserID(liid),
|
UserID: userid,
|
||||||
Username: username,
|
Username: username,
|
||||||
ReadKey: readKey,
|
ReadKey: readKey,
|
||||||
SendKey: sendKey,
|
SendKey: sendKey,
|
||||||
|
@ -24,7 +24,7 @@ type Database struct {
|
|||||||
func NewRequestsDatabase(cfg server.Config) (*Database, error) {
|
func NewRequestsDatabase(cfg server.Config) (*Database, error) {
|
||||||
conf := cfg.DBRequests
|
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)
|
xdb, err := sqlx.Open("sqlite3", url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,11 +7,12 @@ import (
|
|||||||
"time"
|
"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()
|
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,
|
"method": data.Method,
|
||||||
"uri": data.URI,
|
"uri": data.URI,
|
||||||
"user_agent": data.UserAgent,
|
"user_agent": data.UserAgent,
|
||||||
@ -38,13 +39,8 @@ func (db *Database) InsertRequestLog(ctx context.Context, data models.RequestLog
|
|||||||
return models.RequestLogDB{}, err
|
return models.RequestLogDB{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
liid, err := res.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return models.RequestLogDB{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.RequestLogDB{
|
return models.RequestLogDB{
|
||||||
RequestID: models.RequestID(liid),
|
RequestID: requestid,
|
||||||
Method: data.Method,
|
Method: data.Method,
|
||||||
URI: data.URI,
|
URI: data.URI,
|
||||||
UserAgent: data.UserAgent,
|
UserAgent: data.UserAgent,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
CREATE TABLE `requests`
|
CREATE TABLE `requests`
|
||||||
(
|
(
|
||||||
request_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
request_id TEXT NOT NULL,
|
||||||
|
|
||||||
method TEXT NOT NULL,
|
method TEXT NOT NULL,
|
||||||
uri TEXT NOT NULL,
|
uri TEXT NOT NULL,
|
||||||
@ -15,8 +15,8 @@ CREATE TABLE `requests`
|
|||||||
userid TEXT NULL,
|
userid TEXT NULL,
|
||||||
permissions TEXT NULL,
|
permissions TEXT NULL,
|
||||||
|
|
||||||
response_statuscode INTEGER NOT NULL,
|
response_statuscode INTEGER NULL,
|
||||||
response_body_size INTEGER NOT NULL,
|
response_body_size INTEGER NULL,
|
||||||
response_body TEXT NULL,
|
response_body TEXT NULL,
|
||||||
response_content_type TEXT NOT NULL,
|
response_content_type TEXT NOT NULL,
|
||||||
processing_time INTEGER NOT NULL,
|
processing_time INTEGER NOT NULL,
|
||||||
@ -26,8 +26,9 @@ CREATE TABLE `requests`
|
|||||||
|
|
||||||
timestamp_created INTEGER NOT NULL,
|
timestamp_created INTEGER NOT NULL,
|
||||||
timestamp_start INTEGER NOT NULL,
|
timestamp_start INTEGER NOT NULL,
|
||||||
timestamp_finish INTEGER NOT NULL
|
timestamp_finish INTEGER NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (request_id)
|
||||||
) STRICT;
|
) 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)
|
client, err := j.app.Database.Primary.GetClient(ctx, delivery.ReceiverUserID, delivery.ReceiverClientID)
|
||||||
if err != nil {
|
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()
|
ctx.RollbackTransaction()
|
||||||
return
|
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 {
|
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()
|
ctx.RollbackTransaction()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
|
|||||||
if msg.Deleted {
|
if msg.Deleted {
|
||||||
err = j.app.Database.Primary.SetDeliveryFailed(ctx, delivery)
|
err = j.app.Database.Primary.SetDeliveryFailed(ctx, delivery)
|
||||||
if err != nil {
|
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()
|
ctx.RollbackTransaction()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -159,22 +159,22 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
err = j.app.Database.Primary.SetDeliverySuccess(ctx, delivery, *fcmDelivID)
|
err = j.app.Database.Primary.SetDeliverySuccess(ctx, delivery, *fcmDelivID)
|
||||||
if err != nil {
|
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()
|
ctx.RollbackTransaction()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if delivery.RetryCount+1 > delivery.MaxRetryCount() {
|
} else if delivery.RetryCount+1 > delivery.MaxRetryCount() {
|
||||||
err = j.app.Database.Primary.SetDeliveryFailed(ctx, delivery)
|
err = j.app.Database.Primary.SetDeliveryFailed(ctx, delivery)
|
||||||
if err != nil {
|
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()
|
ctx.RollbackTransaction()
|
||||||
return
|
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 {
|
} else {
|
||||||
err = j.app.Database.Primary.SetDeliveryRetry(ctx, delivery)
|
err = j.app.Database.Primary.SetDeliveryRetry(ctx, delivery)
|
||||||
if err != nil {
|
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()
|
ctx.RollbackTransaction()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -72,11 +72,12 @@ mainLoop:
|
|||||||
log.Error().Msg(fmt.Sprintf("Received unknown job signal: <%s> in job [%s]", signal, j.name))
|
log.Error().Msg(fmt.Sprintf("Received unknown job signal: <%s> in job [%s]", signal, j.name))
|
||||||
}
|
}
|
||||||
case obj := <-j.app.RequestLogQueue:
|
case obj := <-j.app.RequestLogQueue:
|
||||||
err := j.insertLog(obj)
|
requestid := models.NewRequestID()
|
||||||
|
err := j.insertLog(requestid, obj)
|
||||||
if err != nil {
|
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 {
|
} 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)
|
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)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, err := j.app.Database.Requests.InsertRequestLog(ctx, rl.DB())
|
_, err := j.app.Database.Requests.InsertRequestLog(ctx, requestid, rl.DB())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ func (app *Application) DeliverMessage(ctx context.Context, client models.Client
|
|||||||
if client.FCMToken != nil {
|
if client.FCMToken != nil {
|
||||||
fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg)
|
fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg)
|
||||||
if err != nil {
|
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 nil, err
|
||||||
}
|
}
|
||||||
return langext.Ptr(fcmDelivID), nil
|
return langext.Ptr(fcmDelivID), nil
|
||||||
|
@ -17,7 +17,7 @@ const (
|
|||||||
|
|
||||||
type Delivery struct {
|
type Delivery struct {
|
||||||
DeliveryID DeliveryID
|
DeliveryID DeliveryID
|
||||||
SCNMessageID SCNMessageID
|
MessageID MessageID
|
||||||
ReceiverUserID UserID
|
ReceiverUserID UserID
|
||||||
ReceiverClientID ClientID
|
ReceiverClientID ClientID
|
||||||
TimestampCreated time.Time
|
TimestampCreated time.Time
|
||||||
@ -31,7 +31,7 @@ type Delivery struct {
|
|||||||
func (d Delivery) JSON() DeliveryJSON {
|
func (d Delivery) JSON() DeliveryJSON {
|
||||||
return DeliveryJSON{
|
return DeliveryJSON{
|
||||||
DeliveryID: d.DeliveryID,
|
DeliveryID: d.DeliveryID,
|
||||||
SCNMessageID: d.SCNMessageID,
|
MessageID: d.MessageID,
|
||||||
ReceiverUserID: d.ReceiverUserID,
|
ReceiverUserID: d.ReceiverUserID,
|
||||||
ReceiverClientID: d.ReceiverClientID,
|
ReceiverClientID: d.ReceiverClientID,
|
||||||
TimestampCreated: d.TimestampCreated.Format(time.RFC3339Nano),
|
TimestampCreated: d.TimestampCreated.Format(time.RFC3339Nano),
|
||||||
@ -49,7 +49,7 @@ func (d Delivery) MaxRetryCount() int {
|
|||||||
|
|
||||||
type DeliveryJSON struct {
|
type DeliveryJSON struct {
|
||||||
DeliveryID DeliveryID `json:"delivery_id"`
|
DeliveryID DeliveryID `json:"delivery_id"`
|
||||||
SCNMessageID SCNMessageID `json:"scn_message_id"`
|
MessageID MessageID `json:"message_id"`
|
||||||
ReceiverUserID UserID `json:"receiver_user_id"`
|
ReceiverUserID UserID `json:"receiver_user_id"`
|
||||||
ReceiverClientID ClientID `json:"receiver_client_id"`
|
ReceiverClientID ClientID `json:"receiver_client_id"`
|
||||||
TimestampCreated string `json:"timestamp_created"`
|
TimestampCreated string `json:"timestamp_created"`
|
||||||
@ -62,7 +62,7 @@ type DeliveryJSON struct {
|
|||||||
|
|
||||||
type DeliveryDB struct {
|
type DeliveryDB struct {
|
||||||
DeliveryID DeliveryID `db:"delivery_id"`
|
DeliveryID DeliveryID `db:"delivery_id"`
|
||||||
SCNMessageID SCNMessageID `db:"scn_message_id"`
|
MessageID MessageID `db:"message_id"`
|
||||||
ReceiverUserID UserID `db:"receiver_user_id"`
|
ReceiverUserID UserID `db:"receiver_user_id"`
|
||||||
ReceiverClientID ClientID `db:"receiver_client_id"`
|
ReceiverClientID ClientID `db:"receiver_client_id"`
|
||||||
TimestampCreated int64 `db:"timestamp_created"`
|
TimestampCreated int64 `db:"timestamp_created"`
|
||||||
@ -76,7 +76,7 @@ type DeliveryDB struct {
|
|||||||
func (d DeliveryDB) Model() Delivery {
|
func (d DeliveryDB) Model() Delivery {
|
||||||
return Delivery{
|
return Delivery{
|
||||||
DeliveryID: d.DeliveryID,
|
DeliveryID: d.DeliveryID,
|
||||||
SCNMessageID: d.SCNMessageID,
|
MessageID: d.MessageID,
|
||||||
ReceiverUserID: d.ReceiverUserID,
|
ReceiverUserID: d.ReceiverUserID,
|
||||||
ReceiverClientID: d.ReceiverClientID,
|
ReceiverClientID: d.ReceiverClientID,
|
||||||
TimestampCreated: time.UnixMilli(d.TimestampCreated),
|
TimestampCreated: time.UnixMilli(d.TimestampCreated),
|
||||||
|
@ -1,78 +1,376 @@
|
|||||||
package models
|
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 {
|
type EntityID interface {
|
||||||
IntID() int64
|
|
||||||
String() string
|
String() string
|
||||||
|
Valid() error
|
||||||
|
Prefix() string
|
||||||
|
Raw() string
|
||||||
|
CheckString() string
|
||||||
|
Regex() *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserID int64
|
const idlen = 24
|
||||||
|
|
||||||
func (id UserID) IntID() int64 {
|
const checklen = 1
|
||||||
return int64(id)
|
|
||||||
|
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 {
|
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 {
|
func (id UserID) Raw() string {
|
||||||
return int64(id)
|
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 {
|
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 {
|
func (id ChannelID) Raw() string {
|
||||||
return int64(id)
|
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 {
|
func (id DeliveryID) String() string {
|
||||||
return strconv.FormatInt(int64(id), 10)
|
return string(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SCNMessageID int64
|
func (id DeliveryID) Prefix() string {
|
||||||
|
return prefixDeliveryID
|
||||||
func (id SCNMessageID) IntID() int64 {
|
|
||||||
return int64(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id SCNMessageID) String() string {
|
func (id DeliveryID) Raw() string {
|
||||||
return strconv.FormatInt(int64(id), 10)
|
return getRawData(prefixDeliveryID, string(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
type SubscriptionID int64
|
func (id DeliveryID) CheckString() string {
|
||||||
|
return getCheckString(prefixDeliveryID, string(id))
|
||||||
|
}
|
||||||
|
|
||||||
func (id SubscriptionID) IntID() int64 {
|
func (id DeliveryID) Regex() *regexp.Regexp {
|
||||||
return int64(id)
|
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 {
|
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 {
|
func (id SubscriptionID) Raw() string {
|
||||||
return int64(id)
|
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 {
|
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 {
|
func (id ClientID) Raw() string {
|
||||||
return int64(id)
|
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 {
|
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 {
|
type Message struct {
|
||||||
SCNMessageID SCNMessageID
|
MessageID MessageID
|
||||||
SenderUserID UserID
|
SenderUserID UserID
|
||||||
OwnerUserID UserID
|
OwnerUserID UserID
|
||||||
ChannelInternalName string
|
ChannelInternalName string
|
||||||
@ -31,7 +31,7 @@ type Message struct {
|
|||||||
|
|
||||||
func (m Message) FullJSON() MessageJSON {
|
func (m Message) FullJSON() MessageJSON {
|
||||||
return MessageJSON{
|
return MessageJSON{
|
||||||
SCNMessageID: m.SCNMessageID,
|
MessageID: m.MessageID,
|
||||||
SenderUserID: m.SenderUserID,
|
SenderUserID: m.SenderUserID,
|
||||||
OwnerUserID: m.OwnerUserID,
|
OwnerUserID: m.OwnerUserID,
|
||||||
ChannelInternalName: m.ChannelInternalName,
|
ChannelInternalName: m.ChannelInternalName,
|
||||||
@ -49,7 +49,7 @@ func (m Message) FullJSON() MessageJSON {
|
|||||||
|
|
||||||
func (m Message) TrimmedJSON() MessageJSON {
|
func (m Message) TrimmedJSON() MessageJSON {
|
||||||
return MessageJSON{
|
return MessageJSON{
|
||||||
SCNMessageID: m.SCNMessageID,
|
MessageID: m.MessageID,
|
||||||
SenderUserID: m.SenderUserID,
|
SenderUserID: m.SenderUserID,
|
||||||
OwnerUserID: m.OwnerUserID,
|
OwnerUserID: m.OwnerUserID,
|
||||||
ChannelInternalName: m.ChannelInternalName,
|
ChannelInternalName: m.ChannelInternalName,
|
||||||
@ -94,7 +94,7 @@ func (m Message) ShortContent() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MessageJSON struct {
|
type MessageJSON struct {
|
||||||
SCNMessageID SCNMessageID `json:"scn_message_id"`
|
MessageID MessageID `json:"message_id"`
|
||||||
SenderUserID UserID `json:"sender_user_id"`
|
SenderUserID UserID `json:"sender_user_id"`
|
||||||
OwnerUserID UserID `json:"owner_user_id"`
|
OwnerUserID UserID `json:"owner_user_id"`
|
||||||
ChannelInternalName string `json:"channel_internal_name"`
|
ChannelInternalName string `json:"channel_internal_name"`
|
||||||
@ -110,7 +110,7 @@ type MessageJSON struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MessageDB struct {
|
type MessageDB struct {
|
||||||
SCNMessageID SCNMessageID `db:"scn_message_id"`
|
MessageID MessageID `db:"message_id"`
|
||||||
SenderUserID UserID `db:"sender_user_id"`
|
SenderUserID UserID `db:"sender_user_id"`
|
||||||
OwnerUserID UserID `db:"owner_user_id"`
|
OwnerUserID UserID `db:"owner_user_id"`
|
||||||
ChannelInternalName string `db:"channel_internal_name"`
|
ChannelInternalName string `db:"channel_internal_name"`
|
||||||
@ -128,7 +128,7 @@ type MessageDB struct {
|
|||||||
|
|
||||||
func (m MessageDB) Model() Message {
|
func (m MessageDB) Model() Message {
|
||||||
return Message{
|
return Message{
|
||||||
SCNMessageID: m.SCNMessageID,
|
MessageID: m.MessageID,
|
||||||
SenderUserID: m.SenderUserID,
|
SenderUserID: m.SenderUserID,
|
||||||
OwnerUserID: m.OwnerUserID,
|
OwnerUserID: m.OwnerUserID,
|
||||||
ChannelInternalName: m.ChannelInternalName,
|
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 "
|
joinClause += " LEFT JOIN subscriptions AS subs on messages.channel_id = subs.channel_id "
|
||||||
}
|
}
|
||||||
if f.SearchString != nil {
|
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)
|
sqlClauses := make([]string, 0)
|
||||||
|
@ -56,7 +56,7 @@ func (fb FirebaseConnector) SendNotification(ctx context.Context, client models.
|
|||||||
|
|
||||||
jsonBody := gin.H{
|
jsonBody := gin.H{
|
||||||
"data": gin.H{
|
"data": gin.H{
|
||||||
"scn_msg_id": msg.SCNMessageID.String(),
|
"scn_msg_id": msg.MessageID.String(),
|
||||||
"usr_msg_id": langext.Coalesce(msg.UserMessageID, ""),
|
"usr_msg_id": langext.Coalesce(msg.UserMessageID, ""),
|
||||||
"client_id": client.ClientID.String(),
|
"client_id": client.ClientID.String(),
|
||||||
"timestamp": strconv.FormatInt(msg.Timestamp().Unix(), 10),
|
"timestamp": strconv.FormatInt(msg.Timestamp().Unix(), 10),
|
||||||
|
@ -71,8 +71,8 @@
|
|||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "string",
|
||||||
"example": 7725,
|
"example": "7725",
|
||||||
"name": "user_id",
|
"name": "user_id",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@ -144,8 +144,8 @@
|
|||||||
"in": "formData"
|
"in": "formData"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "string",
|
||||||
"example": 7725,
|
"example": "7725",
|
||||||
"name": "user_id",
|
"name": "user_id",
|
||||||
"in": "formData"
|
"in": "formData"
|
||||||
},
|
},
|
||||||
@ -478,7 +478,7 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "SCNMessageID",
|
"description": "MessageID",
|
||||||
"name": "mid",
|
"name": "mid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
@ -527,7 +527,7 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "SCNMessageID",
|
"description": "MessageID",
|
||||||
"name": "mid",
|
"name": "mid",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
@ -2093,8 +2093,8 @@
|
|||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "string",
|
||||||
"example": 7725,
|
"example": "7725",
|
||||||
"name": "user_id",
|
"name": "user_id",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
@ -2166,8 +2166,8 @@
|
|||||||
"in": "formData"
|
"in": "formData"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "string",
|
||||||
"example": 7725,
|
"example": "7725",
|
||||||
"name": "user_id",
|
"name": "user_id",
|
||||||
"in": "formData"
|
"in": "formData"
|
||||||
},
|
},
|
||||||
@ -2414,13 +2414,13 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"channel_id": {
|
"channel_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"channel_internal_name": {
|
"channel_internal_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"channel_owner_user_id": {
|
"channel_owner_user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2686,8 +2686,8 @@
|
|||||||
"example": "Hello World"
|
"example": "Hello World"
|
||||||
},
|
},
|
||||||
"user_id": {
|
"user_id": {
|
||||||
"type": "integer",
|
"type": "string",
|
||||||
"example": 7725
|
"example": "7725"
|
||||||
},
|
},
|
||||||
"user_key": {
|
"user_key": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -2828,7 +2828,7 @@
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"scn_msg_id": {
|
"scn_msg_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
@ -2842,7 +2842,7 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"channel_id": {
|
"channel_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"description_name": {
|
"description_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -2857,7 +2857,7 @@
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"owner_user_id": {
|
"owner_user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"send_key": {
|
"send_key": {
|
||||||
"description": "can be nil, depending on endpoint",
|
"description": "can be nil, depending on endpoint",
|
||||||
@ -2888,7 +2888,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"client_id": {
|
"client_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"fcm_token": {
|
"fcm_token": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -2900,7 +2900,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"user_id": {
|
"user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2934,7 +2934,7 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"channel_id": {
|
"channel_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"channel_internal_name": {
|
"channel_internal_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -2942,15 +2942,15 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"message_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"owner_user_id": {
|
"owner_user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"priority": {
|
"priority": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"scn_message_id": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"sender_ip": {
|
"sender_ip": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -2958,7 +2958,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"sender_user_id": {
|
"sender_user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"timestamp": {
|
"timestamp": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -2978,22 +2978,22 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"channel_id": {
|
"channel_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"channel_internal_name": {
|
"channel_internal_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"channel_owner_user_id": {
|
"channel_owner_user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"confirmed": {
|
"confirmed": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"subscriber_user_id": {
|
"subscriber_user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"subscription_id": {
|
"subscription_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"timestamp_created": {
|
"timestamp_created": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -3040,7 +3040,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"user_id": {
|
"user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"username": {
|
"username": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -3093,7 +3093,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"user_id": {
|
"user_id": {
|
||||||
"type": "integer"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"username": {
|
"username": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -57,11 +57,11 @@ definitions:
|
|||||||
handler.CreateSubscription.body:
|
handler.CreateSubscription.body:
|
||||||
properties:
|
properties:
|
||||||
channel_id:
|
channel_id:
|
||||||
type: integer
|
type: string
|
||||||
channel_internal_name:
|
channel_internal_name:
|
||||||
type: string
|
type: string
|
||||||
channel_owner_user_id:
|
channel_owner_user_id:
|
||||||
type: integer
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handler.CreateUser.body:
|
handler.CreateUser.body:
|
||||||
properties:
|
properties:
|
||||||
@ -237,8 +237,8 @@ definitions:
|
|||||||
example: Hello World
|
example: Hello World
|
||||||
type: string
|
type: string
|
||||||
user_id:
|
user_id:
|
||||||
example: 7725
|
example: "7725"
|
||||||
type: integer
|
type: string
|
||||||
user_key:
|
user_key:
|
||||||
example: P3TNH8mvv14fm
|
example: P3TNH8mvv14fm
|
||||||
type: string
|
type: string
|
||||||
@ -330,7 +330,7 @@ definitions:
|
|||||||
quota_max:
|
quota_max:
|
||||||
type: integer
|
type: integer
|
||||||
scn_msg_id:
|
scn_msg_id:
|
||||||
type: integer
|
type: string
|
||||||
success:
|
success:
|
||||||
type: boolean
|
type: boolean
|
||||||
suppress_send:
|
suppress_send:
|
||||||
@ -339,7 +339,7 @@ definitions:
|
|||||||
models.ChannelWithSubscriptionJSON:
|
models.ChannelWithSubscriptionJSON:
|
||||||
properties:
|
properties:
|
||||||
channel_id:
|
channel_id:
|
||||||
type: integer
|
type: string
|
||||||
description_name:
|
description_name:
|
||||||
type: string
|
type: string
|
||||||
display_name:
|
display_name:
|
||||||
@ -349,7 +349,7 @@ definitions:
|
|||||||
messages_sent:
|
messages_sent:
|
||||||
type: integer
|
type: integer
|
||||||
owner_user_id:
|
owner_user_id:
|
||||||
type: integer
|
type: string
|
||||||
send_key:
|
send_key:
|
||||||
description: can be nil, depending on endpoint
|
description: can be nil, depending on endpoint
|
||||||
type: string
|
type: string
|
||||||
@ -370,7 +370,7 @@ definitions:
|
|||||||
agent_version:
|
agent_version:
|
||||||
type: string
|
type: string
|
||||||
client_id:
|
client_id:
|
||||||
type: integer
|
type: string
|
||||||
fcm_token:
|
fcm_token:
|
||||||
type: string
|
type: string
|
||||||
timestamp_created:
|
timestamp_created:
|
||||||
@ -378,7 +378,7 @@ definitions:
|
|||||||
type:
|
type:
|
||||||
type: string
|
type: string
|
||||||
user_id:
|
user_id:
|
||||||
type: integer
|
type: string
|
||||||
type: object
|
type: object
|
||||||
models.CompatMessage:
|
models.CompatMessage:
|
||||||
properties:
|
properties:
|
||||||
@ -400,23 +400,23 @@ definitions:
|
|||||||
models.MessageJSON:
|
models.MessageJSON:
|
||||||
properties:
|
properties:
|
||||||
channel_id:
|
channel_id:
|
||||||
type: integer
|
type: string
|
||||||
channel_internal_name:
|
channel_internal_name:
|
||||||
type: string
|
type: string
|
||||||
content:
|
content:
|
||||||
type: string
|
type: string
|
||||||
|
message_id:
|
||||||
|
type: string
|
||||||
owner_user_id:
|
owner_user_id:
|
||||||
type: integer
|
type: string
|
||||||
priority:
|
priority:
|
||||||
type: integer
|
type: integer
|
||||||
scn_message_id:
|
|
||||||
type: integer
|
|
||||||
sender_ip:
|
sender_ip:
|
||||||
type: string
|
type: string
|
||||||
sender_name:
|
sender_name:
|
||||||
type: string
|
type: string
|
||||||
sender_user_id:
|
sender_user_id:
|
||||||
type: integer
|
type: string
|
||||||
timestamp:
|
timestamp:
|
||||||
type: string
|
type: string
|
||||||
title:
|
title:
|
||||||
@ -429,17 +429,17 @@ definitions:
|
|||||||
models.SubscriptionJSON:
|
models.SubscriptionJSON:
|
||||||
properties:
|
properties:
|
||||||
channel_id:
|
channel_id:
|
||||||
type: integer
|
type: string
|
||||||
channel_internal_name:
|
channel_internal_name:
|
||||||
type: string
|
type: string
|
||||||
channel_owner_user_id:
|
channel_owner_user_id:
|
||||||
type: integer
|
type: string
|
||||||
confirmed:
|
confirmed:
|
||||||
type: boolean
|
type: boolean
|
||||||
subscriber_user_id:
|
subscriber_user_id:
|
||||||
type: integer
|
type: string
|
||||||
subscription_id:
|
subscription_id:
|
||||||
type: integer
|
type: string
|
||||||
timestamp_created:
|
timestamp_created:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
@ -470,7 +470,7 @@ definitions:
|
|||||||
timestamp_lastsent:
|
timestamp_lastsent:
|
||||||
type: string
|
type: string
|
||||||
user_id:
|
user_id:
|
||||||
type: integer
|
type: string
|
||||||
username:
|
username:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
@ -505,7 +505,7 @@ definitions:
|
|||||||
timestamp_lastsent:
|
timestamp_lastsent:
|
||||||
type: string
|
type: string
|
||||||
user_id:
|
user_id:
|
||||||
type: integer
|
type: string
|
||||||
username:
|
username:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
@ -557,10 +557,10 @@ paths:
|
|||||||
in: query
|
in: query
|
||||||
name: title
|
name: title
|
||||||
type: string
|
type: string
|
||||||
- example: 7725
|
- example: "7725"
|
||||||
in: query
|
in: query
|
||||||
name: user_id
|
name: user_id
|
||||||
type: integer
|
type: string
|
||||||
- example: P3TNH8mvv14fm
|
- example: P3TNH8mvv14fm
|
||||||
in: query
|
in: query
|
||||||
name: user_key
|
name: user_key
|
||||||
@ -606,10 +606,10 @@ paths:
|
|||||||
in: formData
|
in: formData
|
||||||
name: title
|
name: title
|
||||||
type: string
|
type: string
|
||||||
- example: 7725
|
- example: "7725"
|
||||||
in: formData
|
in: formData
|
||||||
name: user_id
|
name: user_id
|
||||||
type: integer
|
type: string
|
||||||
- example: P3TNH8mvv14fm
|
- example: P3TNH8mvv14fm
|
||||||
in: formData
|
in: formData
|
||||||
name: user_key
|
name: user_key
|
||||||
@ -836,7 +836,7 @@ paths:
|
|||||||
ADMIN Key
|
ADMIN Key
|
||||||
operationId: api-messages-delete
|
operationId: api-messages-delete
|
||||||
parameters:
|
parameters:
|
||||||
- description: SCNMessageID
|
- description: MessageID
|
||||||
in: path
|
in: path
|
||||||
name: mid
|
name: mid
|
||||||
required: true
|
required: true
|
||||||
@ -872,7 +872,7 @@ paths:
|
|||||||
The returned message is never trimmed
|
The returned message is never trimmed
|
||||||
operationId: api-messages-get
|
operationId: api-messages-get
|
||||||
parameters:
|
parameters:
|
||||||
- description: SCNMessageID
|
- description: MessageID
|
||||||
in: path
|
in: path
|
||||||
name: mid
|
name: mid
|
||||||
required: true
|
required: true
|
||||||
@ -1941,10 +1941,10 @@ paths:
|
|||||||
in: query
|
in: query
|
||||||
name: title
|
name: title
|
||||||
type: string
|
type: string
|
||||||
- example: 7725
|
- example: "7725"
|
||||||
in: query
|
in: query
|
||||||
name: user_id
|
name: user_id
|
||||||
type: integer
|
type: string
|
||||||
- example: P3TNH8mvv14fm
|
- example: P3TNH8mvv14fm
|
||||||
in: query
|
in: query
|
||||||
name: user_key
|
name: user_key
|
||||||
@ -1990,10 +1990,10 @@ paths:
|
|||||||
in: formData
|
in: formData
|
||||||
name: title
|
name: title
|
||||||
type: string
|
type: string
|
||||||
- example: 7725
|
- example: "7725"
|
||||||
in: formData
|
in: formData
|
||||||
name: user_id
|
name: user_id
|
||||||
type: integer
|
type: string
|
||||||
- example: P3TNH8mvv14fm
|
- example: P3TNH8mvv14fm
|
||||||
in: formData
|
in: formData
|
||||||
name: user_key
|
name: user_key
|
||||||
|
@ -21,7 +21,7 @@ func TestCreateChannel(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
type chanlist struct {
|
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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_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",
|
"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.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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "internal_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",
|
"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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"asdf", "test"}, clist.Channels, "internal_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",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(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),
|
"name": langext.StrRepeat("X", 121),
|
||||||
}, 400, apierr.CHANNEL_TOO_LONG)
|
}, 400, apierr.CHANNEL_TOO_LONG)
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func TestChannelNameNormalization(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
type chanlist struct {
|
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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_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",
|
"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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "internal_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",
|
"name": "test",
|
||||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
}, 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",
|
"name": "TEST",
|
||||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
}, 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",
|
"name": "Test",
|
||||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
}, 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 ",
|
"name": "Test ",
|
||||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
}, 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",
|
"name": " Test",
|
||||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
}, 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",
|
"name": "\rTeSt\n",
|
||||||
}, 409, apierr.CHANNEL_ALREADY_EXISTS)
|
}, 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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"test"}, clist.Channels, "internal_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 ",
|
"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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"test", "weird_[\uF5FF]\\stuff"}, clist.Channels, "internal_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 {
|
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")
|
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 {
|
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")
|
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 {
|
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")
|
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 {
|
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")
|
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 {
|
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")
|
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 {
|
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")
|
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",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
type chanlist struct {
|
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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_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",
|
"name": "server-alerts",
|
||||||
})
|
})
|
||||||
chanid := fmt.Sprintf("%v", chan0["channel_id"])
|
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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"server-alerts"}, clist.Channels, "internal_name")
|
tt.AssertMappedSet(t, "channels", []string{"server-alerts"}, clist.Channels, "internal_name")
|
||||||
tt.AssertEqual(t, "channels.descr", nil, clist.Channels[0]["description_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.display_name", "server-alerts", chan1["display_name"])
|
||||||
tt.AssertEqual(t, "channels.internal_name", "server-alerts", chan1["internal_name"])
|
tt.AssertEqual(t, "channels.internal_name", "server-alerts", chan1["internal_name"])
|
||||||
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_name"])
|
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_name"])
|
||||||
@ -408,12 +408,12 @@ func TestChannelUpdate(t *testing.T) {
|
|||||||
|
|
||||||
// [1] update display_name
|
// [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",
|
"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.display_name", "SERVER-ALERTS", chan1["display_name"])
|
||||||
tt.AssertEqual(t, "channels.internal_name", "server-alerts", chan1["internal_name"])
|
tt.AssertEqual(t, "channels.internal_name", "server-alerts", chan1["internal_name"])
|
||||||
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_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
|
// [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",
|
"display_name": "SERVER-ALERTS2",
|
||||||
}, 400, apierr.CHANNEL_NAME_WOULD_CHANGE)
|
}, 400, apierr.CHANNEL_NAME_WOULD_CHANGE)
|
||||||
|
|
||||||
// [3] renew subscribe_key
|
// [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,
|
"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.AssertNotEqual(t, "channels.subscribe_key", chan0["subscribe_key"], chan1["subscribe_key"])
|
||||||
tt.AssertEqual(t, "channels.send_key", chan0["send_key"], chan1["send_key"])
|
tt.AssertEqual(t, "channels.send_key", chan0["send_key"], chan1["send_key"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// [4] renew 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,
|
"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.subscribe_key", chan0["subscribe_key"], chan1["subscribe_key"])
|
||||||
tt.AssertNotEqual(t, "channels.send_key", chan0["send_key"], chan1["send_key"])
|
tt.AssertNotEqual(t, "channels.send_key", chan0["send_key"], chan1["send_key"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// [5] update description_name
|
// [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",
|
"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"])
|
tt.AssertEqual(t, "channels.description_name", "hello World", chan1["description_name"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// [6] update 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 ",
|
"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"])
|
tt.AssertEqual(t, "channels.description_name", "AXXhello World9", chan1["description_name"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// [7] clear 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": "",
|
"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"])
|
tt.AssertEqual(t, "channels.description_name", nil, chan1["description_name"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// [8] fail to update 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),
|
"description_name": strings.Repeat("0123456789", 48),
|
||||||
}, 400, apierr.CHANNEL_DESCRIPTION_TOO_LONG)
|
}, 400, apierr.CHANNEL_DESCRIPTION_TOO_LONG)
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
//TODO test compat methods
|
//TODO test compat methods
|
||||||
|
|
||||||
|
//TODO also test compat_id mapping
|
||||||
|
@ -2,6 +2,7 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||||
|
"blackforestbytes.com/simplecloudnotifier/models"
|
||||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -48,7 +49,7 @@ func TestDeleteMessage(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ func TestDeleteMessageAndResendUsrMsgId(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
@ -138,7 +139,18 @@ func TestGetMessageNotFound(t *testing.T) {
|
|||||||
|
|
||||||
data := tt.InitDefaultData(t, ws)
|
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) {
|
func TestGetMessageFull(t *testing.T) {
|
||||||
|
@ -2,6 +2,7 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||||
|
"blackforestbytes.com/simplecloudnotifier/models"
|
||||||
"blackforestbytes.com/simplecloudnotifier/push"
|
"blackforestbytes.com/simplecloudnotifier/push"
|
||||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -24,7 +25,7 @@ func TestSendSimpleMessageJSON(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
readtok := r0["read_key"].(string)
|
readtok := r0["read_key"].(string)
|
||||||
sendtok := r0["send_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.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -77,16 +78,16 @@ func TestSendSimpleMessageQuery(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_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.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "Hello World 2134", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -113,20 +114,20 @@ func TestSendSimpleMessageForm(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", tt.FormData{
|
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": uid,
|
||||||
"title": "Hello World 9999 [$$$]",
|
"title": "Hello World 9999 [$$$]",
|
||||||
})
|
})
|
||||||
|
|
||||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "Hello World 9999 [$$$]", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -153,10 +154,10 @@ func TestSendSimpleMessageFormAndQuery(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_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("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_key": "ERR",
|
||||||
"user_id": "999999",
|
"user_id": "999999",
|
||||||
"title": "2222222",
|
"title": "2222222",
|
||||||
@ -164,7 +165,7 @@ func TestSendSimpleMessageFormAndQuery(t *testing.T) {
|
|||||||
|
|
||||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "1111111", pusher.Last().Message.Title)
|
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) {
|
func TestSendSimpleMessageJSONAndQuery(t *testing.T) {
|
||||||
@ -180,18 +181,19 @@ func TestSendSimpleMessageJSONAndQuery(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_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("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_key": "ERR",
|
||||||
"user_id": 999999,
|
"user_id": models.NewUserID(),
|
||||||
"title": "2222222",
|
"title": "2222222",
|
||||||
})
|
})
|
||||||
|
|
||||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "1111111", pusher.Last().Message.Title)
|
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) {
|
func TestSendSimpleMessageAlt1(t *testing.T) {
|
||||||
@ -207,7 +209,7 @@ func TestSendSimpleMessageAlt1(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
readtok := r0["read_key"].(string)
|
readtok := r0["read_key"].(string)
|
||||||
sendtok := r0["send_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.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -254,7 +256,7 @@ func TestSendContentMessage(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_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.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_042", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -299,7 +301,7 @@ func TestSendWithSendername(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_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.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.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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -348,7 +350,7 @@ func TestSendLongContent(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_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.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_042", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -405,7 +407,7 @@ func TestSendTooLongContent(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
longContent := ""
|
longContent := ""
|
||||||
@ -433,7 +435,7 @@ func TestSendLongContentPro(t *testing.T) {
|
|||||||
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -519,7 +521,7 @@ func TestSendTooLongTitle(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
tt.RequestPostShouldFail(t, baseUrl, "/", gin.H{
|
||||||
@ -542,7 +544,7 @@ func TestSendIdempotent(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
readtok := r0["admin_key"].(string)
|
readtok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_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.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.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.msg_id", "c0235a49-dabc-4cdc-a0ce-453966e0c2d5", pusher.Last().Message.UserMessageID)
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "Hello SCN", pusher.Last().Message.Title)
|
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.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", 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.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.msg_id", "c0235a49-dabc-4cdc-a0ce-453966e0c2d5", pusher.Last().Message.UserMessageID)
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "Hello SCN", pusher.Last().Message.Title)
|
tt.AssertStrRepEqual(t, "msg.title", "Hello SCN", pusher.Last().Message.Title)
|
||||||
@ -620,7 +622,7 @@ func TestSendWithPriority(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
@ -713,7 +715,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
@ -765,11 +767,9 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
"priority": 9999,
|
"priority": 9999,
|
||||||
}, 400, apierr.INVALID_PRIO)
|
}, 400, apierr.INVALID_PRIO)
|
||||||
|
|
||||||
struid := fmt.Sprintf("%d", uid)
|
|
||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": struid,
|
"user_id": uid,
|
||||||
"title": "(title)",
|
"title": "(title)",
|
||||||
"content": "(content)",
|
"content": "(content)",
|
||||||
"priority": "-1",
|
"priority": "-1",
|
||||||
@ -777,7 +777,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": struid,
|
"user_id": uid,
|
||||||
"title": "(title)",
|
"title": "(title)",
|
||||||
"content": "(content)",
|
"content": "(content)",
|
||||||
"priority": "4",
|
"priority": "4",
|
||||||
@ -785,7 +785,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": struid,
|
"user_id": uid,
|
||||||
"title": "(title)",
|
"title": "(title)",
|
||||||
"content": "(content)",
|
"content": "(content)",
|
||||||
"priority": "9999",
|
"priority": "9999",
|
||||||
@ -793,7 +793,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": admintok,
|
"user_key": admintok,
|
||||||
"user_id": struid,
|
"user_id": uid,
|
||||||
"title": "(title)",
|
"title": "(title)",
|
||||||
"content": "(content)",
|
"content": "(content)",
|
||||||
"priority": "-1",
|
"priority": "-1",
|
||||||
@ -801,7 +801,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": admintok,
|
"user_key": admintok,
|
||||||
"user_id": struid,
|
"user_id": uid,
|
||||||
"title": "(title)",
|
"title": "(title)",
|
||||||
"content": "(content)",
|
"content": "(content)",
|
||||||
"priority": "4",
|
"priority": "4",
|
||||||
@ -809,7 +809,7 @@ func TestSendInvalidPriority(t *testing.T) {
|
|||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": admintok,
|
"user_key": admintok,
|
||||||
"user_id": struid,
|
"user_id": uid,
|
||||||
"title": "(title)",
|
"title": "(title)",
|
||||||
"content": "(content)",
|
"content": "(content)",
|
||||||
"priority": "9999",
|
"priority": "9999",
|
||||||
@ -831,7 +831,7 @@ func TestSendWithTimestamp(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_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{
|
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%s", uid),
|
||||||
"title": "TTT",
|
"title": "TTT",
|
||||||
"timestamp": fmt.Sprintf("%d", ts),
|
"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.TimestampClient", ts, pusher.Last().Message.TimestampClient.Unix())
|
||||||
tt.AssertStrRepEqual(t, "msg.Timestamp", ts, pusher.Last().Message.Timestamp().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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
Messages []gin.H `json:"messages"`
|
||||||
@ -888,33 +888,33 @@ func TestSendInvalidTimestamp(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%s", uid),
|
||||||
"title": "TTT",
|
"title": "TTT",
|
||||||
"timestamp": "-10000",
|
"timestamp": "-10000",
|
||||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%s", uid),
|
||||||
"title": "TTT",
|
"title": "TTT",
|
||||||
"timestamp": "0",
|
"timestamp": "0",
|
||||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%s", uid),
|
||||||
"title": "TTT",
|
"title": "TTT",
|
||||||
"timestamp": fmt.Sprintf("%d", time.Now().Unix()-int64(25*time.Hour.Seconds())),
|
"timestamp": fmt.Sprintf("%d", time.Now().Unix()-int64(25*time.Hour.Seconds())),
|
||||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||||
|
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
tt.RequestPostShouldFail(t, baseUrl, "/", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%s", uid),
|
||||||
"title": "TTT",
|
"title": "TTT",
|
||||||
"timestamp": fmt.Sprintf("%d", time.Now().Unix()+int64(25*time.Hour.Seconds())),
|
"timestamp": fmt.Sprintf("%d", time.Now().Unix()+int64(25*time.Hour.Seconds())),
|
||||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
||||||
@ -947,28 +947,28 @@ func TestSendInvalidTimestamp(t *testing.T) {
|
|||||||
"timestamp": time.Now().Unix() + int64(25*time.Hour.Seconds()),
|
"timestamp": time.Now().Unix() + int64(25*time.Hour.Seconds()),
|
||||||
}, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
}, 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,
|
sendtok,
|
||||||
uid,
|
uid,
|
||||||
"TTT",
|
"TTT",
|
||||||
-10000,
|
-10000,
|
||||||
), nil, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
), 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,
|
sendtok,
|
||||||
uid,
|
uid,
|
||||||
"TTT",
|
"TTT",
|
||||||
0,
|
0,
|
||||||
), nil, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
), 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,
|
sendtok,
|
||||||
uid,
|
uid,
|
||||||
"TTT",
|
"TTT",
|
||||||
time.Now().Unix()-int64(25*time.Hour.Seconds()),
|
time.Now().Unix()-int64(25*time.Hour.Seconds()),
|
||||||
), nil, 400, apierr.TIMESTAMP_OUT_OF_RANGE)
|
), 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,
|
sendtok,
|
||||||
uid,
|
uid,
|
||||||
"TTT",
|
"TTT",
|
||||||
@ -978,40 +978,34 @@ func TestSendInvalidTimestamp(t *testing.T) {
|
|||||||
tt.AssertEqual(t, "messageCount", 0, len(pusher.Data))
|
tt.AssertEqual(t, "messageCount", 0, len(pusher.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSendCompat(t *testing.T) {
|
func TestSendCompatWithOldUser(t *testing.T) {
|
||||||
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
pusher := ws.Pusher.(*push.TestSink)
|
pusher := ws.Pusher.(*push.TestSink)
|
||||||
|
|
||||||
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/users", gin.H{
|
r0 := tt.RequestGet[gin.H](t, baseUrl, "/api/register.php?fcm_token=DUMMY_FCM&pro=0&pro_token=")
|
||||||
"agent_model": "DUMMY_PHONE",
|
|
||||||
"agent_version": "4X",
|
|
||||||
"client_type": "ANDROID",
|
|
||||||
"fcm_token": "DUMMY_FCM",
|
|
||||||
})
|
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uidold := int64(r0["user_id"].(float64))
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["user_key"].(string)
|
||||||
readtok := r0["read_key"].(string)
|
|
||||||
sendtok := r0["send_key"].(string)
|
|
||||||
|
|
||||||
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
msg1 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": admintok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%d", uidold),
|
||||||
"title": "HelloWorld_001",
|
"title": "HelloWorld_001",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// does not allow json - only form & query
|
||||||
tt.RequestPostShouldFail(t, baseUrl, "/send.php", gin.H{
|
tt.RequestPostShouldFail(t, baseUrl, "/send.php", gin.H{
|
||||||
"user_key": readtok,
|
"user_key": admintok,
|
||||||
"user_id": uid,
|
"user_id": uidold,
|
||||||
"title": "HelloWorld_001",
|
"title": "HelloWorld_001",
|
||||||
}, 0, 0)
|
}, 400, 0)
|
||||||
|
|
||||||
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
tt.AssertEqual(t, "messageCount", 1, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_001", pusher.Last().Message.Title)
|
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.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 {
|
type mglist struct {
|
||||||
Messages []gin.H `json:"messages"`
|
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.title", "HelloWorld_001", msg1Get["title"])
|
||||||
tt.AssertStrRepEqual(t, "msg.channel_internal_name", "main", msg1Get["channel_internal_name"])
|
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.AssertEqual(t, "messageCount", 2, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.title", "HelloWorld_002", pusher.Last().Message.Title)
|
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.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"]))
|
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{
|
msg3 := tt.RequestPost[gin.H](t, baseUrl, "/send.php", tt.FormData{
|
||||||
"user_key": sendtok,
|
"user_key": sendtok,
|
||||||
"user_id": fmt.Sprintf("%d", uid),
|
"user_id": fmt.Sprintf("%d", uidold),
|
||||||
"title": "HelloWorld_003",
|
"title": "HelloWorld_003",
|
||||||
"content": content3,
|
"content": content3,
|
||||||
"priority": "2",
|
"priority": "2",
|
||||||
@ -1059,7 +1144,7 @@ func TestSendCompat(t *testing.T) {
|
|||||||
tt.AssertEqual(t, "messageCount", 3, len(pusher.Data))
|
tt.AssertEqual(t, "messageCount", 3, len(pusher.Data))
|
||||||
tt.AssertStrRepEqual(t, "msg.Title", "HelloWorld_003", pusher.Last().Message.Title)
|
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.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.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", "8a2c7e92-86f3-4d69-897a-571286954030", pusher.Last().Message.UserMessageID)
|
||||||
tt.AssertStrRepEqual(t, "msg.UserMessageID", ts3, pusher.Last().Message.Timestamp().Unix())
|
tt.AssertStrRepEqual(t, "msg.UserMessageID", ts3, pusher.Last().Message.Timestamp().Unix())
|
||||||
@ -1077,7 +1162,7 @@ func TestSendToNewChannel(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_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))
|
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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "internal_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "internal_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_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",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
admintok := r0["admin_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{}, clist.Channels, "internal_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main"}, clist.Channels, "internal_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.len", 1, len(clist.Channels))
|
||||||
tt.AssertEqual(t, "chan.internal_name", "main", clist.Channels[0]["internal_name"])
|
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.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",
|
"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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_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, "display_name")
|
||||||
tt.AssertMappedSet(t, "channels", []string{"main", "test"}, clist.Channels, "internal_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",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
tt.RequestPost[tt.Void](t, baseUrl, "/", gin.H{
|
tt.RequestPost[tt.Void](t, baseUrl, "/", gin.H{
|
||||||
@ -1281,7 +1366,7 @@ func TestQuotaExceededNoPro(t *testing.T) {
|
|||||||
"fcm_token": "DUMMY_FCM",
|
"fcm_token": "DUMMY_FCM",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_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", 1, usr["quota_used"])
|
||||||
tt.AssertStrRepEqual(t, "quota.1", 50, usr["quota_max"])
|
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", 49, usr["quota_used"])
|
||||||
tt.AssertStrRepEqual(t, "quota.49", 50, usr["quota_max"])
|
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"])
|
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_used"])
|
||||||
tt.AssertStrRepEqual(t, "quota.50", 50, usr["quota_max"])
|
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",
|
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
admintok := r0["admin_key"].(string)
|
admintok := r0["admin_key"].(string)
|
||||||
sendtok := r0["send_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", 1, usr["quota_used"])
|
||||||
tt.AssertStrRepEqual(t, "quota.1", 1000, usr["quota_max"])
|
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", 999, usr["quota_used"])
|
||||||
tt.AssertStrRepEqual(t, "quota.999", 1000, usr["quota_max"])
|
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"])
|
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_used"])
|
||||||
tt.AssertStrRepEqual(t, "quota.1000", 1000, usr["quota_max"])
|
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",
|
"pro_token": "ANDROID|v2|PURCHASED:DUMMY_TOK_XX",
|
||||||
})
|
})
|
||||||
|
|
||||||
uid := int(r0["user_id"].(float64))
|
uid := r0["user_id"].(string)
|
||||||
sendtok := r0["send_key"].(string)
|
sendtok := r0["send_key"].(string)
|
||||||
|
|
||||||
count := 128
|
count := 128
|
||||||
|
@ -59,7 +59,7 @@ type clientex struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Userdat struct {
|
type Userdat struct {
|
||||||
UID int64
|
UID string
|
||||||
SendKey string
|
SendKey string
|
||||||
AdminKey string
|
AdminKey string
|
||||||
ReadKey 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)
|
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)
|
readtok0 := user0["read_key"].(string)
|
||||||
sendtok0 := user0["send_key"].(string)
|
sendtok0 := user0["send_key"].(string)
|
||||||
admintok0 := user0["admin_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["agent_version"] = cex.AgentVersion
|
||||||
body["client_type"] = cex.ClientType
|
body["client_type"] = cex.ClientType
|
||||||
body["fcm_token"] = cex.FCMTok
|
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
|
// Create Messages
|
||||||
@ -378,7 +378,7 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
|||||||
// create manual channels
|
// 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
|
// Sub/Unsub for Users 12+13
|
||||||
@ -399,7 +399,7 @@ func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat,
|
|||||||
|
|
||||||
if user == chanOwner {
|
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_owner_user_id": chanOwner.UID,
|
||||||
"channel_internal_name": chanInternalName,
|
"channel_internal_name": chanInternalName,
|
||||||
})
|
})
|
||||||
@ -409,7 +409,7 @@ func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat,
|
|||||||
Channels []gin.H `json:"channels"`
|
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
|
var chandat gin.H
|
||||||
for _, v := range clist.Channels {
|
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{
|
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"].(float64),
|
"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"`
|
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
|
var subdat gin.H
|
||||||
for _, v := range slist.Subscriptions {
|
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
|
subdat = v
|
||||||
break
|
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"`
|
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
|
var subdat gin.H
|
||||||
for _, v := range slist.Subscriptions {
|
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
|
subdat = v
|
||||||
break
|
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,
|
"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),
|
jobs.NewRequestLogCollectorJob(app),
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Init(ginengine)
|
err = router.Init(ginengine)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
stop := func() {
|
stop := func() {
|
||||||
app.Stop()
|
app.Stop()
|
||||||
|
_ = app.IsRunning.WaitWithTimeout(5*time.Second, false)
|
||||||
_ = os.Remove(dbfile1)
|
_ = os.Remove(dbfile1)
|
||||||
_ = os.Remove(dbfile2)
|
_ = os.Remove(dbfile2)
|
||||||
_ = os.Remove(dbfile3)
|
_ = os.Remove(dbfile3)
|
||||||
_ = app.IsRunning.WaitWithTimeout(400*time.Millisecond, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() { app.Run() }()
|
go func() { app.Run() }()
|
||||||
|
Loading…
Reference in New Issue
Block a user