From 0cc6e27267054e36f16095b767fde01e56ffef1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Sun, 20 Nov 2022 22:18:24 +0100 Subject: [PATCH] Use ID types --- server/README.md | 2 +- server/api/handler/api.go | 68 +++++++++---------- server/api/handler/compat.go | 24 +++---- server/api/handler/message.go | 117 ++++++++++++++++---------------- server/db/channels.go | 24 +++---- server/db/clients.go | 10 +-- server/db/deliveries.go | 6 +- server/db/messages.go | 16 ++--- server/db/subscriptions.go | 16 ++--- server/db/users.go | 18 ++--- server/firebase/firebase.go | 4 +- server/jobs/DeliveryRetryJob.go | 12 ++-- server/logic/application.go | 18 +++-- server/logic/permissions.go | 8 +-- server/models/channel.go | 38 +++++------ server/models/client.go | 12 ++-- server/models/delivery.go | 24 +++---- server/models/ids.go | 68 +++++++++++++++++++ server/models/message.go | 52 +++++++------- server/models/subscription.go | 36 +++++----- server/models/user.go | 12 +++- server/swagger/swagger.json | 3 + server/swagger/swagger.yaml | 2 + 23 files changed, 334 insertions(+), 256 deletions(-) create mode 100644 server/models/ids.go diff --git a/server/README.md b/server/README.md index eb9b396..daa0a5e 100644 --- a/server/README.md +++ b/server/README.md @@ -4,8 +4,8 @@ - ack/read deliveries && return ack-count - - go ID types + - verify pro_token - full-text-search: https://www.sqlite.org/fts5.html#contentless_tables - deploy diff --git a/server/api/handler/api.go b/server/api/handler/api.go index 605c20e..c0712f8 100644 --- a/server/api/handler/api.go +++ b/server/api/handler/api.go @@ -129,7 +129,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid} [GET] func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } var u uri @@ -177,7 +177,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid} [PATCH] func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } type body struct { Username *string `json:"username"` @@ -283,7 +283,7 @@ func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/clients [GET] func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } type response struct { Clients []models.ClientJSON `json:"clients"` @@ -327,8 +327,8 @@ func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/clients/{cid} [GET] func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - ClientID int64 `uri:"cid"` + UserID models.UserID `uri:"uid"` + ClientID models.ClientID `uri:"cid"` } var u uri @@ -371,7 +371,7 @@ func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/clients [POST] func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } type body struct { FCMToken string `json:"fcm_token" binding:"required"` @@ -426,8 +426,8 @@ func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/clients [POST] func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - ClientID int64 `uri:"cid"` + UserID models.UserID `uri:"uid"` + ClientID models.ClientID `uri:"cid"` } var u uri @@ -480,7 +480,7 @@ func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/channels [GET] func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } type query struct { Selector *string `form:"selector"` @@ -559,8 +559,8 @@ func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/channels/{cid} [GET] func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - ChannelID int64 `uri:"cid"` + UserID models.UserID `uri:"uid"` + ChannelID models.ChannelID `uri:"cid"` } var u uri @@ -605,8 +605,8 @@ func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/channels/{cid} [PATCH] func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - ChannelID int64 `uri:"cid"` + UserID models.UserID `uri:"uid"` + ChannelID models.ChannelID `uri:"cid"` } type body struct { RefreshSubscribeKey *bool `json:"subscribe_key"` @@ -679,8 +679,8 @@ func (h APIHandler) UpdateChannel(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/channels/{cid}/messages [GET] func (h APIHandler) ListChannelMessages(g *gin.Context) ginresp.HTTPResponse { type uri struct { - ChannelUserID int64 `uri:"uid"` - ChannelID int64 `uri:"cid"` + ChannelUserID models.UserID `uri:"uid"` + ChannelID models.ChannelID `uri:"cid"` } type query struct { PageSize *int `form:"page_size"` @@ -769,7 +769,7 @@ func (h APIHandler) ListChannelMessages(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/subscriptions [GET] func (h APIHandler) ListUserSubscriptions(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } type response struct { Subscriptions []models.SubscriptionJSON `json:"subscriptions"` @@ -813,8 +813,8 @@ func (h APIHandler) ListUserSubscriptions(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/channels/{cid}/subscriptions [GET] func (h APIHandler) ListChannelSubscriptions(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - ChannelID int64 `uri:"cid"` + UserID models.UserID `uri:"uid"` + ChannelID models.ChannelID `uri:"cid"` } type response struct { Subscriptions []models.SubscriptionJSON `json:"subscriptions"` @@ -866,8 +866,8 @@ func (h APIHandler) ListChannelSubscriptions(g *gin.Context) ginresp.HTTPRespons // @Router /api-v2/users/{uid}/subscriptions/{sid} [GET] func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - SubscriptionID int64 `uri:"sid"` + UserID models.UserID `uri:"uid"` + SubscriptionID models.SubscriptionID `uri:"sid"` } var u uri @@ -913,8 +913,8 @@ func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/subscriptions/{sid} [DELETE] func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - SubscriptionID int64 `uri:"sid"` + UserID models.UserID `uri:"uid"` + SubscriptionID models.SubscriptionID `uri:"sid"` } var u uri @@ -966,11 +966,11 @@ func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/subscriptions [POST] func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` + UserID models.UserID `uri:"uid"` } type body struct { - ChannelOwnerUserID int64 `form:"channel_owner_user_id" binding:"required"` - Channel string `form:"channel_name" binding:"required"` + ChannelOwnerUserID models.UserID `form:"channel_owner_user_id" binding:"required"` + Channel string `form:"channel_name" binding:"required"` } type query struct { ChanSubscribeKey *string `form:"chan_subscribe_key"` @@ -1026,8 +1026,8 @@ func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/users/{uid}/subscriptions/{sid} [PATCH] func (h APIHandler) UpdateSubscription(g *gin.Context) ginresp.HTTPResponse { type uri struct { - UserID int64 `uri:"uid"` - SubscriptionID int64 `uri:"sid"` + UserID models.UserID `uri:"uid"` + SubscriptionID models.SubscriptionID `uri:"sid"` } type body struct { Confirmed *bool `form:"confirmed"` @@ -1166,7 +1166,7 @@ func (h APIHandler) ListMessages(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/messages/{mid} [PATCH] func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse { type uri struct { - MessageID int64 `uri:"mid"` + MessageID models.SCNMessageID `uri:"mid"` } var u uri @@ -1235,7 +1235,7 @@ func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse { // @Router /api-v2/messages/{mid} [PATCH] func (h APIHandler) DeleteMessage(g *gin.Context) ginresp.HTTPResponse { type uri struct { - MessageID int64 `uri:"mid"` + MessageID models.SCNMessageID `uri:"mid"` } var u uri @@ -1337,11 +1337,6 @@ func (h APIHandler) CreateMessage(g *gin.Context) ginresp.HTTPResponse { return ginresp.SendAPIError(g, 400, apierr.USR_MSG_ID_TOO_LONG, -1, "MessageID too long (64 characters)", nil) } - channelName := h.app.DefaultChannel - if b.Channel != nil { - channelName = h.app.NormalizeChannelName(*b.Channel) - } - user, err := h.database.GetUser(ctx, userID) if err == sql.ErrNoRows { return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, -1, "User not found", nil) @@ -1350,6 +1345,11 @@ func (h APIHandler) CreateMessage(g *gin.Context) ginresp.HTTPResponse { return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query user", err) } + channelName := user.DefaultChannel() + if b.Channel != nil { + channelName = h.app.NormalizeChannelName(*b.Channel) + } + if len(*b.Title) > user.MaxTitleLength() { return ginresp.SendAPIError(g, 400, apierr.TITLE_TOO_LONG, 103, fmt.Sprintf("Title too long (max %d characters)", user.MaxTitleLength()), nil) } diff --git a/server/api/handler/compat.go b/server/api/handler/compat.go index 93092f9..495927d 100644 --- a/server/api/handler/compat.go +++ b/server/api/handler/compat.go @@ -122,7 +122,7 @@ func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse { return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{ Success: true, Message: "New user registered", - UserID: user.UserID, + UserID: user.UserID.IntID(), UserKey: user.AdminKey, QuotaUsed: user.QuotaUsedToday(), QuotaMax: user.QuotaPerDay(), @@ -180,7 +180,7 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]") } - user, err := h.database.GetUser(ctx, *data.UserID) + user, err := h.database.GetUser(ctx, models.UserID(*data.UserID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(201, "User not found") } @@ -202,7 +202,7 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse { return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{ Success: true, Message: "ok", - UserID: user.UserID, + UserID: user.UserID.IntID(), UserKey: user.AdminKey, QuotaUsed: user.QuotaUsedToday(), QuotaMax: user.QuotaPerDay(), @@ -263,7 +263,7 @@ func (h CompatHandler) Ack(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(103, "Missing parameter [[scn_msg_id]]") } - user, err := h.database.GetUser(ctx, *data.UserID) + user, err := h.database.GetUser(ctx, models.UserID(*data.UserID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(201, "User not found") } @@ -328,7 +328,7 @@ func (h CompatHandler) Requery(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]") } - user, err := h.database.GetUser(ctx, *data.UserID) + user, err := h.database.GetUser(ctx, models.UserID(*data.UserID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(201, "User not found") } @@ -399,7 +399,7 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(102, "Missing parameter [[user_key]]") } - user, err := h.database.GetUser(ctx, *data.UserID) + user, err := h.database.GetUser(ctx, models.UserID(*data.UserID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(201, "User not found") } @@ -451,7 +451,7 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse { return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{ Success: true, Message: "user updated", - UserID: user.UserID, + UserID: user.UserID.IntID(), UserKey: user.AdminKey, QuotaUsed: user.QuotaUsedToday(), QuotaMax: user.QuotaPerDay(), @@ -509,7 +509,7 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(103, "Missing parameter [[scn_msg_id]]") } - user, err := h.database.GetUser(ctx, *data.UserID) + user, err := h.database.GetUser(ctx, models.UserID(*data.UserID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(201, "User not found") } @@ -521,7 +521,7 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(204, "Authentification failed") } - msg, err := h.database.GetMessage(ctx, *data.MessageID) + msg, err := h.database.GetMessage(ctx, models.SCNMessageID(*data.MessageID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(301, "Message not found") } @@ -539,7 +539,7 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse { Priority: msg.Priority, Timestamp: msg.Timestamp().Unix(), UserMessageID: msg.UserMessageID, - SCNMessageID: msg.SCNMessageID, + SCNMessageID: msg.SCNMessageID.IntID(), }, })) } @@ -603,7 +603,7 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse { return ginresp.CompatAPIError(104, "Missing parameter [[pro_token]]") } - user, err := h.database.GetUser(ctx, *data.UserID) + user, err := h.database.GetUser(ctx, models.UserID(*data.UserID)) if err == sql.ErrNoRows { return ginresp.CompatAPIError(201, "User not found") } @@ -648,7 +648,7 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse { return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{ Success: true, Message: "user updated", - UserID: user.UserID, + UserID: user.UserID.IntID(), QuotaUsed: user.QuotaUsedToday(), QuotaMax: user.QuotaPerDay(), IsPro: user.IsPro, diff --git a/server/api/handler/message.go b/server/api/handler/message.go index a3fcb05..590d75e 100644 --- a/server/api/handler/message.go +++ b/server/api/handler/message.go @@ -5,6 +5,7 @@ import ( "blackforestbytes.com/simplecloudnotifier/common/ginresp" "blackforestbytes.com/simplecloudnotifier/db" "blackforestbytes.com/simplecloudnotifier/logic" + "blackforestbytes.com/simplecloudnotifier/models" "database/sql" "fmt" "github.com/gin-gonic/gin" @@ -49,22 +50,22 @@ func NewMessageHandler(app *logic.Application) MessageHandler { // @Router /send.php [POST] func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse { type query struct { - UserID *int64 `form:"user_id"` - UserKey *string `form:"user_key"` - Title *string `form:"title"` - Content *string `form:"content"` - Priority *int `form:"priority"` - UserMessageID *string `form:"msg_id"` - SendTimestamp *float64 `form:"timestamp"` + UserID *models.UserID `form:"user_id"` + UserKey *string `form:"user_key"` + Title *string `form:"title"` + Content *string `form:"content"` + Priority *int `form:"priority"` + UserMessageID *string `form:"msg_id"` + SendTimestamp *float64 `form:"timestamp"` } type form struct { - UserID *int64 `form:"user_id"` - UserKey *string `form:"user_key"` - Title *string `form:"title"` - Content *string `form:"content"` - Priority *int `form:"priority"` - UserMessageID *string `form:"msg_id"` - SendTimestamp *float64 `form:"timestamp"` + UserID *models.UserID `form:"user_id"` + UserKey *string `form:"user_key"` + Title *string `form:"title"` + Content *string `form:"content"` + Priority *int `form:"priority"` + UserMessageID *string `form:"msg_id"` + SendTimestamp *float64 `form:"timestamp"` } var f form @@ -77,7 +78,7 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse { data := dataext.ObjectMerge(f, q) - return h.sendMessageInternal(g, ctx, data.UserID, data.UserKey, langext.Ptr(h.app.DefaultChannel), nil, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp) + return h.sendMessageInternal(g, ctx, data.UserID, data.UserKey, nil, nil, data.Title, data.Content, data.Priority, data.UserMessageID, data.SendTimestamp) } @@ -101,37 +102,37 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse { // @Router /send [POST] func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse { type query struct { - UserID *int64 `form:"user_id"` - UserKey *string `form:"user_key"` - Channel *string `form:"channel"` - ChanKey *string `form:"chan_key"` - Title *string `form:"title"` - Content *string `form:"content"` - Priority *int `form:"priority"` - UserMessageID *string `form:"msg_id"` - SendTimestamp *float64 `form:"timestamp"` + UserID *models.UserID `form:"user_id"` + UserKey *string `form:"user_key"` + Channel *string `form:"channel"` + ChanKey *string `form:"chan_key"` + Title *string `form:"title"` + Content *string `form:"content"` + Priority *int `form:"priority"` + UserMessageID *string `form:"msg_id"` + SendTimestamp *float64 `form:"timestamp"` } type body struct { - UserID *int64 `json:"user_id"` - UserKey *string `json:"user_key"` - Channel *string `json:"channel"` - ChanKey *string `json:"chan_key"` - Title *string `json:"title"` - Content *string `json:"content"` - Priority *int `json:"priority"` - UserMessageID *string `json:"msg_id"` - SendTimestamp *float64 `json:"timestamp"` + UserID *models.UserID `json:"user_id"` + UserKey *string `json:"user_key"` + Channel *string `json:"channel"` + ChanKey *string `json:"chan_key"` + Title *string `json:"title"` + Content *string `json:"content"` + Priority *int `json:"priority"` + UserMessageID *string `json:"msg_id"` + SendTimestamp *float64 `json:"timestamp"` } type form struct { - UserID *int64 `form:"user_id"` - UserKey *string `form:"user_key"` - Channel *string `form:"channel"` - ChanKey *string `form:"chan_key"` - Title *string `form:"title"` - Content *string `form:"content"` - Priority *int `form:"priority"` - UserMessageID *string `form:"msg_id"` - SendTimestamp *float64 `form:"timestamp"` + UserID *models.UserID `form:"user_id"` + UserKey *string `form:"user_key"` + Channel *string `form:"channel"` + ChanKey *string `form:"chan_key"` + Title *string `form:"title"` + Content *string `form:"content"` + Priority *int `form:"priority"` + UserMessageID *string `form:"msg_id"` + SendTimestamp *float64 `form:"timestamp"` } var b body @@ -149,18 +150,18 @@ func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse { } -func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContext, UserID *int64, UserKey *string, Channel *string, ChanKey *string, Title *string, Content *string, Priority *int, UserMessageID *string, SendTimestamp *float64) ginresp.HTTPResponse { +func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContext, UserID *models.UserID, UserKey *string, Channel *string, ChanKey *string, Title *string, Content *string, Priority *int, UserMessageID *string, SendTimestamp *float64) ginresp.HTTPResponse { type response struct { - Success bool `json:"success"` - ErrorID apierr.APIError `json:"error"` - ErrorHighlight int `json:"errhighlight"` - Message string `json:"message"` - SuppressSend bool `json:"suppress_send"` - MessageCount int `json:"messagecount"` - Quota int `json:"quota"` - IsPro bool `json:"is_pro"` - QuotaMax int `json:"quota_max"` - SCNMessageID int64 `json:"scn_msg_id"` + Success bool `json:"success"` + ErrorID apierr.APIError `json:"error"` + ErrorHighlight int `json:"errhighlight"` + Message string `json:"message"` + SuppressSend bool `json:"suppress_send"` + MessageCount int `json:"messagecount"` + Quota int `json:"quota"` + IsPro bool `json:"is_pro"` + QuotaMax int `json:"quota_max"` + SCNMessageID models.SCNMessageID `json:"scn_msg_id"` } if Title != nil { @@ -192,11 +193,6 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex return ginresp.SendAPIError(g, 400, apierr.USR_MSG_ID_TOO_LONG, -1, "MessageID too long (64 characters)", nil) } - channelName := h.app.DefaultChannel - if Channel != nil { - channelName = h.app.NormalizeChannelName(*Channel) - } - user, err := h.database.GetUser(ctx, *UserID) if err == sql.ErrNoRows { return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, -1, "User not found", nil) @@ -205,6 +201,11 @@ func (h MessageHandler) sendMessageInternal(g *gin.Context, ctx *logic.AppContex return ginresp.SendAPIError(g, 500, apierr.DATABASE_ERROR, -1, "Failed to query user", err) } + channelName := user.DefaultChannel() + if Channel != nil { + channelName = h.app.NormalizeChannelName(*Channel) + } + if len(*Title) > user.MaxTitleLength() { return ginresp.SendAPIError(g, 400, apierr.TITLE_TOO_LONG, 103, fmt.Sprintf("Title too long (max %d characters)", user.MaxTitleLength()), nil) } diff --git a/server/db/channels.go b/server/db/channels.go index 53a6075..f55936d 100644 --- a/server/db/channels.go +++ b/server/db/channels.go @@ -6,7 +6,7 @@ import ( "time" ) -func (db *Database) GetChannelByName(ctx TxContext, userid int64, chanName string) (*models.Channel, error) { +func (db *Database) GetChannelByName(ctx TxContext, userid models.UserID, chanName string) (*models.Channel, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -28,7 +28,7 @@ func (db *Database) GetChannelByName(ctx TxContext, userid int64, chanName strin return &channel, nil } -func (db *Database) CreateChannel(ctx TxContext, userid int64, name string, subscribeKey string, sendKey string) (models.Channel, error) { +func (db *Database) CreateChannel(ctx TxContext, userid models.UserID, name string, subscribeKey string, sendKey string) (models.Channel, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Channel{}, err @@ -52,7 +52,7 @@ func (db *Database) CreateChannel(ctx TxContext, userid int64, name string, subs } return models.Channel{ - ChannelID: liid, + ChannelID: models.ChannelID(liid), OwnerUserID: userid, Name: name, SubscribeKey: subscribeKey, @@ -63,7 +63,7 @@ func (db *Database) CreateChannel(ctx TxContext, userid int64, name string, subs }, nil } -func (db *Database) ListChannelsByOwner(ctx TxContext, userid int64) ([]models.Channel, error) { +func (db *Database) ListChannelsByOwner(ctx TxContext, userid models.UserID) ([]models.Channel, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -82,7 +82,7 @@ func (db *Database) ListChannelsByOwner(ctx TxContext, userid int64) ([]models.C return data, nil } -func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid int64, confirmed bool) ([]models.Channel, error) { +func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid models.UserID, confirmed bool) ([]models.Channel, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -107,18 +107,18 @@ func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid int64, confir return data, nil } -func (db *Database) ListChannelsByAccess(ctx TxContext, userid int64, confirmed bool) ([]models.Channel, error) { +func (db *Database) ListChannelsByAccess(ctx TxContext, userid models.UserID, confirmed bool) ([]models.Channel, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err } - confCond := "sub.subscriber_user_id = ?" + confCond := "OR sub.subscriber_user_id = ?" if confirmed { - confCond = "(sub.subscriber_user_id = ? AND sub.confirmed = 1)" + confCond = "OR (sub.subscriber_user_id = ? AND sub.confirmed = 1)" } - rows, err := tx.QueryContext(ctx, "SELECT * FROM channels LEFT JOIN subscriptions sub on channels.channel_id = sub.channel_id WHERE owner_user_id = ? OR "+confCond, + rows, err := tx.QueryContext(ctx, "SELECT * FROM channels LEFT JOIN subscriptions sub on channels.channel_id = sub.channel_id WHERE owner_user_id = ? "+confCond, userid) if err != nil { return nil, err @@ -132,7 +132,7 @@ func (db *Database) ListChannelsByAccess(ctx TxContext, userid int64, confirmed return data, nil } -func (db *Database) GetChannel(ctx TxContext, userid int64, channelid int64) (models.Channel, error) { +func (db *Database) GetChannel(ctx TxContext, userid models.UserID, channelid models.ChannelID) (models.Channel, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Channel{}, err @@ -168,7 +168,7 @@ func (db *Database) IncChannelMessageCounter(ctx TxContext, channel models.Chann return nil } -func (db *Database) UpdateChannelSendKey(ctx TxContext, channelid int64, newkey string) error { +func (db *Database) UpdateChannelSendKey(ctx TxContext, channelid models.ChannelID, newkey string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -184,7 +184,7 @@ func (db *Database) UpdateChannelSendKey(ctx TxContext, channelid int64, newkey return nil } -func (db *Database) UpdateChannelSubscribeKey(ctx TxContext, channelid int64, newkey string) error { +func (db *Database) UpdateChannelSubscribeKey(ctx TxContext, channelid models.ChannelID, newkey string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err diff --git a/server/db/clients.go b/server/db/clients.go index 3762d96..c3cd22d 100644 --- a/server/db/clients.go +++ b/server/db/clients.go @@ -6,7 +6,7 @@ import ( "time" ) -func (db *Database) CreateClient(ctx TxContext, userid int64, ctype models.ClientType, fcmToken string, agentModel string, agentVersion string) (models.Client, error) { +func (db *Database) CreateClient(ctx TxContext, userid models.UserID, ctype models.ClientType, fcmToken string, agentModel string, agentVersion string) (models.Client, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Client{}, err @@ -31,7 +31,7 @@ func (db *Database) CreateClient(ctx TxContext, userid int64, ctype models.Clien } return models.Client{ - ClientID: liid, + ClientID: models.ClientID(liid), UserID: userid, Type: ctype, FCMToken: langext.Ptr(fcmToken), @@ -55,7 +55,7 @@ func (db *Database) ClearFCMTokens(ctx TxContext, fcmtoken string) error { return nil } -func (db *Database) ListClients(ctx TxContext, userid int64) ([]models.Client, error) { +func (db *Database) ListClients(ctx TxContext, userid models.UserID) ([]models.Client, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -74,7 +74,7 @@ func (db *Database) ListClients(ctx TxContext, userid int64) ([]models.Client, e return data, nil } -func (db *Database) GetClient(ctx TxContext, userid int64, clientid int64) (models.Client, error) { +func (db *Database) GetClient(ctx TxContext, userid models.UserID, clientid models.ClientID) (models.Client, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Client{}, err @@ -93,7 +93,7 @@ func (db *Database) GetClient(ctx TxContext, userid int64, clientid int64) (mode return client, nil } -func (db *Database) DeleteClient(ctx TxContext, clientid int64) error { +func (db *Database) DeleteClient(ctx TxContext, clientid models.ClientID) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err diff --git a/server/db/deliveries.go b/server/db/deliveries.go index 0f7effb..4c29c23 100644 --- a/server/db/deliveries.go +++ b/server/db/deliveries.go @@ -35,7 +35,7 @@ func (db *Database) CreateRetryDelivery(ctx TxContext, client models.Client, msg } return models.Delivery{ - DeliveryID: liid, + DeliveryID: models.DeliveryID(liid), SCNMessageID: msg.SCNMessageID, ReceiverUserID: client.UserID, ReceiverClientID: client.ClientID, @@ -75,7 +75,7 @@ func (db *Database) CreateSuccessDelivery(ctx TxContext, client models.Client, m } return models.Delivery{ - DeliveryID: liid, + DeliveryID: models.DeliveryID(liid), SCNMessageID: msg.SCNMessageID, ReceiverUserID: client.UserID, ReceiverClientID: client.ClientID, @@ -161,7 +161,7 @@ func (db *Database) SetDeliveryRetry(ctx TxContext, delivery models.Delivery) er return nil } -func (db *Database) CancelPendingDeliveries(ctx TxContext, scnMessageID int64) error { +func (db *Database) CancelPendingDeliveries(ctx TxContext, scnMessageID models.SCNMessageID) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err diff --git a/server/db/messages.go b/server/db/messages.go index 5aee0f8..e32511e 100644 --- a/server/db/messages.go +++ b/server/db/messages.go @@ -30,7 +30,7 @@ func (db *Database) GetMessageByUserMessageID(ctx TxContext, usrMsgId string) (* return &msg, nil } -func (db *Database) GetMessage(ctx TxContext, scnMessageID int64) (models.Message, error) { +func (db *Database) GetMessage(ctx TxContext, scnMessageID models.SCNMessageID) (models.Message, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Message{}, err @@ -49,7 +49,7 @@ func (db *Database) GetMessage(ctx TxContext, scnMessageID int64) (models.Messag return msg, nil } -func (db *Database) CreateMessage(ctx TxContext, senderUserID int64, channel models.Channel, timestampSend *time.Time, title string, content *string, priority int, userMsgId *string) (models.Message, error) { +func (db *Database) CreateMessage(ctx TxContext, senderUserID models.UserID, channel models.Channel, timestampSend *time.Time, title string, content *string, priority int, userMsgId *string) (models.Message, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Message{}, err @@ -78,7 +78,7 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID int64, channel mod } return models.Message{ - SCNMessageID: liid, + SCNMessageID: models.SCNMessageID(liid), SenderUserID: senderUserID, OwnerUserID: channel.OwnerUserID, ChannelName: channel.Name, @@ -92,7 +92,7 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID int64, channel mod }, nil } -func (db *Database) DeleteMessage(ctx TxContext, scnMessageID int64) error { +func (db *Database) DeleteMessage(ctx TxContext, scnMessageID models.SCNMessageID) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -106,7 +106,7 @@ func (db *Database) DeleteMessage(ctx TxContext, scnMessageID int64) error { return nil } -func (db *Database) ListMessages(ctx TxContext, userid int64, pageSize int, inTok cursortoken.CursorToken) ([]models.Message, cursortoken.CursorToken, error) { +func (db *Database) ListMessages(ctx TxContext, userid models.UserID, pageSize int, inTok cursortoken.CursorToken) ([]models.Message, cursortoken.CursorToken, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, cursortoken.CursorToken{}, err @@ -136,12 +136,12 @@ func (db *Database) ListMessages(ctx TxContext, userid int64, pageSize int, inTo if len(data) <= pageSize { return data, cursortoken.End(), nil } else { - outToken := cursortoken.Normal(data[pageSize-1].TimestampReal, data[pageSize-1].SCNMessageID, "DESC") + outToken := cursortoken.Normal(data[pageSize-1].TimestampReal, data[pageSize-1].SCNMessageID.IntID(), "DESC") return data[0:pageSize], outToken, nil } } -func (db *Database) ListChannelMessages(ctx TxContext, channelid int64, pageSize int, inTok cursortoken.CursorToken) ([]models.Message, cursortoken.CursorToken, error) { +func (db *Database) ListChannelMessages(ctx TxContext, channelid models.ChannelID, pageSize int, inTok cursortoken.CursorToken) ([]models.Message, cursortoken.CursorToken, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, cursortoken.CursorToken{}, err @@ -171,7 +171,7 @@ func (db *Database) ListChannelMessages(ctx TxContext, channelid int64, pageSize if len(data) <= pageSize { return data, cursortoken.End(), nil } else { - outToken := cursortoken.Normal(data[pageSize-1].TimestampReal, data[pageSize-1].SCNMessageID, "DESC") + outToken := cursortoken.Normal(data[pageSize-1].TimestampReal, data[pageSize-1].SCNMessageID.IntID(), "DESC") return data[0:pageSize], outToken, nil } } diff --git a/server/db/subscriptions.go b/server/db/subscriptions.go index 4fe4f1c..fb6839f 100644 --- a/server/db/subscriptions.go +++ b/server/db/subscriptions.go @@ -6,7 +6,7 @@ import ( "time" ) -func (db *Database) CreateSubscription(ctx TxContext, subscriberUID int64, channel models.Channel, confirmed bool) (models.Subscription, error) { +func (db *Database) CreateSubscription(ctx TxContext, subscriberUID models.UserID, channel models.Channel, confirmed bool) (models.Subscription, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Subscription{}, err @@ -31,7 +31,7 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID int64, chann } return models.Subscription{ - SubscriptionID: liid, + SubscriptionID: models.SubscriptionID(liid), SubscriberUserID: subscriberUID, ChannelOwnerUserID: channel.OwnerUserID, ChannelID: channel.ChannelID, @@ -41,7 +41,7 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID int64, chann }, nil } -func (db *Database) ListSubscriptionsByChannel(ctx TxContext, channelID int64) ([]models.Subscription, error) { +func (db *Database) ListSubscriptionsByChannel(ctx TxContext, channelID models.ChannelID) ([]models.Subscription, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -60,7 +60,7 @@ func (db *Database) ListSubscriptionsByChannel(ctx TxContext, channelID int64) ( return data, nil } -func (db *Database) ListSubscriptionsByOwner(ctx TxContext, ownerUserID int64) ([]models.Subscription, error) { +func (db *Database) ListSubscriptionsByOwner(ctx TxContext, ownerUserID models.UserID) ([]models.Subscription, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -79,7 +79,7 @@ func (db *Database) ListSubscriptionsByOwner(ctx TxContext, ownerUserID int64) ( return data, nil } -func (db *Database) GetSubscription(ctx TxContext, subid int64) (models.Subscription, error) { +func (db *Database) GetSubscription(ctx TxContext, subid models.SubscriptionID) (models.Subscription, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.Subscription{}, err @@ -98,7 +98,7 @@ func (db *Database) GetSubscription(ctx TxContext, subid int64) (models.Subscrip return sub, nil } -func (db *Database) GetSubscriptionBySubscriber(ctx TxContext, subscriberId int64, channelId int64) (*models.Subscription, error) { +func (db *Database) GetSubscriptionBySubscriber(ctx TxContext, subscriberId models.UserID, channelId models.ChannelID) (*models.Subscription, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return nil, err @@ -120,7 +120,7 @@ func (db *Database) GetSubscriptionBySubscriber(ctx TxContext, subscriberId int6 return &user, nil } -func (db *Database) DeleteSubscription(ctx TxContext, subid int64) error { +func (db *Database) DeleteSubscription(ctx TxContext, subid models.SubscriptionID) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -134,7 +134,7 @@ func (db *Database) DeleteSubscription(ctx TxContext, subid int64) error { return nil } -func (db *Database) UpdateSubscriptionConfirmed(ctx TxContext, subscriptionID int64, confirmed bool) error { +func (db *Database) UpdateSubscriptionConfirmed(ctx TxContext, subscriptionID models.SubscriptionID, confirmed bool) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err diff --git a/server/db/users.go b/server/db/users.go index e5915d8..84f763c 100644 --- a/server/db/users.go +++ b/server/db/users.go @@ -33,7 +33,7 @@ func (db *Database) CreateUser(ctx TxContext, readKey string, sendKey string, ad } return models.User{ - UserID: liid, + UserID: models.UserID(liid), Username: username, ReadKey: readKey, SendKey: sendKey, @@ -85,7 +85,7 @@ func (db *Database) GetUserByKey(ctx TxContext, key string) (*models.User, error return &user, nil } -func (db *Database) GetUser(ctx TxContext, userid int64) (models.User, error) { +func (db *Database) GetUser(ctx TxContext, userid models.UserID) (models.User, error) { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return models.User{}, err @@ -104,7 +104,7 @@ func (db *Database) GetUser(ctx TxContext, userid int64) (models.User, error) { return user, nil } -func (db *Database) UpdateUserUsername(ctx TxContext, userid int64, username *string) error { +func (db *Database) UpdateUserUsername(ctx TxContext, userid models.UserID, username *string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -120,7 +120,7 @@ func (db *Database) UpdateUserUsername(ctx TxContext, userid int64, username *st return nil } -func (db *Database) UpdateUserProToken(ctx TxContext, userid int64, protoken *string) error { +func (db *Database) UpdateUserProToken(ctx TxContext, userid models.UserID, protoken *string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -158,7 +158,7 @@ func (db *Database) IncUserMessageCounter(ctx TxContext, user models.User) error return nil } -func (db *Database) UpdateUserLastRead(ctx TxContext, userid int64) error { +func (db *Database) UpdateUserLastRead(ctx TxContext, userid models.UserID) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -174,7 +174,7 @@ func (db *Database) UpdateUserLastRead(ctx TxContext, userid int64) error { return nil } -func (db *Database) UpdateUserKeys(ctx TxContext, userid int64, sendKey string, readKey string, adminKey string) error { +func (db *Database) UpdateUserKeys(ctx TxContext, userid models.UserID, sendKey string, readKey string, adminKey string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -192,7 +192,7 @@ func (db *Database) UpdateUserKeys(ctx TxContext, userid int64, sendKey string, return nil } -func (db *Database) UpdateUserSendKey(ctx TxContext, userid int64, newkey string) error { +func (db *Database) UpdateUserSendKey(ctx TxContext, userid models.UserID, newkey string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -208,7 +208,7 @@ func (db *Database) UpdateUserSendKey(ctx TxContext, userid int64, newkey string return nil } -func (db *Database) UpdateUserReadKey(ctx TxContext, userid int64, newkey string) error { +func (db *Database) UpdateUserReadKey(ctx TxContext, userid models.UserID, newkey string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err @@ -224,7 +224,7 @@ func (db *Database) UpdateUserReadKey(ctx TxContext, userid int64, newkey string return nil } -func (db *Database) UpdateUserAdminKey(ctx TxContext, userid int64, newkey string) error { +func (db *Database) UpdateUserAdminKey(ctx TxContext, userid models.UserID, newkey string) error { tx, err := ctx.GetOrCreateTransaction(db) if err != nil { return err diff --git a/server/firebase/firebase.go b/server/firebase/firebase.go index bb46d0c..54ea4ad 100644 --- a/server/firebase/firebase.go +++ b/server/firebase/firebase.go @@ -56,9 +56,9 @@ func (fb FBConnector) SendNotification(ctx context.Context, client models.Client jsonBody := gin.H{ "data": gin.H{ - "scn_msg_id": strconv.FormatInt(msg.SCNMessageID, 10), + "scn_msg_id": msg.SCNMessageID.String(), "usr_msg_id": langext.Coalesce(msg.UserMessageID, ""), - "client_id": strconv.FormatInt(client.ClientID, 10), + "client_id": client.ClientID.String(), "timestamp": strconv.FormatInt(msg.Timestamp().Unix(), 10), "priority": strconv.Itoa(msg.Priority), "trimmed": langext.Conditional(msg.NeedsTrim(), "true", "false"), diff --git a/server/jobs/DeliveryRetryJob.go b/server/jobs/DeliveryRetryJob.go index 4f61362..e702fe6 100644 --- a/server/jobs/DeliveryRetryJob.go +++ b/server/jobs/DeliveryRetryJob.go @@ -88,14 +88,14 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D client, err := j.app.Database.GetClient(ctx, delivery.ReceiverUserID, delivery.ReceiverClientID) if err != nil { - log.Err(err).Int64("ReceiverUserID", delivery.ReceiverUserID).Int64("ReceiverClientID", delivery.ReceiverClientID).Msg("Failed to get client") + log.Err(err).Int64("ReceiverUserID", delivery.ReceiverUserID.IntID()).Int64("ReceiverClientID", delivery.ReceiverClientID.IntID()).Msg("Failed to get client") ctx.RollbackTransaction() return } msg, err := j.app.Database.GetMessage(ctx, delivery.SCNMessageID) if err != nil { - log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID).Msg("Failed to get message") + log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Msg("Failed to get message") ctx.RollbackTransaction() return } @@ -104,22 +104,22 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D if err == nil { err = j.app.Database.SetDeliverySuccess(ctx, delivery, *fcmDelivID) if err != nil { - log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID).Int64("DeliveryID", delivery.DeliveryID).Msg("Failed to update delivery") + log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery") ctx.RollbackTransaction() return } } else if delivery.RetryCount+1 > delivery.MaxRetryCount() { err = j.app.Database.SetDeliveryFailed(ctx, delivery) if err != nil { - log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID).Int64("DeliveryID", delivery.DeliveryID).Msg("Failed to update delivery") + log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery") ctx.RollbackTransaction() return } - log.Warn().Int64("SCNMessageID", delivery.SCNMessageID).Int64("DeliveryID", delivery.DeliveryID).Msg("Delivery failed after retries (set to FAILURE)") + log.Warn().Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Delivery failed after retries (set to FAILURE)") } else { err = j.app.Database.SetDeliveryRetry(ctx, delivery) if err != nil { - log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID).Int64("DeliveryID", delivery.DeliveryID).Msg("Failed to update delivery") + log.Err(err).Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Failed to update delivery") ctx.RollbackTransaction() return } diff --git a/server/logic/application.go b/server/logic/application.go index b9a7da5..5f5c746 100644 --- a/server/logic/application.go +++ b/server/logic/application.go @@ -24,18 +24,16 @@ import ( ) type Application struct { - Config scn.Config - Gin *gin.Engine - Database *db.Database - Firebase *firebase.FBConnector - DefaultChannel string - Jobs []Job + Config scn.Config + Gin *gin.Engine + Database *db.Database + Firebase *firebase.FBConnector + Jobs []Job } func NewApp(db *db.Database) *Application { return &Application{ - Database: db, - DefaultChannel: "main", + Database: db, } } @@ -194,7 +192,7 @@ func (app *Application) getPermissions(ctx *AppContext, hdr string) (PermissionS return NewEmptyPermissions(), nil } -func (app *Application) GetOrCreateChannel(ctx *AppContext, userid int64, chanName string) (models.Channel, error) { +func (app *Application) GetOrCreateChannel(ctx *AppContext, userid models.UserID, chanName string) (models.Channel, error) { chanName = app.NormalizeChannelName(chanName) existingChan, err := app.Database.GetChannelByName(ctx, userid, chanName) @@ -245,7 +243,7 @@ func (app *Application) DeliverMessage(ctx context.Context, client models.Client if client.FCMToken != nil { fcmDelivID, err := app.Firebase.SendNotification(ctx, client, msg) if err != nil { - log.Warn().Int64("SCNMessageID", msg.SCNMessageID).Int64("ClientID", client.ClientID).Err(err).Msg("FCM Delivery failed") + log.Warn().Int64("SCNMessageID", msg.SCNMessageID.IntID()).Int64("ClientID", client.ClientID.IntID()).Err(err).Msg("FCM Delivery failed") return nil, err } return langext.Ptr(fcmDelivID), nil diff --git a/server/logic/permissions.go b/server/logic/permissions.go index 399509b..cc549b0 100644 --- a/server/logic/permissions.go +++ b/server/logic/permissions.go @@ -17,7 +17,7 @@ const ( ) type PermissionSet struct { - UserID *int64 + UserID *models.UserID KeyType PermKeyType } @@ -28,7 +28,7 @@ func NewEmptyPermissions() PermissionSet { } } -func (ac *AppContext) CheckPermissionUserRead(userid int64) *ginresp.HTTPResponse { +func (ac *AppContext) CheckPermissionUserRead(userid models.UserID) *ginresp.HTTPResponse { p := ac.permissions if p.UserID != nil && *p.UserID == userid && p.KeyType == PermKeyTypeUserRead { return nil @@ -52,7 +52,7 @@ func (ac *AppContext) CheckPermissionRead() *ginresp.HTTPResponse { return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil)) } -func (ac *AppContext) CheckPermissionUserAdmin(userid int64) *ginresp.HTTPResponse { +func (ac *AppContext) CheckPermissionUserAdmin(userid models.UserID) *ginresp.HTTPResponse { p := ac.permissions if p.UserID != nil && *p.UserID == userid && p.KeyType == PermKeyTypeUserAdmin { return nil @@ -94,7 +94,7 @@ func (ac *AppContext) CheckPermissionMessageReadDirect(msg models.Message) bool return false } -func (ac *AppContext) GetPermissionUserID() *int64 { +func (ac *AppContext) GetPermissionUserID() *models.UserID { if ac.permissions.UserID == nil { return nil } else { diff --git a/server/models/channel.go b/server/models/channel.go index b19f5e2..3fb0b77 100644 --- a/server/models/channel.go +++ b/server/models/channel.go @@ -8,8 +8,8 @@ import ( ) type Channel struct { - ChannelID int64 - OwnerUserID int64 + ChannelID ChannelID + OwnerUserID UserID Name string SubscribeKey string SendKey string @@ -32,26 +32,26 @@ func (c Channel) JSON(includeKey bool) ChannelJSON { } type ChannelJSON struct { - ChannelID int64 `json:"channel_id"` - OwnerUserID int64 `json:"owner_user_id"` - Name string `json:"name"` - SubscribeKey *string `json:"subscribe_key"` // can be nil, depending on endpoint - SendKey *string `json:"send_key"` // can be nil, depending on endpoint - TimestampCreated string `json:"timestamp_created"` - TimestampLastSent *string `json:"timestamp_last_sent"` - MessagesSent int `json:"messages_sent"` + ChannelID ChannelID `json:"channel_id"` + OwnerUserID UserID `json:"owner_user_id"` + Name string `json:"name"` + SubscribeKey *string `json:"subscribe_key"` // can be nil, depending on endpoint + SendKey *string `json:"send_key"` // can be nil, depending on endpoint + TimestampCreated string `json:"timestamp_created"` + TimestampLastSent *string `json:"timestamp_last_sent"` + MessagesSent int `json:"messages_sent"` } type ChannelDB struct { - ChannelID int64 `db:"channel_id"` - OwnerUserID int64 `db:"owner_user_id"` - Name string `db:"name"` - SubscribeKey string `db:"subscribe_key"` - SendKey string `db:"send_key"` - TimestampCreated int64 `db:"timestamp_created"` - TimestampLastRead *int64 `db:"timestamp_last_read"` - TimestampLastSent *int64 `db:"timestamp_last_sent"` - MessagesSent int `db:"messages_sent"` + ChannelID ChannelID `db:"channel_id"` + OwnerUserID UserID `db:"owner_user_id"` + Name string `db:"name"` + SubscribeKey string `db:"subscribe_key"` + SendKey string `db:"send_key"` + TimestampCreated int64 `db:"timestamp_created"` + TimestampLastRead *int64 `db:"timestamp_last_read"` + TimestampLastSent *int64 `db:"timestamp_last_sent"` + MessagesSent int `db:"messages_sent"` } func (c ChannelDB) Model() Channel { diff --git a/server/models/client.go b/server/models/client.go index 7566fe3..ccc32fa 100644 --- a/server/models/client.go +++ b/server/models/client.go @@ -15,8 +15,8 @@ const ( ) type Client struct { - ClientID int64 - UserID int64 + ClientID ClientID + UserID UserID Type ClientType FCMToken *string TimestampCreated time.Time @@ -37,8 +37,8 @@ func (c Client) JSON() ClientJSON { } type ClientJSON struct { - ClientID int64 `json:"client_id"` - UserID int64 `json:"user_id"` + ClientID ClientID `json:"client_id"` + UserID UserID `json:"user_id"` Type ClientType `json:"type"` FCMToken *string `json:"fcm_token"` TimestampCreated string `json:"timestamp_created"` @@ -47,8 +47,8 @@ type ClientJSON struct { } type ClientDB struct { - ClientID int64 `db:"client_id"` - UserID int64 `db:"user_id"` + ClientID ClientID `db:"client_id"` + UserID UserID `db:"user_id"` Type ClientType `db:"type"` FCMToken *string `db:"fcm_token"` TimestampCreated int64 `db:"timestamp_created"` diff --git a/server/models/delivery.go b/server/models/delivery.go index c16cb8f..788c3bd 100644 --- a/server/models/delivery.go +++ b/server/models/delivery.go @@ -16,10 +16,10 @@ const ( ) type Delivery struct { - DeliveryID int64 - SCNMessageID int64 - ReceiverUserID int64 - ReceiverClientID int64 + DeliveryID DeliveryID + SCNMessageID SCNMessageID + ReceiverUserID UserID + ReceiverClientID ClientID TimestampCreated time.Time TimestampFinalized *time.Time Status DeliveryStatus @@ -48,10 +48,10 @@ func (d Delivery) MaxRetryCount() int { } type DeliveryJSON struct { - DeliveryID int64 `json:"delivery_id"` - SCNMessageID int64 `json:"scn_message_id"` - ReceiverUserID int64 `json:"receiver_user_id"` - ReceiverClientID int64 `json:"receiver_client_id"` + DeliveryID DeliveryID `json:"delivery_id"` + SCNMessageID SCNMessageID `json:"scn_message_id"` + ReceiverUserID UserID `json:"receiver_user_id"` + ReceiverClientID ClientID `json:"receiver_client_id"` TimestampCreated string `json:"timestamp_created"` TimestampFinalized *string `json:"tiestamp_finalized"` Status DeliveryStatus `json:"status"` @@ -61,10 +61,10 @@ type DeliveryJSON struct { } type DeliveryDB struct { - DeliveryID int64 `db:"delivery_id"` - SCNMessageID int64 `db:"scn_message_id"` - ReceiverUserID int64 `db:"receiver_user_id"` - ReceiverClientID int64 `db:"receiver_client_id"` + DeliveryID DeliveryID `db:"delivery_id"` + SCNMessageID SCNMessageID `db:"scn_message_id"` + ReceiverUserID UserID `db:"receiver_user_id"` + ReceiverClientID ClientID `db:"receiver_client_id"` TimestampCreated int64 `db:"timestamp_created"` TimestampFinalized *int64 `db:"tiestamp_finalized"` Status DeliveryStatus `db:"status"` diff --git a/server/models/ids.go b/server/models/ids.go new file mode 100644 index 0000000..2fa4697 --- /dev/null +++ b/server/models/ids.go @@ -0,0 +1,68 @@ +package models + +import "strconv" + +type EntityID interface { + IntID() int64 + String() string +} + +type UserID int64 + +func (id UserID) IntID() int64 { + return int64(id) +} + +func (id UserID) String() string { + return strconv.FormatInt(int64(id), 10) +} + +type ChannelID int64 + +func (id ChannelID) IntID() int64 { + return int64(id) +} + +func (id ChannelID) String() string { + return strconv.FormatInt(int64(id), 10) +} + +type DeliveryID int64 + +func (id DeliveryID) IntID() int64 { + return int64(id) +} + +func (id DeliveryID) String() string { + return strconv.FormatInt(int64(id), 10) +} + +type SCNMessageID int64 + +func (id SCNMessageID) IntID() int64 { + return int64(id) +} + +func (id SCNMessageID) String() string { + return strconv.FormatInt(int64(id), 10) +} + +type SubscriptionID int64 + +func (id SubscriptionID) IntID() int64 { + return int64(id) +} + +func (id SubscriptionID) String() string { + return strconv.FormatInt(int64(id), 10) +} + +type ClientID int64 + +func (id ClientID) IntID() int64 { + return int64(id) +} + +func (id ClientID) String() string { + return strconv.FormatInt(int64(id), 10) +} diff --git a/server/models/message.go b/server/models/message.go index 263a0fa..6f4a6ad 100644 --- a/server/models/message.go +++ b/server/models/message.go @@ -13,11 +13,11 @@ const ( ) type Message struct { - SCNMessageID int64 - SenderUserID int64 - OwnerUserID int64 + SCNMessageID SCNMessageID + SenderUserID UserID + OwnerUserID UserID ChannelName string - ChannelID int64 + ChannelID ChannelID TimestampReal time.Time TimestampClient *time.Time Title string @@ -87,31 +87,31 @@ func (m Message) ShortContent() string { } type MessageJSON struct { - SCNMessageID int64 `json:"scn_message_id"` - SenderUserID int64 `json:"sender_user_id"` - OwnerUserID int64 `json:"owner_user_id"` - ChannelName string `json:"channel_name"` - ChannelID int64 `json:"channel_id"` - Timestamp string `json:"timestamp"` - Title string `json:"title"` - Content *string `json:"body"` - Priority int `json:"priority"` - UserMessageID *string `json:"usr_message_id"` - Trimmed bool `json:"trimmed"` + SCNMessageID SCNMessageID `json:"scn_message_id"` + SenderUserID UserID `json:"sender_user_id"` + OwnerUserID UserID `json:"owner_user_id"` + ChannelName string `json:"channel_name"` + ChannelID ChannelID `json:"channel_id"` + Timestamp string `json:"timestamp"` + Title string `json:"title"` + Content *string `json:"body"` + Priority int `json:"priority"` + UserMessageID *string `json:"usr_message_id"` + Trimmed bool `json:"trimmed"` } type MessageDB struct { - SCNMessageID int64 `db:"scn_message_id"` - SenderUserID int64 `db:"sender_user_id"` - OwnerUserID int64 `db:"owner_user_id"` - ChannelName string `db:"channel_name"` - ChannelID int64 `db:"channel_id"` - TimestampReal int64 `db:"timestamp_real"` - TimestampClient *int64 `db:"timestamp_client"` - Title string `db:"title"` - Content *string `db:"content"` - Priority int `db:"priority"` - UserMessageID *string `db:"usr_message_id"` + SCNMessageID SCNMessageID `db:"scn_message_id"` + SenderUserID UserID `db:"sender_user_id"` + OwnerUserID UserID `db:"owner_user_id"` + ChannelName string `db:"channel_name"` + ChannelID ChannelID `db:"channel_id"` + TimestampReal int64 `db:"timestamp_real"` + TimestampClient *int64 `db:"timestamp_client"` + Title string `db:"title"` + Content *string `db:"content"` + Priority int `db:"priority"` + UserMessageID *string `db:"usr_message_id"` } func (m MessageDB) Model() Message { diff --git a/server/models/subscription.go b/server/models/subscription.go index 2730724..04f6229 100644 --- a/server/models/subscription.go +++ b/server/models/subscription.go @@ -8,10 +8,10 @@ import ( ) type Subscription struct { - SubscriptionID int64 - SubscriberUserID int64 - ChannelOwnerUserID int64 - ChannelID int64 + SubscriptionID SubscriptionID + SubscriberUserID UserID + ChannelOwnerUserID UserID + ChannelID ChannelID ChannelName string TimestampCreated time.Time Confirmed bool @@ -30,23 +30,23 @@ func (s Subscription) JSON() SubscriptionJSON { } type SubscriptionJSON struct { - SubscriptionID int64 `json:"subscription_id"` - SubscriberUserID int64 `json:"subscriber_user_id"` - ChannelOwnerUserID int64 `json:"channel_owner_user_id"` - ChannelID int64 `json:"channel_id"` - ChannelName string `json:"channel_name"` - TimestampCreated string `json:"timestamp_created"` - Confirmed bool `json:"confirmed"` + SubscriptionID SubscriptionID `json:"subscription_id"` + SubscriberUserID UserID `json:"subscriber_user_id"` + ChannelOwnerUserID UserID `json:"channel_owner_user_id"` + ChannelID ChannelID `json:"channel_id"` + ChannelName string `json:"channel_name"` + TimestampCreated string `json:"timestamp_created"` + Confirmed bool `json:"confirmed"` } type SubscriptionDB struct { - SubscriptionID int64 `db:"subscription_id"` - SubscriberUserID int64 `db:"subscriber_user_id"` - ChannelOwnerUserID int64 `db:"channel_owner_user_id"` - ChannelID int64 `db:"channel_id"` - ChannelName string `db:"channel_name"` - TimestampCreated int64 `db:"timestamp_created"` - Confirmed int `db:"confirmed"` + SubscriptionID SubscriptionID `db:"subscription_id"` + SubscriberUserID UserID `db:"subscriber_user_id"` + ChannelOwnerUserID UserID `db:"channel_owner_user_id"` + ChannelID ChannelID `db:"channel_id"` + ChannelName string `db:"channel_name"` + TimestampCreated int64 `db:"timestamp_created"` + Confirmed int `db:"confirmed"` } func (s SubscriptionDB) Model() Subscription { diff --git a/server/models/user.go b/server/models/user.go index f80699b..6507f86 100644 --- a/server/models/user.go +++ b/server/models/user.go @@ -9,7 +9,7 @@ import ( ) type User struct { - UserID int64 + UserID UserID Username *string SendKey string ReadKey string @@ -38,6 +38,7 @@ func (u User) JSON() UserJSON { QuotaUsed: u.QuotaUsed, QuotaUsedDay: u.QuotaUsedDay, IsPro: u.IsPro, + DefaultChannel: u.DefaultChannel(), } } @@ -74,8 +75,12 @@ func (u User) QuotaRemainingToday() int { return u.QuotaPerDay() - u.QuotaUsedToday() } +func (u User) DefaultChannel() string { + return "main" +} + type UserJSON struct { - UserID int64 `json:"user_id"` + UserID UserID `json:"user_id"` Username *string `json:"username"` ReadKey string `json:"read_key"` SendKey string `json:"send_key"` @@ -87,10 +92,11 @@ type UserJSON struct { QuotaUsed int `json:"quota_used"` QuotaUsedDay *string `json:"quota_used_day"` IsPro bool `json:"is_pro"` + DefaultChannel string `json:"default_channel"` } type UserDB struct { - UserID int64 `db:"user_id"` + UserID UserID `db:"user_id"` Username *string `db:"username"` SendKey string `db:"send_key"` ReadKey string `db:"read_key"` diff --git a/server/swagger/swagger.json b/server/swagger/swagger.json index a4e0a12..97274d1 100644 --- a/server/swagger/swagger.json +++ b/server/swagger/swagger.json @@ -2638,6 +2638,9 @@ "admin_key": { "type": "string" }, + "default_channel": { + "type": "string" + }, "is_pro": { "type": "boolean" }, diff --git a/server/swagger/swagger.yaml b/server/swagger/swagger.yaml index c90c6dd..4051d90 100644 --- a/server/swagger/swagger.yaml +++ b/server/swagger/swagger.yaml @@ -408,6 +408,8 @@ definitions: properties: admin_key: type: string + default_channel: + type: string is_pro: type: boolean messages_sent: