diff --git a/app/http/endpoints/api/panelcreate.go b/app/http/endpoints/api/panelcreate.go index 465e9ae..5da647f 100644 --- a/app/http/endpoints/api/panelcreate.go +++ b/app/http/endpoints/api/panelcreate.go @@ -3,9 +3,11 @@ package api import ( "github.com/TicketsBot/GoPanel/config" dbclient "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/GoPanel/rpc" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/common/premium" "github.com/TicketsBot/database" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/objects/channel" @@ -32,10 +34,10 @@ func CreatePanel(ctx *gin.Context) { data.MessageId = 0 // Check panel quota - premiumChan := make(chan bool) - go utils.IsPremiumGuild(guildId, premiumChan) - isPremium := <-premiumChan - if !isPremium { + // TODO: Whitelabel tokens & ratelimiters + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + + if premiumTier == premium.None { panels, err := dbclient.Client.Panel.GetByGuild(guildId) if err != nil { ctx.AbortWithStatusJSON(500, gin.H{ @@ -57,7 +59,7 @@ func CreatePanel(ctx *gin.Context) { return } - msgId, err := data.sendEmbed(isPremium) + msgId, err := data.sendEmbed(premiumTier > premium.None) if err != nil { if err == request.ErrForbidden { ctx.AbortWithStatusJSON(500, gin.H{ diff --git a/app/http/endpoints/api/premium.go b/app/http/endpoints/api/premium.go index ff5fe41..df0db51 100644 --- a/app/http/endpoints/api/premium.go +++ b/app/http/endpoints/api/premium.go @@ -1,17 +1,20 @@ package api import ( - "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/rpc" + "github.com/TicketsBot/GoPanel/rpc/ratelimit" + "github.com/TicketsBot/common/premium" "github.com/gin-gonic/gin" ) func PremiumHandler(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - isPremium := make(chan bool) - go utils.IsPremiumGuild(guildId, isPremium) + // TODO: Whitelabel tokens & ratelimiters + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) ctx.JSON(200, gin.H{ - "premium": <-isPremium, + "premium": premiumTier >= premium.Premium, }) } diff --git a/app/http/endpoints/api/sendmessage.go b/app/http/endpoints/api/sendmessage.go index e9f6414..6c182e9 100644 --- a/app/http/endpoints/api/sendmessage.go +++ b/app/http/endpoints/api/sendmessage.go @@ -4,9 +4,10 @@ import ( "fmt" "github.com/TicketsBot/GoPanel/config" "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/GoPanel/rpc" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/rpc/ratelimit" - "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/common/premium" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" "github.com/rxdn/gdl/rest/request" @@ -41,9 +42,9 @@ func SendMessage(ctx *gin.Context) { } // Verify guild is premium - isPremium := make(chan bool) - go utils.IsPremiumGuild(guildId, isPremium) - if !<-isPremium { + // TODO: Whitelabel tokens & ratelimiters + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + if premiumTier == premium.None { ctx.AbortWithStatusJSON(402, gin.H{ "success": false, "error": "Guild is not premium", diff --git a/app/http/endpoints/api/whitelabel.go b/app/http/endpoints/api/whitelabel.go new file mode 100644 index 0000000..a099fdd --- /dev/null +++ b/app/http/endpoints/api/whitelabel.go @@ -0,0 +1,112 @@ +package api + +import ( + dbclient "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/GoPanel/messagequeue" + "github.com/TicketsBot/GoPanel/rpc" + "github.com/TicketsBot/common/premium" + "github.com/TicketsBot/common/tokenchange" + "github.com/TicketsBot/database" + "github.com/gin-gonic/gin" + "github.com/rxdn/gdl/rest" +) + +func WhitelabelHandler(ctx *gin.Context) { + userId := ctx.Keys["userid"].(uint64) + + premiumTier := rpc.PremiumClient.GetTierByUser(userId, false) + if premiumTier < premium.Whitelabel { + ctx.JSON(402, gin.H{ + "success": false, + "error": "You must have the whitelabel premium tier", + }) + return + } + + // Get token + var data map[string]interface{} + if err := ctx.BindJSON(&data); err != nil { + ctx.JSON(400, gin.H{ + "success": false, + "error": "Missing token", + }) + return + } + + token, ok := data["token"].(string) + if !ok { + ctx.JSON(400, gin.H{ + "success": false, + "error": "Missing token", + }) + return + } + + // Validate token + get bot ID + bot, err := rest.GetCurrentUser(token, nil) + if err != nil { + ctx.JSON(400, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + if !bot.Bot { + ctx.JSON(400, gin.H{ + "success": false, + "error": "Token is not of a bot user", + }) + return + } + + // Check if this is a different token + existing, err := dbclient.Client.Whitelabel.GetByUserId(userId) + if err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + if existing.Token == token { + // Respond with 200 to prevent information disclosure attack + ctx.JSON(200, gin.H{ + "success": true, + "bot": bot, + }) + return + } + + if err = dbclient.Client.Whitelabel.Set(database.WhitelabelBot{ + UserId: userId, + BotId: bot.Id, + Token: token, + }); err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + tokenChangeData := tokenchange.TokenChangeData{ + Token: token, + NewId: bot.Id, + OldId: existing.BotId, + } + + if err := tokenchange.PublishTokenChange(messagequeue.Client.Client, tokenChangeData); err != nil { + ctx.JSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + ctx.JSON(200, gin.H{ + "success": true, + "bot": bot, + }) +} diff --git a/app/http/endpoints/manage/webchatws.go b/app/http/endpoints/manage/webchatws.go index 7877972..baf6975 100644 --- a/app/http/endpoints/manage/webchatws.go +++ b/app/http/endpoints/manage/webchatws.go @@ -2,8 +2,12 @@ package manage import ( "fmt" + "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/rpc" "github.com/TicketsBot/GoPanel/rpc/cache" + "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/common/premium" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" @@ -122,9 +126,9 @@ func WebChatWs(ctx *gin.Context) { } // Verify the guild is premium - premium := make(chan bool) - go utils.IsPremiumGuild(guildIdParsed, premium) - if !<-premium { + // TODO: Whitelabel tokens & ratelimiters + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildIdParsed, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + if premiumTier == premium.None { conn.Close() return } diff --git a/app/http/endpoints/root/whitelabel.go b/app/http/endpoints/root/whitelabel.go new file mode 100644 index 0000000..2a08ba9 --- /dev/null +++ b/app/http/endpoints/root/whitelabel.go @@ -0,0 +1,32 @@ +package root + +import ( + "fmt" + "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/rpc" + "github.com/TicketsBot/common/premium" + "github.com/gin-gonic/contrib/sessions" + "github.com/gin-gonic/gin" +) + +func WhitelabelHandler(ctx *gin.Context) { + store := sessions.Default(ctx) + if store == nil { + return + } + defer store.Save() + + userId := store.Get("userid").(uint64) + + premiumTier := rpc.PremiumClient.GetTierByUser(userId, false) + if premiumTier < premium.Whitelabel { + ctx.Redirect(302, fmt.Sprintf("%s/premium", config.Conf.Server.MainSite)) + return + } + + ctx.HTML(200, "main/whitelabel", gin.H{ + "name": store.Get("name").(string), + "baseurl": config.Conf.Server.BaseUrl, + "avatar": store.Get("avatar").(string), + }) +} diff --git a/app/http/server.go b/app/http/server.go index 1e7515f..98b34d9 100644 --- a/app/http/server.go +++ b/app/http/server.go @@ -56,6 +56,7 @@ func StartServer() { authenticateGuild := authorized.Group("/", middleware.AuthenticateGuild(false)) authorized.GET("/", root.IndexHandler) + authorized.GET("/whitelabel", root.WhitelabelHandler) authorized.GET("/logout", root.LogoutHandler) authenticateGuild.GET("/manage/:id/settings", manage.SettingsHandler) @@ -108,6 +109,7 @@ func StartServer() { userGroup := router.Group("/user", middleware.AuthenticateToken) { userGroup.GET("/guilds", api.GetGuilds) + userGroup.POST("/whitelabel", api.WhitelabelHandler) } if err := router.Run(config.Conf.Server.Host); err != nil { @@ -119,6 +121,7 @@ func createRenderer() multitemplate.Renderer { r := multitemplate.NewRenderer() r = addMainTemplate(r, "index") + r = addMainTemplate(r, "whitelabel") r = addManageTemplate(r, "blacklist") r = addManageTemplate(r, "logs") diff --git a/cmd/panel/main.go b/cmd/panel/main.go index 4c6377d..c05610f 100644 --- a/cmd/panel/main.go +++ b/cmd/panel/main.go @@ -9,10 +9,12 @@ import ( "github.com/TicketsBot/GoPanel/config" "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/messagequeue" + "github.com/TicketsBot/GoPanel/rpc" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/archiverclient" + "github.com/TicketsBot/common/premium" "github.com/apex/log" gdlratelimit "github.com/rxdn/gdl/rest/ratelimit" "math/rand" @@ -33,13 +35,20 @@ func main() { database.ConnectToDatabase() cache.Instance = cache.NewCache() - manage.Archiver = archiverclient.NewArchiverClientWithTimeout(config.Conf.Bot.ObjectStore, time.Second * 15) + manage.Archiver = archiverclient.NewArchiverClientWithTimeout(config.Conf.Bot.ObjectStore, time.Second*15) utils.LoadEmoji() messagequeue.Client = messagequeue.NewRedisClient() go Listen(messagequeue.Client) + rpc.PremiumClient = premium.NewPremiumLookupClient( + premium.NewPatreonClient(config.Conf.Bot.PremiumLookupProxyUrl, config.Conf.Bot.PremiumLookupProxyKey), + messagequeue.Client.Client, + cache.Instance.PgCache, + database.Client, + ) + ratelimit.Ratelimiter = gdlratelimit.NewRateLimiter(gdlratelimit.NewRedisStore(messagequeue.Client.Client, "ratelimit"), 1) // TODO: Use values from config http.StartServer() diff --git a/go.mod b/go.mod index 3111ad4..84142a6 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,8 @@ go 1.14 require ( github.com/BurntSushi/toml v0.3.1 github.com/TicketsBot/archiverclient v0.0.0-20200425115930-0ca198cc8306 - github.com/TicketsBot/database v0.0.0-20200516170158-fd8a949aec2c + github.com/TicketsBot/common v0.0.0-20200526165242-b17694befe05 + github.com/TicketsBot/database v0.0.0-20200526163954-2cb21ac72d23 github.com/apex/log v1.1.2 github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible @@ -13,15 +14,14 @@ require ( github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2 github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607 github.com/gin-gonic/gin v1.6.2 - github.com/go-redis/redis v6.15.7+incompatible + github.com/go-redis/redis v6.15.8+incompatible github.com/gofrs/uuid v3.3.0+incompatible github.com/gorilla/sessions v1.2.0 // indirect github.com/gorilla/websocket v1.4.2 github.com/jackc/pgx/v4 v4.6.0 github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c github.com/pkg/errors v0.9.1 - github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 - github.com/rxdn/gdl v0.0.0-20200511170555-8ab2206d70df + github.com/rxdn/gdl v0.0.0-20200522202912-4ae241eb98c1 github.com/sirupsen/logrus v1.5.0 github.com/ulule/limiter/v3 v3.5.0 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a diff --git a/public/templates/includes/sidebar.tmpl b/public/templates/includes/sidebar.tmpl index a8372cb..8e8b644 100644 --- a/public/templates/includes/sidebar.tmpl +++ b/public/templates/includes/sidebar.tmpl @@ -8,6 +8,12 @@

Servers

+