Use ID types

This commit is contained in:
Mike Schwörer 2022-11-20 22:18:24 +01:00
parent ca58aa782d
commit 0cc6e27267
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
23 changed files with 334 additions and 256 deletions

View File

@ -4,8 +4,8 @@
- ack/read deliveries && return ack-count - ack/read deliveries && return ack-count
- go ID types
- verify pro_token
- full-text-search: https://www.sqlite.org/fts5.html#contentless_tables - full-text-search: https://www.sqlite.org/fts5.html#contentless_tables
- deploy - deploy

View File

@ -129,7 +129,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid} [GET] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
var u uri var u uri
@ -177,7 +177,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid} [PATCH] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
type body struct { type body struct {
Username *string `json:"username"` Username *string `json:"username"`
@ -283,7 +283,7 @@ func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/clients [GET] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
type response struct { type response struct {
Clients []models.ClientJSON `json:"clients"` 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] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
ClientID int64 `uri:"cid"` ClientID models.ClientID `uri:"cid"`
} }
var u uri var u uri
@ -371,7 +371,7 @@ func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/clients [POST] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
type body struct { type body struct {
FCMToken string `json:"fcm_token" binding:"required"` 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] // @Router /api-v2/users/{uid}/clients [POST]
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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
ClientID int64 `uri:"cid"` ClientID models.ClientID `uri:"cid"`
} }
var u uri var u uri
@ -480,7 +480,7 @@ func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/channels [GET] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
type query struct { type query struct {
Selector *string `form:"selector"` 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] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
ChannelID int64 `uri:"cid"` ChannelID models.ChannelID `uri:"cid"`
} }
var u uri var u uri
@ -605,8 +605,8 @@ func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/channels/{cid} [PATCH] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
ChannelID int64 `uri:"cid"` ChannelID models.ChannelID `uri:"cid"`
} }
type body struct { type body struct {
RefreshSubscribeKey *bool `json:"subscribe_key"` 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] // @Router /api-v2/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 int64 `uri:"uid"` ChannelUserID models.UserID `uri:"uid"`
ChannelID int64 `uri:"cid"` ChannelID models.ChannelID `uri:"cid"`
} }
type query struct { type query struct {
PageSize *int `form:"page_size"` 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] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
type response struct { type response struct {
Subscriptions []models.SubscriptionJSON `json:"subscriptions"` 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] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
ChannelID int64 `uri:"cid"` ChannelID models.ChannelID `uri:"cid"`
} }
type response struct { type response struct {
Subscriptions []models.SubscriptionJSON `json:"subscriptions"` 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] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
SubscriptionID int64 `uri:"sid"` SubscriptionID models.SubscriptionID `uri:"sid"`
} }
var u uri var u uri
@ -913,8 +913,8 @@ func (h APIHandler) GetSubscription(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/subscriptions/{sid} [DELETE] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
SubscriptionID int64 `uri:"sid"` SubscriptionID models.SubscriptionID `uri:"sid"`
} }
var u uri var u uri
@ -966,10 +966,10 @@ func (h APIHandler) CancelSubscription(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/subscriptions [POST] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
} }
type body struct { type body struct {
ChannelOwnerUserID int64 `form:"channel_owner_user_id" binding:"required"` ChannelOwnerUserID models.UserID `form:"channel_owner_user_id" binding:"required"`
Channel string `form:"channel_name" binding:"required"` Channel string `form:"channel_name" binding:"required"`
} }
type query struct { type query struct {
@ -1026,8 +1026,8 @@ func (h APIHandler) CreateSubscription(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/users/{uid}/subscriptions/{sid} [PATCH] // @Router /api-v2/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 int64 `uri:"uid"` UserID models.UserID `uri:"uid"`
SubscriptionID int64 `uri:"sid"` SubscriptionID models.SubscriptionID `uri:"sid"`
} }
type body struct { type body struct {
Confirmed *bool `form:"confirmed"` Confirmed *bool `form:"confirmed"`
@ -1166,7 +1166,7 @@ func (h APIHandler) ListMessages(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/messages/{mid} [PATCH] // @Router /api-v2/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 int64 `uri:"mid"` MessageID models.SCNMessageID `uri:"mid"`
} }
var u uri var u uri
@ -1235,7 +1235,7 @@ func (h APIHandler) GetMessage(g *gin.Context) ginresp.HTTPResponse {
// @Router /api-v2/messages/{mid} [PATCH] // @Router /api-v2/messages/{mid} [PATCH]
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 int64 `uri:"mid"` MessageID models.SCNMessageID `uri:"mid"`
} }
var u uri 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) 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) user, err := h.database.GetUser(ctx, userID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, -1, "User not found", nil) 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) 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() { 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) return ginresp.SendAPIError(g, 400, apierr.TITLE_TOO_LONG, 103, fmt.Sprintf("Title too long (max %d characters)", user.MaxTitleLength()), nil)
} }

