added UpdateClient route
This commit is contained in:
parent
3a9b15c2be
commit
0daca2cf8f
1
scnserver/.idea/server.iml
generated
1
scnserver/.idea/server.iml
generated
@ -14,7 +14,6 @@
|
|||||||
<component name="NewModuleRootManager">
|
<component name="NewModuleRootManager">
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/_pygments" />
|
<excludeFolder url="file://$MODULE_DIR$/_pygments" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/swagger" />
|
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
// @ID api-channels-list
|
// @ID api-channels-list
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param selector query string false "Filter channels (default: owned)" Enums(owned, subscribed, all, subscribed_any, all_any)
|
// @Param selector query string false "Filter channels (default: owned)" Enums(owned, subscribed, all, subscribed_any, all_any)
|
||||||
//
|
//
|
||||||
// @Success 200 {object} handler.ListChannels.response
|
// @Success 200 {object} handler.ListChannels.response
|
||||||
@ -162,7 +162,7 @@ func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-channels-create
|
// @ID api-channels-create
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param post_body body handler.CreateChannel.body false " "
|
// @Param post_body body handler.CreateChannel.body false " "
|
||||||
//
|
//
|
||||||
// @Success 200 {object} models.ChannelWithSubscriptionJSON
|
// @Success 200 {object} models.ChannelWithSubscriptionJSON
|
||||||
@ -260,8 +260,8 @@ func (h APIHandler) CreateChannel(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-channels-update
|
// @ID api-channels-update
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param cid path int true "ChannelID"
|
// @Param cid path string true "ChannelID"
|
||||||
//
|
//
|
||||||
// @Param subscribe_key body string false "Send `true` to create a new subscribe_key"
|
// @Param subscribe_key body string false "Send `true` to create a new subscribe_key"
|
||||||
// @Param send_key body string false "Send `true` to create a new send_key"
|
// @Param send_key body string false "Send `true` to create a new send_key"
|
||||||
@ -378,8 +378,8 @@ func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param query_data query handler.ListChannelMessages.query false " "
|
// @Param query_data query handler.ListChannelMessages.query false " "
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param cid path int true "ChannelID"
|
// @Param cid path string true "ChannelID"
|
||||||
//
|
//
|
||||||
// @Success 200 {object} handler.ListChannelMessages.response
|
// @Success 200 {object} handler.ListChannelMessages.response
|
||||||
// @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"
|
||||||
|
@ -103,7 +103,7 @@ func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-clients-create
|
// @ID api-clients-create
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
//
|
//
|
||||||
// @Param post_body body handler.AddClient.body false " "
|
// @Param post_body body handler.AddClient.body false " "
|
||||||
//
|
//
|
||||||
@ -206,3 +206,89 @@ func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
|
|
||||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, client.JSON()))
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, client.JSON()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateClient swaggerdoc
|
||||||
|
//
|
||||||
|
// @Summary (Partially) update a client
|
||||||
|
// @Description The body-values are optional, only send the ones you want to update
|
||||||
|
// @ID api-client-update
|
||||||
|
// @Tags API-v2
|
||||||
|
//
|
||||||
|
// @Param uid path string true "UserID"
|
||||||
|
// @Param cid path string true "ClientID"
|
||||||
|
//
|
||||||
|
// @Param clientname body string false "Change the clientname (send an empty string to clear it)"
|
||||||
|
// @Param pro_token body string false "Send a verification of premium purchase"
|
||||||
|
//
|
||||||
|
// @Success 200 {object} models.ClientJSON
|
||||||
|
// @Failure 400 {object} ginresp.apiError "supplied values/parameters cannot be parsed / are invalid"
|
||||||
|
// @Failure 401 {object} ginresp.apiError "client is not authorized / has missing permissions"
|
||||||
|
// @Failure 404 {object} ginresp.apiError "client not found"
|
||||||
|
// @Failure 500 {object} ginresp.apiError "internal server error"
|
||||||
|
//
|
||||||
|
// @Router /api/v2/users/{uid}/clients/{cid} [PATCH]
|
||||||
|
func (h APIHandler) UpdateClient(g *gin.Context) ginresp.HTTPResponse {
|
||||||
|
type uri struct {
|
||||||
|
UserID models.UserID `uri:"uid" binding:"entityid"`
|
||||||
|
ClientID models.ClientID `uri:"cid" binding:"entityid"`
|
||||||
|
}
|
||||||
|
type body struct {
|
||||||
|
FCMToken *string `json:"fcm_token"`
|
||||||
|
AgentModel *string `json:"agent_model"`
|
||||||
|
AgentVersion *string `json:"agent_version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var u uri
|
||||||
|
var b body
|
||||||
|
ctx, errResp := h.app.StartRequest(g, &u, nil, &b, nil)
|
||||||
|
if errResp != nil {
|
||||||
|
return *errResp
|
||||||
|
}
|
||||||
|
defer ctx.Cancel()
|
||||||
|
|
||||||
|
if permResp := ctx.CheckPermissionUserAdmin(u.UserID); permResp != nil {
|
||||||
|
return *permResp
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := h.database.GetClient(ctx, u.UserID, u.ClientID)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return ginresp.APIError(g, 404, apierr.CLIENT_NOT_FOUND, "Client not found", err)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query client", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.FCMToken != nil && *b.FCMToken != client.FCMToken {
|
||||||
|
|
||||||
|
err = h.database.DeleteClientsByFCM(ctx, *b.FCMToken)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to delete existing clients in db", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.database.UpdateClientFCMToken(ctx, u.ClientID, *b.FCMToken)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update client", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.AgentModel != nil {
|
||||||
|
err = h.database.UpdateClientAgentModel(ctx, u.ClientID, *b.AgentModel)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update client", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.AgentVersion != nil {
|
||||||
|
err = h.database.UpdateClientAgentVersion(ctx, u.ClientID, *b.AgentVersion)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update client", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err = h.database.GetClient(ctx, u.UserID, u.ClientID)
|
||||||
|
if err != nil {
|
||||||
|
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query (updated) client", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, client.JSON()))
|
||||||
|
}
|
||||||
|
@ -106,8 +106,8 @@ func (h APIHandler) GetUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-tokenkeys-update
|
// @ID api-tokenkeys-update
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param kid path int true "TokenKeyID"
|
// @Param kid path string true "TokenKeyID"
|
||||||
//
|
//
|
||||||
// @Param post_body body handler.UpdateUserKey.body false " "
|
// @Param post_body body handler.UpdateUserKey.body false " "
|
||||||
//
|
//
|
||||||
@ -204,7 +204,7 @@ func (h APIHandler) UpdateUserKey(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-tokenkeys-create
|
// @ID api-tokenkeys-create
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
//
|
//
|
||||||
// @Param post_body body handler.CreateUserKey.body false " "
|
// @Param post_body body handler.CreateUserKey.body false " "
|
||||||
//
|
//
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
// @ID api-user-subscriptions-list
|
// @ID api-user-subscriptions-list
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param selector query string true "Filter subscriptions (default: outgoing_all)" Enums(outgoing_all, outgoing_confirmed, outgoing_unconfirmed, incoming_all, incoming_confirmed, incoming_unconfirmed)
|
// @Param selector query string true "Filter subscriptions (default: outgoing_all)" Enums(outgoing_all, outgoing_confirmed, outgoing_unconfirmed, incoming_all, incoming_confirmed, incoming_unconfirmed)
|
||||||
//
|
//
|
||||||
// @Success 200 {object} handler.ListUserSubscriptions.response
|
// @Success 200 {object} handler.ListUserSubscriptions.response
|
||||||
@ -275,7 +275,7 @@ func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-subscriptions-create
|
// @ID api-subscriptions-create
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param query_data query handler.CreateSubscription.query false " "
|
// @Param query_data query handler.CreateSubscription.query false " "
|
||||||
// @Param post_data body handler.CreateSubscription.body false " "
|
// @Param post_data body handler.CreateSubscription.body false " "
|
||||||
//
|
//
|
||||||
@ -363,8 +363,8 @@ func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-subscriptions-update
|
// @ID api-subscriptions-update
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
// @Param sid path int true "SubscriptionID"
|
// @Param sid path string true "SubscriptionID"
|
||||||
// @Param post_data body handler.UpdateSubscription.body false " "
|
// @Param post_data body handler.UpdateSubscription.body false " "
|
||||||
//
|
//
|
||||||
// @Success 200 {object} models.SubscriptionJSON
|
// @Success 200 {object} models.SubscriptionJSON
|
||||||
|
@ -180,7 +180,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
// @ID api-user-update
|
// @ID api-user-update
|
||||||
// @Tags API-v2
|
// @Tags API-v2
|
||||||
//
|
//
|
||||||
// @Param uid path int true "UserID"
|
// @Param uid path string true "UserID"
|
||||||
//
|
//
|
||||||
// @Param username body string false "Change the username (send an empty string to clear it)"
|
// @Param username body string false "Change the username (send an empty string to clear it)"
|
||||||
// @Param pro_token body string false "Send a verification of premium purchase"
|
// @Param pro_token body string false "Send a verification of premium purchase"
|
||||||
|
@ -325,8 +325,6 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
return ginresp.CompatAPIError(0, "Failed to query clients")
|
return ginresp.CompatAPIError(0, "Failed to query clients")
|
||||||
}
|
}
|
||||||
|
|
||||||
fcmSet := langext.ArrAny(clients, func(c models.Client) bool { return c.FCMToken != nil })
|
|
||||||
|
|
||||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
|
||||||
Success: true,
|
Success: true,
|
||||||
Message: "ok",
|
Message: "ok",
|
||||||
@ -335,7 +333,7 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
|
|||||||
QuotaUsed: user.QuotaUsedToday(),
|
QuotaUsed: user.QuotaUsedToday(),
|
||||||
QuotaMax: user.QuotaPerDay(),
|
QuotaMax: user.QuotaPerDay(),
|
||||||
IsPro: langext.Conditional(user.IsPro, 1, 0),
|
IsPro: langext.Conditional(user.IsPro, 1, 0),
|
||||||
FCMSet: fcmSet,
|
FCMSet: len(clients) > 0,
|
||||||
UnackCount: 0,
|
UnackCount: 0,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex
|
|||||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create delivery", err))
|
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create delivery", err))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err = h.database.CreateSuccessDelivery(ctx, client, msg, *fcmDelivID)
|
_, err = h.database.CreateSuccessDelivery(ctx, client, msg, fcmDelivID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create delivery", err))
|
return nil, langext.Ptr(ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, hl.NONE, "Failed to create delivery", err))
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,7 @@ func (r *Router) Init(e *gin.Engine) error {
|
|||||||
|
|
||||||
apiv2.GET("/users/:uid/clients", r.Wrap(r.apiHandler.ListClients))
|
apiv2.GET("/users/:uid/clients", r.Wrap(r.apiHandler.ListClients))
|
||||||
apiv2.GET("/users/:uid/clients/:cid", r.Wrap(r.apiHandler.GetClient))
|
apiv2.GET("/users/:uid/clients/:cid", r.Wrap(r.apiHandler.GetClient))
|
||||||
|
apiv2.PATCH("/users/:uid/clients/:cid", r.Wrap(r.apiHandler.UpdateClient))
|
||||||
apiv2.POST("/users/:uid/clients", r.Wrap(r.apiHandler.AddClient))
|
apiv2.POST("/users/:uid/clients", r.Wrap(r.apiHandler.AddClient))
|
||||||
apiv2.DELETE("/users/:uid/clients/:cid", r.Wrap(r.apiHandler.DeleteClient))
|
apiv2.DELETE("/users/:uid/clients/:cid", r.Wrap(r.apiHandler.DeleteClient))
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package primary
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blackforestbytes.com/simplecloudnotifier/models"
|
"blackforestbytes.com/simplecloudnotifier/models"
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/sq"
|
"gogs.mikescher.com/BlackForestBytes/goext/sq"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -17,7 +16,7 @@ func (db *Database) CreateClient(ctx TxContext, userid models.UserID, ctype mode
|
|||||||
ClientID: models.NewClientID(),
|
ClientID: models.NewClientID(),
|
||||||
UserID: userid,
|
UserID: userid,
|
||||||
Type: ctype,
|
Type: ctype,
|
||||||
FCMToken: langext.Ptr(fcmToken),
|
FCMToken: fcmToken,
|
||||||
TimestampCreated: time2DB(time.Now()),
|
TimestampCreated: time2DB(time.Now()),
|
||||||
AgentModel: agentModel,
|
AgentModel: agentModel,
|
||||||
AgentVersion: agentVersion,
|
AgentVersion: agentVersion,
|
||||||
@ -113,3 +112,54 @@ func (db *Database) DeleteClientsByFCM(ctx TxContext, fcmtoken string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Database) UpdateClientFCMToken(ctx TxContext, clientid models.ClientID, fcmtoken string) error {
|
||||||
|
tx, err := ctx.GetOrCreateTransaction(db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(ctx, "UPDATE clients SET fcm_token = :vvv WHERE client_id = :cid", sq.PP{
|
||||||
|
"vvv": fcmtoken,
|
||||||
|
"cid": clientid,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) UpdateClientAgentModel(ctx TxContext, clientid models.ClientID, agentModel string) error {
|
||||||
|
tx, err := ctx.GetOrCreateTransaction(db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(ctx, "UPDATE clients SET agent_model = :vvv WHERE client_id = :cid", sq.PP{
|
||||||
|
"vvv": agentModel,
|
||||||
|
"cid": clientid,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Database) UpdateClientAgentVersion(ctx TxContext, clientid models.ClientID, agentVersion string) error {
|
||||||
|
tx, err := ctx.GetOrCreateTransaction(db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(ctx, "UPDATE clients SET agent_version = :vvv WHERE client_id = :cid", sq.PP{
|
||||||
|
"vvv": agentVersion,
|
||||||
|
"cid": clientid,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -50,7 +50,7 @@ CREATE TABLE clients
|
|||||||
|
|
||||||
user_id TEXT 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 NOT NULL,
|
||||||
|
|
||||||
timestamp_created INTEGER NOT NULL,
|
timestamp_created INTEGER NOT NULL,
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ require (
|
|||||||
github.com/jmoiron/sqlx v1.3.5
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
github.com/rs/zerolog v1.28.0
|
github.com/rs/zerolog v1.28.0
|
||||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.126
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.127
|
||||||
gopkg.in/loremipsum.v1 v1.1.0
|
gopkg.in/loremipsum.v1 v1.1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,6 +81,8 @@ gogs.mikescher.com/BlackForestBytes/goext v0.0.125 h1:l4C5/CQS/IVm364oZa8MqiG62+
|
|||||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.125/go.mod h1:w8JlyUHpoOJmW5GxsiheZkFh3vn8Mp80ynSVOFLszL0=
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.125/go.mod h1:w8JlyUHpoOJmW5GxsiheZkFh3vn8Mp80ynSVOFLszL0=
|
||||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.126 h1:o3u0STRaPkmNBenqzvXAOPALSyRswuDwl3Y/0MVHAx4=
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.126 h1:o3u0STRaPkmNBenqzvXAOPALSyRswuDwl3Y/0MVHAx4=
|
||||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.126/go.mod h1:w8JlyUHpoOJmW5GxsiheZkFh3vn8Mp80ynSVOFLszL0=
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.126/go.mod h1:w8JlyUHpoOJmW5GxsiheZkFh3vn8Mp80ynSVOFLszL0=
|
||||||
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.127 h1:NYrSO1kjFWL1yMh0xqIeMZ4hUJiGjILMQwvZMLy4VEg=
|
||||||
|
gogs.mikescher.com/BlackForestBytes/goext v0.0.127/go.mod h1:w8JlyUHpoOJmW5GxsiheZkFh3vn8Mp80ynSVOFLszL0=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||||
|
@ -158,7 +158,7 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
|
|||||||
|
|
||||||
fcmDelivID, err := j.app.DeliverMessage(ctx, client, msg, nil)
|
fcmDelivID, err := j.app.DeliverMessage(ctx, client, msg, nil)
|
||||||
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).Str("MessageID", delivery.MessageID.String()).Str("DeliveryID", delivery.DeliveryID.String()).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()
|
||||||
|
@ -339,17 +339,13 @@ func (app *Application) NormalizeUsername(v string) string {
|
|||||||
return strings.TrimSpace(v)
|
return strings.TrimSpace(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *Application) DeliverMessage(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (*string, error) {
|
func (app *Application) DeliverMessage(ctx context.Context, client models.Client, msg models.Message, compatTitleOverride *string) (string, error) {
|
||||||
if client.FCMToken != nil {
|
|
||||||
fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg, compatTitleOverride)
|
fcmDelivID, err := app.Pusher.SendNotification(ctx, client, msg, compatTitleOverride)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Str("MessageID", msg.MessageID.String()).Str("ClientID", client.ClientID.String()).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 "", err
|
||||||
}
|
|
||||||
return langext.Ptr(fcmDelivID), nil
|
|
||||||
} else {
|
|
||||||
return langext.Ptr(""), nil
|
|
||||||
}
|
}
|
||||||
|
return fcmDelivID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *Application) InsertRequestLog(data models.RequestLog) {
|
func (app *Application) InsertRequestLog(data models.RequestLog) {
|
||||||
|
@ -18,7 +18,7 @@ type Client struct {
|
|||||||
ClientID ClientID
|
ClientID ClientID
|
||||||
UserID UserID
|
UserID UserID
|
||||||
Type ClientType
|
Type ClientType
|
||||||
FCMToken *string
|
FCMToken string
|
||||||
TimestampCreated time.Time
|
TimestampCreated time.Time
|
||||||
AgentModel string
|
AgentModel string
|
||||||
AgentVersion string
|
AgentVersion string
|
||||||
@ -40,7 +40,7 @@ type ClientJSON struct {
|
|||||||
ClientID ClientID `json:"client_id"`
|
ClientID ClientID `json:"client_id"`
|
||||||
UserID UserID `json:"user_id"`
|
UserID UserID `json:"user_id"`
|
||||||
Type ClientType `json:"type"`
|
Type ClientType `json:"type"`
|
||||||
FCMToken *string `json:"fcm_token"`
|
FCMToken string `json:"fcm_token"`
|
||||||
TimestampCreated string `json:"timestamp_created"`
|
TimestampCreated string `json:"timestamp_created"`
|
||||||
AgentModel string `json:"agent_model"`
|
AgentModel string `json:"agent_model"`
|
||||||
AgentVersion string `json:"agent_version"`
|
AgentVersion string `json:"agent_version"`
|
||||||
@ -50,7 +50,7 @@ type ClientDB struct {
|
|||||||
ClientID ClientID `db:"client_id"`
|
ClientID ClientID `db:"client_id"`
|
||||||
UserID UserID `db:"user_id"`
|
UserID UserID `db:"user_id"`
|
||||||
Type ClientType `db:"type"`
|
Type ClientType `db:"type"`
|
||||||
FCMToken *string `db:"fcm_token"`
|
FCMToken string `db:"fcm_token"`
|
||||||
TimestampCreated int64 `db:"timestamp_created"`
|
TimestampCreated int64 `db:"timestamp_created"`
|
||||||
AgentModel string `db:"agent_model"`
|
AgentModel string `db:"agent_model"`
|
||||||
AgentVersion string `db:"agent_version"`
|
AgentVersion string `db:"agent_version"`
|
||||||
|
@ -65,7 +65,7 @@ func (fb FirebaseConnector) SendNotification(ctx context.Context, client models.
|
|||||||
"title": langext.Coalesce(compatTitleOverride, msg.Title),
|
"title": langext.Coalesce(compatTitleOverride, msg.Title),
|
||||||
"body": langext.Coalesce(msg.TrimmedContent(), ""),
|
"body": langext.Coalesce(msg.TrimmedContent(), ""),
|
||||||
},
|
},
|
||||||
"token": *client.FCMToken,
|
"token": client.FCMToken,
|
||||||
"android": gin.H{
|
"android": gin.H{
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
},
|
},
|
||||||
|
@ -57,7 +57,42 @@ func TestGetClient(t *testing.T) {
|
|||||||
tt.AssertJsonMapEqual(t, "client", r3, c0)
|
tt.AssertJsonMapEqual(t, "client", r3, c0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateAndDeleteClient(t *testing.T) {
|
func TestCreateClient(t *testing.T) {
|
||||||
|
_, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/v2/users", gin.H{
|
||||||
|
"agent_model": "DUMMY_PHONE",
|
||||||
|
"agent_version": "4X",
|
||||||
|
"client_type": "ANDROID",
|
||||||
|
"fcm_token": "DUMMY_FCM",
|
||||||
|
})
|
||||||
|
|
||||||
|
uid := fmt.Sprintf("%v", r0["user_id"])
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "len(clients)", 1, len(r0["clients"].([]any)))
|
||||||
|
|
||||||
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
|
fmt.Printf("uid := %s\n", uid)
|
||||||
|
fmt.Printf("admin_key := %s\n", admintok)
|
||||||
|
|
||||||
|
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients", gin.H{
|
||||||
|
"agent_model": "DUMMY_PHONE_2",
|
||||||
|
"agent_version": "99X",
|
||||||
|
"client_type": "IOS",
|
||||||
|
"fcm_token": "DUMMY_FCM_2",
|
||||||
|
})
|
||||||
|
|
||||||
|
type rt3 struct {
|
||||||
|
Clients []gin.H `json:"clients"`
|
||||||
|
}
|
||||||
|
|
||||||
|
r3 := tt.RequestAuthGet[rt3](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients")
|
||||||
|
tt.AssertEqual(t, "len(clients)", 2, len(r3.Clients))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteClient(t *testing.T) {
|
||||||
_, baseUrl, stop := tt.StartSimpleWebserver(t)
|
_, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
@ -191,3 +226,63 @@ func TestListClients(t *testing.T) {
|
|||||||
|
|
||||||
tt.RequestAuthGetShouldFail(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/clients", url.QueryEscape(data.User[1].UID)), 401, apierr.USER_AUTH_FAILED)
|
tt.RequestAuthGetShouldFail(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/clients", url.QueryEscape(data.User[1].UID)), 401, apierr.USER_AUTH_FAILED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdateClient(t *testing.T) {
|
||||||
|
_, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
r0 := tt.RequestPost[gin.H](t, baseUrl, "/api/v2/users", gin.H{
|
||||||
|
"agent_model": "DUMMY_PHONE",
|
||||||
|
"agent_version": "4X",
|
||||||
|
"client_type": "ANDROID",
|
||||||
|
"fcm_token": "DUMMY_FCM",
|
||||||
|
})
|
||||||
|
|
||||||
|
uid := fmt.Sprintf("%v", r0["user_id"])
|
||||||
|
|
||||||
|
tt.AssertEqual(t, "len(clients)", 1, len(r0["clients"].([]any)))
|
||||||
|
|
||||||
|
admintok := r0["admin_key"].(string)
|
||||||
|
|
||||||
|
fmt.Printf("uid := %s\n", uid)
|
||||||
|
fmt.Printf("admin_key := %s\n", admintok)
|
||||||
|
|
||||||
|
r2 := tt.RequestAuthPost[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients", gin.H{
|
||||||
|
"agent_model": "DUMMY_PHONE_2",
|
||||||
|
"agent_version": "99X",
|
||||||
|
"client_type": "IOS",
|
||||||
|
"fcm_token": "DUMMY_FCM_2",
|
||||||
|
})
|
||||||
|
|
||||||
|
cid2 := fmt.Sprintf("%v", r2["client_id"])
|
||||||
|
|
||||||
|
type rt3 struct {
|
||||||
|
Clients []gin.H `json:"clients"`
|
||||||
|
}
|
||||||
|
|
||||||
|
r3 := tt.RequestAuthGet[rt3](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients")
|
||||||
|
tt.AssertEqual(t, "len(clients)", 2, len(r3.Clients))
|
||||||
|
|
||||||
|
r4 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2)
|
||||||
|
tt.AssertEqual(t, "agent_model", "DUMMY_PHONE_2", r4["agent_model"])
|
||||||
|
tt.AssertEqual(t, "agent_version", "99X", r4["agent_version"])
|
||||||
|
tt.AssertEqual(t, "client_type", "IOS", r4["type"])
|
||||||
|
tt.AssertEqual(t, "fcm_token", "DUMMY_FCM_2", r4["fcm_token"])
|
||||||
|
|
||||||
|
r5 := tt.RequestAuthPatch[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2, gin.H{
|
||||||
|
"agent_model": "PP_DUMMY_PHONE_2",
|
||||||
|
"agent_version": "PP_99X",
|
||||||
|
"fcm_token": "PP_DUMMY_FCM_2",
|
||||||
|
})
|
||||||
|
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r5["agent_model"])
|
||||||
|
tt.AssertEqual(t, "agent_version", "PP_99X", r5["agent_version"])
|
||||||
|
tt.AssertEqual(t, "client_type", "IOS", r5["type"])
|
||||||
|
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r5["fcm_token"])
|
||||||
|
|
||||||
|
r6 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2)
|
||||||
|
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r6["agent_model"])
|
||||||
|
tt.AssertEqual(t, "agent_version", "PP_99X", r6["agent_version"])
|
||||||
|
tt.AssertEqual(t, "client_type", "IOS", r6["type"])
|
||||||
|
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r6["fcm_token"])
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -477,7 +477,7 @@ func TestCompatUpdateUserKey(t *testing.T) {
|
|||||||
|
|
||||||
s0 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, userkey, url.QueryEscape("msg_1")), nil)
|
s0 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, userkey, url.QueryEscape("msg_1")), nil)
|
||||||
tt.AssertEqual(t, "success", true, s0["success"])
|
tt.AssertEqual(t, "success", true, s0["success"])
|
||||||
tt.AssertEqual(t, "fcm", "DUMMY_FCM", *pusher.Last().Client.FCMToken)
|
tt.AssertEqual(t, "fcm", "DUMMY_FCM", pusher.Last().Client.FCMToken)
|
||||||
|
|
||||||
upd := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/update.php?user_id=%d&user_key=%s", userid, userkey))
|
upd := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/update.php?user_id=%d&user_key=%s", userid, userkey))
|
||||||
tt.AssertEqual(t, "success", true, upd["success"])
|
tt.AssertEqual(t, "success", true, upd["success"])
|
||||||
@ -497,7 +497,7 @@ func TestCompatUpdateUserKey(t *testing.T) {
|
|||||||
|
|
||||||
s1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, newkey, url.QueryEscape("msg_2")), nil)
|
s1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, newkey, url.QueryEscape("msg_2")), nil)
|
||||||
tt.AssertEqual(t, "success", true, s1["success"])
|
tt.AssertEqual(t, "success", true, s1["success"])
|
||||||
tt.AssertEqual(t, "fcm", "DUMMY_FCM", *pusher.Last().Client.FCMToken)
|
tt.AssertEqual(t, "fcm", "DUMMY_FCM", pusher.Last().Client.FCMToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompatUpdateFCM(t *testing.T) {
|
func TestCompatUpdateFCM(t *testing.T) {
|
||||||
@ -514,7 +514,7 @@ func TestCompatUpdateFCM(t *testing.T) {
|
|||||||
|
|
||||||
s0 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, userkey, url.QueryEscape("msg_1")), nil)
|
s0 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, userkey, url.QueryEscape("msg_1")), nil)
|
||||||
tt.AssertEqual(t, "success", true, s0["success"])
|
tt.AssertEqual(t, "success", true, s0["success"])
|
||||||
tt.AssertEqual(t, "fcm", "DUMMY_FCM", *pusher.Last().Client.FCMToken)
|
tt.AssertEqual(t, "fcm", "DUMMY_FCM", pusher.Last().Client.FCMToken)
|
||||||
|
|
||||||
upd := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/update.php?user_id=%d&user_key=%s&fcm_token=%s", userid, userkey, "NEW_FCM"))
|
upd := tt.RequestGet[gin.H](t, baseUrl, fmt.Sprintf("/api/update.php?user_id=%d&user_key=%s&fcm_token=%s", userid, userkey, "NEW_FCM"))
|
||||||
tt.AssertEqual(t, "success", true, upd["success"])
|
tt.AssertEqual(t, "success", true, upd["success"])
|
||||||
@ -534,7 +534,7 @@ func TestCompatUpdateFCM(t *testing.T) {
|
|||||||
|
|
||||||
s1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, newkey, url.QueryEscape("msg_2")), nil)
|
s1 := tt.RequestPost[gin.H](t, baseUrl, fmt.Sprintf("/send.php?user_id=%d&user_key=%s&title=%s", userid, newkey, url.QueryEscape("msg_2")), nil)
|
||||||
tt.AssertEqual(t, "success", true, s1["success"])
|
tt.AssertEqual(t, "success", true, s1["success"])
|
||||||
tt.AssertEqual(t, "fcm", "NEW_FCM", *pusher.Last().Client.FCMToken)
|
tt.AssertEqual(t, "fcm", "NEW_FCM", pusher.Last().Client.FCMToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompatUpgrade(t *testing.T) {
|
func TestCompatUpgrade(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user