View File

@ -122,7 +122,7 @@ func (h CompatHandler) Register(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: "New user registered", Message: "New user registered",
UserID: user.UserID, UserID: user.UserID.IntID(),
UserKey: user.AdminKey, UserKey: user.AdminKey,
QuotaUsed: user.QuotaUsedToday(), QuotaUsed: user.QuotaUsedToday(),
QuotaMax: user.QuotaPerDay(), QuotaMax: user.QuotaPerDay(),
@ -180,7 +180,7 @@ 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, *data.UserID) user, err := h.database.GetUser(ctx, models.UserID(*data.UserID))
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(201, "User not found") 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{ return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
Success: true, Success: true,
Message: "ok", Message: "ok",
UserID: user.UserID, UserID: user.UserID.IntID(),
UserKey: user.AdminKey, UserKey: user.AdminKey,
QuotaUsed: user.QuotaUsedToday(), QuotaUsed: user.QuotaUsedToday(),
QuotaMax: user.QuotaPerDay(), 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]]") 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 { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(201, "User not found") 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]]") 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 { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(201, "User not found") 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]]") 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 { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(201, "User not found") 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{ return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
Success: true, Success: true,
Message: "user updated", Message: "user updated",
UserID: user.UserID, UserID: user.UserID.IntID(),
UserKey: user.AdminKey, UserKey: user.AdminKey,
QuotaUsed: user.QuotaUsedToday(), QuotaUsed: user.QuotaUsedToday(),
QuotaMax: user.QuotaPerDay(), 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]]") 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 { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(201, "User not found") 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") 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 { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(301, "Message not found") return ginresp.CompatAPIError(301, "Message not found")
} }
@ -539,7 +539,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, 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]]") 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 { if err == sql.ErrNoRows {
return ginresp.CompatAPIError(201, "User not found") 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{ return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{
Success: true, Success: true,
Message: "user updated", Message: "user updated",
UserID: user.UserID, UserID: user.UserID.IntID(),
QuotaUsed: user.QuotaUsedToday(), QuotaUsed: user.QuotaUsedToday(),
QuotaMax: user.QuotaPerDay(), QuotaMax: user.QuotaPerDay(),
IsPro: user.IsPro, IsPro: user.IsPro,

View File

@ -5,6 +5,7 @@ import (
"blackforestbytes.com/simplecloudnotifier/common/ginresp" "blackforestbytes.com/simplecloudnotifier/common/ginresp"
"blackforestbytes.com/simplecloudnotifier/db" "blackforestbytes.com/simplecloudnotifier/db"
"blackforestbytes.com/simplecloudnotifier/logic" "blackforestbytes.com/simplecloudnotifier/logic"
"blackforestbytes.com/simplecloudnotifier/models"
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -49,7 +50,7 @@ func NewMessageHandler(app *logic.Application) MessageHandler {
// @Router /send.php [POST] // @Router /send.php [POST]
func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse { func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
type query struct { type query struct {
UserID *int64 `form:"user_id"` UserID *models.UserID `form:"user_id"`
UserKey *string `form:"user_key"` UserKey *string `form:"user_key"`
Title *string `form:"title"` Title *string `form:"title"`
Content *string `form:"content"` Content *string `form:"content"`
@ -58,7 +59,7 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
SendTimestamp *float64 `form:"timestamp"` SendTimestamp *float64 `form:"timestamp"`
} }
type form struct { type form struct {
UserID *int64 `form:"user_id"` UserID *models.UserID `form:"user_id"`
UserKey *string `form:"user_key"` UserKey *string `form:"user_key"`
Title *string `form:"title"` Title *string `form:"title"`
Content *string `form:"content"` Content *string `form:"content"`
@ -77,7 +78,7 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
data := dataext.ObjectMerge(f, q) 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,7 +102,7 @@ func (h MessageHandler) SendMessageCompat(g *gin.Context) ginresp.HTTPResponse {
// @Router /send [POST] // @Router /send [POST]
func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse { func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse {
type query struct { type query struct {
UserID *int64 `form:"user_id"` UserID *models.UserID `form:"user_id"`
UserKey *string `form:"user_key"` UserKey *string `form:"user_key"`
Channel *string `form:"channel"` Channel *string `form:"channel"`
ChanKey *string `form:"chan_key"` ChanKey *string `form:"chan_key"`
@ -112,7 +113,7 @@ func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse {
SendTimestamp *float64 `form:"timestamp"` SendTimestamp *float64 `form:"timestamp"`
} }
type body struct { type body struct {
UserID *int64 `json:"user_id"` UserID *models.UserID `json:"user_id"`
UserKey *string `json:"user_key"` UserKey *string `json:"user_key"`
Channel *string `json:"channel"` Channel *string `json:"channel"`
ChanKey *string `json:"chan_key"` ChanKey *string `json:"chan_key"`
@ -123,7 +124,7 @@ func (h MessageHandler) SendMessage(g *gin.Context) ginresp.HTTPResponse {
SendTimestamp *float64 `json:"timestamp"` SendTimestamp *float64 `json:"timestamp"`
} }
type form struct { type form struct {
UserID *int64 `form:"user_id"` UserID *models.UserID `form:"user_id"`
UserKey *string `form:"user_key"` UserKey *string `form:"user_key"`
Channel *string `form:"channel"` Channel *string `form:"channel"`
ChanKey *string `form:"chan_key"` ChanKey *string `form:"chan_key"`
@ -149,7 +150,7 @@ 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 { type response struct {
Success bool `json:"success"` Success bool `json:"success"`
ErrorID apierr.APIError `json:"error"` ErrorID apierr.APIError `json:"error"`
@ -160,7 +161,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 int64 `json:"scn_msg_id"` SCNMessageID models.SCNMessageID `json:"scn_msg_id"`
} }
if Title != nil { 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) 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) user, err := h.database.GetUser(ctx, *UserID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return ginresp.SendAPIError(g, 400, apierr.USER_NOT_FOUND, -1, "User not found", nil) 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) 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() { 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) return ginresp.SendAPIError(g, 400, apierr.TITLE_TOO_LONG, 103, fmt.Sprintf("Title too long (max %d characters)", user.MaxTitleLength()), nil)
} }

View File

@ -6,7 +6,7 @@ import (
"time" "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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -28,7 +28,7 @@ func (db *Database) GetChannelByName(ctx TxContext, userid int64, chanName strin
return &channel, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Channel{}, err return models.Channel{}, err
@ -52,7 +52,7 @@ func (db *Database) CreateChannel(ctx TxContext, userid int64, name string, subs
} }
return models.Channel{ return models.Channel{
ChannelID: liid, ChannelID: models.ChannelID(liid),
OwnerUserID: userid, OwnerUserID: userid,
Name: name, Name: name,
SubscribeKey: subscribeKey, SubscribeKey: subscribeKey,
@ -63,7 +63,7 @@ func (db *Database) CreateChannel(ctx TxContext, userid int64, name string, subs
}, nil }, 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -82,7 +82,7 @@ func (db *Database) ListChannelsByOwner(ctx TxContext, userid int64) ([]models.C
return data, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -107,18 +107,18 @@ func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid int64, confir
return data, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
} }
confCond := "sub.subscriber_user_id = ?" confCond := "OR sub.subscriber_user_id = ?"
if confirmed { 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) userid)
if err != nil { if err != nil {
return nil, err return nil, err
@ -132,7 +132,7 @@ func (db *Database) ListChannelsByAccess(ctx TxContext, userid int64, confirmed
return data, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Channel{}, err return models.Channel{}, err
@ -168,7 +168,7 @@ func (db *Database) IncChannelMessageCounter(ctx TxContext, channel models.Chann
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -184,7 +184,7 @@ func (db *Database) UpdateChannelSendKey(ctx TxContext, channelid int64, newkey
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err

View File

@ -6,7 +6,7 @@ import (
"time" "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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Client{}, err return models.Client{}, err
@ -31,7 +31,7 @@ func (db *Database) CreateClient(ctx TxContext, userid int64, ctype models.Clien
} }
return models.Client{ return models.Client{
ClientID: liid, ClientID: models.ClientID(liid),
UserID: userid, UserID: userid,
Type: ctype, Type: ctype,
FCMToken: langext.Ptr(fcmToken), FCMToken: langext.Ptr(fcmToken),
@ -55,7 +55,7 @@ func (db *Database) ClearFCMTokens(ctx TxContext, fcmtoken string) error {
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -74,7 +74,7 @@ func (db *Database) ListClients(ctx TxContext, userid int64) ([]models.Client, e
return data, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Client{}, err return models.Client{}, err
@ -93,7 +93,7 @@ func (db *Database) GetClient(ctx TxContext, userid int64, clientid int64) (mode
return client, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err

View File

@ -35,7 +35,7 @@ func (db *Database) CreateRetryDelivery(ctx TxContext, client models.Client, msg
} }
return models.Delivery{ return models.Delivery{
DeliveryID: liid, DeliveryID: models.DeliveryID(liid),
SCNMessageID: msg.SCNMessageID, SCNMessageID: msg.SCNMessageID,
ReceiverUserID: client.UserID, ReceiverUserID: client.UserID,
ReceiverClientID: client.ClientID, ReceiverClientID: client.ClientID,
@ -75,7 +75,7 @@ func (db *Database) CreateSuccessDelivery(ctx TxContext, client models.Client, m
} }
return models.Delivery{ return models.Delivery{
DeliveryID: liid, DeliveryID: models.DeliveryID(liid),
SCNMessageID: msg.SCNMessageID, SCNMessageID: msg.SCNMessageID,
ReceiverUserID: client.UserID, ReceiverUserID: client.UserID,
ReceiverClientID: client.ClientID, ReceiverClientID: client.ClientID,
@ -161,7 +161,7 @@ func (db *Database) SetDeliveryRetry(ctx TxContext, delivery models.Delivery) er
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err

View File

@ -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 int64) (models.Message, error) { func (db *Database) GetMessage(ctx TxContext, scnMessageID models.SCNMessageID) (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
@ -49,7 +49,7 @@ func (db *Database) GetMessage(ctx TxContext, scnMessageID int64) (models.Messag
return msg, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Message{}, err return models.Message{}, err
@ -78,7 +78,7 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID int64, channel mod
} }
return models.Message{ return models.Message{
SCNMessageID: liid, SCNMessageID: models.SCNMessageID(liid),
SenderUserID: senderUserID, SenderUserID: senderUserID,
OwnerUserID: channel.OwnerUserID, OwnerUserID: channel.OwnerUserID,
ChannelName: channel.Name, ChannelName: channel.Name,
@ -92,7 +92,7 @@ func (db *Database) CreateMessage(ctx TxContext, senderUserID int64, channel mod
}, nil }, 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -106,7 +106,7 @@ func (db *Database) DeleteMessage(ctx TxContext, scnMessageID int64) error {
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, cursortoken.CursorToken{}, err return nil, cursortoken.CursorToken{}, err
@ -136,12 +136,12 @@ func (db *Database) ListMessages(ctx TxContext, userid int64, pageSize int, inTo
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].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 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, cursortoken.CursorToken{}, err return nil, cursortoken.CursorToken{}, err
@ -171,7 +171,7 @@ func (db *Database) ListChannelMessages(ctx TxContext, channelid int64, pageSize
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].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 return data[0:pageSize], outToken, nil
} }
} }

View File

@ -6,7 +6,7 @@ import (
"time" "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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Subscription{}, err return models.Subscription{}, err
@ -31,7 +31,7 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID int64, chann
} }
return models.Subscription{ return models.Subscription{
SubscriptionID: liid, SubscriptionID: models.SubscriptionID(liid),
SubscriberUserID: subscriberUID, SubscriberUserID: subscriberUID,
ChannelOwnerUserID: channel.OwnerUserID, ChannelOwnerUserID: channel.OwnerUserID,
ChannelID: channel.ChannelID, ChannelID: channel.ChannelID,
@ -41,7 +41,7 @@ func (db *Database) CreateSubscription(ctx TxContext, subscriberUID int64, chann
}, nil }, 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -60,7 +60,7 @@ func (db *Database) ListSubscriptionsByChannel(ctx TxContext, channelID int64) (
return data, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -79,7 +79,7 @@ func (db *Database) ListSubscriptionsByOwner(ctx TxContext, ownerUserID int64) (
return data, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.Subscription{}, err return models.Subscription{}, err
@ -98,7 +98,7 @@ func (db *Database) GetSubscription(ctx TxContext, subid int64) (models.Subscrip
return sub, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return nil, err return nil, err
@ -120,7 +120,7 @@ func (db *Database) GetSubscriptionBySubscriber(ctx TxContext, subscriberId int6
return &user, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -134,7 +134,7 @@ func (db *Database) DeleteSubscription(ctx TxContext, subid int64) error {
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err

View File

@ -33,7 +33,7 @@ func (db *Database) CreateUser(ctx TxContext, readKey string, sendKey string, ad
} }
return models.User{ return models.User{
UserID: liid, UserID: models.UserID(liid),
Username: username, Username: username,
ReadKey: readKey, ReadKey: readKey,
SendKey: sendKey, SendKey: sendKey,
@ -85,7 +85,7 @@ func (db *Database) GetUserByKey(ctx TxContext, key string) (*models.User, error
return &user, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return models.User{}, err return models.User{}, err
@ -104,7 +104,7 @@ func (db *Database) GetUser(ctx TxContext, userid int64) (models.User, error) {
return user, nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -120,7 +120,7 @@ func (db *Database) UpdateUserUsername(ctx TxContext, userid int64, username *st
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -158,7 +158,7 @@ func (db *Database) IncUserMessageCounter(ctx TxContext, user models.User) error
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -174,7 +174,7 @@ func (db *Database) UpdateUserLastRead(ctx TxContext, userid int64) error {
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -192,7 +192,7 @@ func (db *Database) UpdateUserKeys(ctx TxContext, userid int64, sendKey string,
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -208,7 +208,7 @@ func (db *Database) UpdateUserSendKey(ctx TxContext, userid int64, newkey string
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err
@ -224,7 +224,7 @@ func (db *Database) UpdateUserReadKey(ctx TxContext, userid int64, newkey string
return nil 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) tx, err := ctx.GetOrCreateTransaction(db)
if err != nil { if err != nil {
return err return err

View File

@ -56,9 +56,9 @@ func (fb FBConnector) SendNotification(ctx context.Context, client models.Client
jsonBody := gin.H{ jsonBody := gin.H{
"data": 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, ""), "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), "timestamp": strconv.FormatInt(msg.Timestamp().Unix(), 10),
"priority": strconv.Itoa(msg.Priority), "priority": strconv.Itoa(msg.Priority),
"trimmed": langext.Conditional(msg.NeedsTrim(), "true", "false"), "trimmed": langext.Conditional(msg.NeedsTrim(), "true", "false"),

View File

@ -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) client, err := j.app.Database.GetClient(ctx, delivery.ReceiverUserID, delivery.ReceiverClientID)
if err != nil { 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() ctx.RollbackTransaction()
return return
} }
msg, err := j.app.Database.GetMessage(ctx, delivery.SCNMessageID) msg, err := j.app.Database.GetMessage(ctx, delivery.SCNMessageID)
if err != nil { 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() ctx.RollbackTransaction()
return return
} }
@ -104,22 +104,22 @@ func (j *DeliveryRetryJob) redeliver(ctx *logic.SimpleContext, delivery models.D
if err == nil { if err == nil {
err = j.app.Database.SetDeliverySuccess(ctx, delivery, *fcmDelivID) err = j.app.Database.SetDeliverySuccess(ctx, delivery, *fcmDelivID)
if err != nil { 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() ctx.RollbackTransaction()
return return
} }
} else if delivery.RetryCount+1 > delivery.MaxRetryCount() { } else if delivery.RetryCount+1 > delivery.MaxRetryCount() {
err = j.app.Database.SetDeliveryFailed(ctx, delivery) err = j.app.Database.SetDeliveryFailed(ctx, delivery)
if err != nil { 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() ctx.RollbackTransaction()
return return
} }
log.Warn().Int64("SCNMessageID", delivery.SCNMessageID).Int64("DeliveryID", delivery.DeliveryID).Msg("Delivery failed after <max> retries (set to FAILURE)") log.Warn().Int64("SCNMessageID", delivery.SCNMessageID.IntID()).Int64("DeliveryID", delivery.DeliveryID.IntID()).Msg("Delivery failed after <max> retries (set to FAILURE)")
} else { } else {
err = j.app.Database.SetDeliveryRetry(ctx, delivery) err = j.app.Database.SetDeliveryRetry(ctx, delivery)
if err != nil { 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() ctx.RollbackTransaction()
return return
} }

View File

@ -28,14 +28,12 @@ type Application struct {
Gin *gin.Engine Gin *gin.Engine
Database *db.Database Database *db.Database
Firebase *firebase.FBConnector Firebase *firebase.FBConnector
DefaultChannel string
Jobs []Job Jobs []Job
} }
func NewApp(db *db.Database) *Application { func NewApp(db *db.Database) *Application {
return &Application{ return &Application{
Database: db, Database: db,
DefaultChannel: "main",
} }
} }
@ -194,7 +192,7 @@ func (app *Application) getPermissions(ctx *AppContext, hdr string) (PermissionS
return NewEmptyPermissions(), nil 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) chanName = app.NormalizeChannelName(chanName)
existingChan, err := app.Database.GetChannelByName(ctx, userid, 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 { if client.FCMToken != nil {
fcmDelivID, err := app.Firebase.SendNotification(ctx, client, msg) fcmDelivID, err := app.Firebase.SendNotification(ctx, client, msg)
if err != nil { 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 nil, err
} }
return langext.Ptr(fcmDelivID), nil return langext.Ptr(fcmDelivID), nil

View File

@ -17,7 +17,7 @@ const (
) )
type PermissionSet struct { type PermissionSet struct {
UserID *int64 UserID *models.UserID
KeyType PermKeyType 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 p := ac.permissions
if p.UserID != nil && *p.UserID == userid && p.KeyType == PermKeyTypeUserRead { if p.UserID != nil && *p.UserID == userid && p.KeyType == PermKeyTypeUserRead {
return nil 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)) 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 p := ac.permissions
if p.UserID != nil && *p.UserID == userid && p.KeyType == PermKeyTypeUserAdmin { if p.UserID != nil && *p.UserID == userid && p.KeyType == PermKeyTypeUserAdmin {
return nil return nil
@ -94,7 +94,7 @@ func (ac *AppContext) CheckPermissionMessageReadDirect(msg models.Message) bool
return false return false
} }
func (ac *AppContext) GetPermissionUserID() *int64 { func (ac *AppContext) GetPermissionUserID() *models.UserID {
if ac.permissions.UserID == nil { if ac.permissions.UserID == nil {
return nil return nil
} else { } else {

View File

@ -8,8 +8,8 @@ import (
) )
type Channel struct { type Channel struct {
ChannelID int64 ChannelID ChannelID
OwnerUserID int64 OwnerUserID UserID
Name string Name string
SubscribeKey string SubscribeKey string
SendKey string SendKey string
@ -32,8 +32,8 @@ func (c Channel) JSON(includeKey bool) ChannelJSON {
} }
type ChannelJSON struct { type ChannelJSON struct {
ChannelID int64 `json:"channel_id"` ChannelID ChannelID `json:"channel_id"`
OwnerUserID int64 `json:"owner_user_id"` OwnerUserID UserID `json:"owner_user_id"`
Name string `json:"name"` Name string `json:"name"`
SubscribeKey *string `json:"subscribe_key"` // can be nil, depending on endpoint SubscribeKey *string `json:"subscribe_key"` // can be nil, depending on endpoint
SendKey *string `json:"send_key"` // can be nil, depending on endpoint SendKey *string `json:"send_key"` // can be nil, depending on endpoint
@ -43,8 +43,8 @@ type ChannelJSON struct {
} }
type ChannelDB struct { type ChannelDB struct {
ChannelID int64 `db:"channel_id"` ChannelID ChannelID `db:"channel_id"`
OwnerUserID int64 `db:"owner_user_id"` OwnerUserID UserID `db:"owner_user_id"`
Name string `db:"name"` Name string `db:"name"`
SubscribeKey string `db:"subscribe_key"` SubscribeKey string `db:"subscribe_key"`
SendKey string `db:"send_key"` SendKey string `db:"send_key"`

View File

@ -15,8 +15,8 @@ const (
) )
type Client struct { type Client struct {
ClientID int64 ClientID ClientID
UserID int64 UserID UserID
Type ClientType Type ClientType
FCMToken *string FCMToken *string
TimestampCreated time.Time TimestampCreated time.Time
@ -37,8 +37,8 @@ func (c Client) JSON() ClientJSON {
} }
type ClientJSON struct { type ClientJSON struct {
ClientID int64 `json:"client_id"` ClientID ClientID `json:"client_id"`
UserID int64 `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"`
@ -47,8 +47,8 @@ type ClientJSON struct {
} }
type ClientDB struct { type ClientDB struct {
ClientID int64 `db:"client_id"` ClientID ClientID `db:"client_id"`
UserID int64 `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"`

View File

@ -16,10 +16,10 @@ const (
) )
type Delivery struct { type Delivery struct {
DeliveryID int64 DeliveryID DeliveryID
SCNMessageID int64 SCNMessageID SCNMessageID
ReceiverUserID int64 ReceiverUserID UserID
ReceiverClientID int64 ReceiverClientID ClientID
TimestampCreated time.Time TimestampCreated time.Time
TimestampFinalized *time.Time TimestampFinalized *time.Time
Status DeliveryStatus Status DeliveryStatus
@ -48,10 +48,10 @@ func (d Delivery) MaxRetryCount() int {
} }
type DeliveryJSON struct { type DeliveryJSON struct {
DeliveryID int64 `json:"delivery_id"` DeliveryID DeliveryID `json:"delivery_id"`
SCNMessageID int64 `json:"scn_message_id"` SCNMessageID SCNMessageID `json:"scn_message_id"`
ReceiverUserID int64 `json:"receiver_user_id"` ReceiverUserID UserID `json:"receiver_user_id"`
ReceiverClientID int64 `json:"receiver_client_id"` ReceiverClientID ClientID `json:"receiver_client_id"`
TimestampCreated string `json:"timestamp_created"` TimestampCreated string `json:"timestamp_created"`
TimestampFinalized *string `json:"tiestamp_finalized"` TimestampFinalized *string `json:"tiestamp_finalized"`
Status DeliveryStatus `json:"status"` Status DeliveryStatus `json:"status"`
@ -61,10 +61,10 @@ type DeliveryJSON struct {
} }
type DeliveryDB struct { type DeliveryDB struct {
DeliveryID int64 `db:"delivery_id"` DeliveryID DeliveryID `db:"delivery_id"`
SCNMessageID int64 `db:"scn_message_id"` SCNMessageID SCNMessageID `db:"scn_message_id"`
ReceiverUserID int64 `db:"receiver_user_id"` ReceiverUserID UserID `db:"receiver_user_id"`
ReceiverClientID int64 `db:"receiver_client_id"` ReceiverClientID ClientID `db:"receiver_client_id"`
TimestampCreated int64 `db:"timestamp_created"` TimestampCreated int64 `db:"timestamp_created"`
TimestampFinalized *int64 `db:"tiestamp_finalized"` TimestampFinalized *int64 `db:"tiestamp_finalized"`
Status DeliveryStatus `db:"status"` Status DeliveryStatus `db:"status"`

68
server/models/ids.go Normal file
View File

@ -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)
}

View File

@ -13,11 +13,11 @@ const (
) )
type Message struct { type Message struct {
SCNMessageID int64 SCNMessageID SCNMessageID
SenderUserID int64 SenderUserID UserID
OwnerUserID int64 OwnerUserID UserID
ChannelName string ChannelName string
ChannelID int64 ChannelID ChannelID
TimestampReal time.Time TimestampReal time.Time
TimestampClient *time.Time TimestampClient *time.Time
Title string Title string
@ -87,11 +87,11 @@ func (m Message) ShortContent() string {
} }
type MessageJSON struct { type MessageJSON struct {
SCNMessageID int64 `json:"scn_message_id"` SCNMessageID SCNMessageID `json:"scn_message_id"`
SenderUserID int64 `json:"sender_user_id"` SenderUserID UserID `json:"sender_user_id"`
OwnerUserID int64 `json:"owner_user_id"` OwnerUserID UserID `json:"owner_user_id"`
ChannelName string `json:"channel_name"` ChannelName string `json:"channel_name"`
ChannelID int64 `json:"channel_id"` ChannelID ChannelID `json:"channel_id"`
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
Title string `json:"title"` Title string `json:"title"`
Content *string `json:"body"` Content *string `json:"body"`
@ -101,11 +101,11 @@ type MessageJSON struct {
} }
type MessageDB struct { type MessageDB struct {
SCNMessageID int64 `db:"scn_message_id"` SCNMessageID SCNMessageID `db:"scn_message_id"`
SenderUserID int64 `db:"sender_user_id"` SenderUserID UserID `db:"sender_user_id"`
OwnerUserID int64 `db:"owner_user_id"` OwnerUserID UserID `db:"owner_user_id"`
ChannelName string `db:"channel_name"` ChannelName string `db:"channel_name"`
ChannelID int64 `db:"channel_id"` ChannelID ChannelID `db:"channel_id"`
TimestampReal int64 `db:"timestamp_real"` TimestampReal int64 `db:"timestamp_real"`
TimestampClient *int64 `db:"timestamp_client"` TimestampClient *int64 `db:"timestamp_client"`
Title string `db:"title"` Title string `db:"title"`

View File

@ -8,10 +8,10 @@ import (
) )
type Subscription struct { type Subscription struct {
SubscriptionID int64 SubscriptionID SubscriptionID
SubscriberUserID int64 SubscriberUserID UserID
ChannelOwnerUserID int64 ChannelOwnerUserID UserID
ChannelID int64 ChannelID ChannelID
ChannelName string ChannelName string
TimestampCreated time.Time TimestampCreated time.Time
Confirmed bool Confirmed bool
@ -30,20 +30,20 @@ func (s Subscription) JSON() SubscriptionJSON {
} }
type SubscriptionJSON struct { type SubscriptionJSON struct {
SubscriptionID int64 `json:"subscription_id"` SubscriptionID SubscriptionID `json:"subscription_id"`
SubscriberUserID int64 `json:"subscriber_user_id"` SubscriberUserID UserID `json:"subscriber_user_id"`
ChannelOwnerUserID int64 `json:"channel_owner_user_id"` ChannelOwnerUserID UserID `json:"channel_owner_user_id"`
ChannelID int64 `json:"channel_id"` ChannelID ChannelID `json:"channel_id"`
ChannelName string `json:"channel_name"` ChannelName string `json:"channel_name"`
TimestampCreated string `json:"timestamp_created"` TimestampCreated string `json:"timestamp_created"`
Confirmed bool `json:"confirmed"` Confirmed bool `json:"confirmed"`
} }
type SubscriptionDB struct { type SubscriptionDB struct {
SubscriptionID int64 `db:"subscription_id"` SubscriptionID SubscriptionID `db:"subscription_id"`
SubscriberUserID int64 `db:"subscriber_user_id"` SubscriberUserID UserID `db:"subscriber_user_id"`
ChannelOwnerUserID int64 `db:"channel_owner_user_id"` ChannelOwnerUserID UserID `db:"channel_owner_user_id"`
ChannelID int64 `db:"channel_id"` ChannelID ChannelID `db:"channel_id"`
ChannelName string `db:"channel_name"` ChannelName string `db:"channel_name"`
TimestampCreated int64 `db:"timestamp_created"` TimestampCreated int64 `db:"timestamp_created"`
Confirmed int `db:"confirmed"` Confirmed int `db:"confirmed"`

View File

@ -9,7 +9,7 @@ import (
) )
type User struct { type User struct {
UserID int64 UserID UserID
Username *string Username *string
SendKey string SendKey string
ReadKey string ReadKey string
@ -38,6 +38,7 @@ func (u User) JSON() UserJSON {
QuotaUsed: u.QuotaUsed, QuotaUsed: u.QuotaUsed,
QuotaUsedDay: u.QuotaUsedDay, QuotaUsedDay: u.QuotaUsedDay,
IsPro: u.IsPro, IsPro: u.IsPro,
DefaultChannel: u.DefaultChannel(),
} }
} }
@ -74,8 +75,12 @@ func (u User) QuotaRemainingToday() int {
return u.QuotaPerDay() - u.QuotaUsedToday() return u.QuotaPerDay() - u.QuotaUsedToday()
} }
func (u User) DefaultChannel() string {
return "main"
}
type UserJSON struct { type UserJSON struct {
UserID int64 `json:"user_id"` UserID UserID `json:"user_id"`
Username *string `json:"username"` Username *string `json:"username"`
ReadKey string `json:"read_key"` ReadKey string `json:"read_key"`
SendKey string `json:"send_key"` SendKey string `json:"send_key"`
@ -87,10 +92,11 @@ type UserJSON struct {
QuotaUsed int `json:"quota_used"` QuotaUsed int `json:"quota_used"`
QuotaUsedDay *string `json:"quota_used_day"` QuotaUsedDay *string `json:"quota_used_day"`
IsPro bool `json:"is_pro"` IsPro bool `json:"is_pro"`
DefaultChannel string `json:"default_channel"`
} }
type UserDB struct { type UserDB struct {
UserID int64 `db:"user_id"` UserID UserID `db:"user_id"`
Username *string `db:"username"` Username *string `db:"username"`
SendKey string `db:"send_key"` SendKey string `db:"send_key"`
ReadKey string `db:"read_key"` ReadKey string `db:"read_key"`

View File

@ -2638,6 +2638,9 @@
"admin_key": { "admin_key": {
"type": "string" "type": "string"
}, },
"default_channel": {
"type": "string"
},
"is_pro": { "is_pro": {
"type": "boolean" "type": "boolean"
}, },

View File

@ -408,6 +408,8 @@ definitions:
properties: properties:
admin_key: admin_key:
type: string type: string
default_channel:
type: string
is_pro: is_pro:
type: boolean type: boolean
messages_sent: messages_sent: