diff --git a/app/http/endpoints/api/getticket.go b/app/http/endpoints/api/getticket.go index cf1bfe3..05d8c23 100644 --- a/app/http/endpoints/api/getticket.go +++ b/app/http/endpoints/api/getticket.go @@ -2,10 +2,9 @@ package api import ( "fmt" - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" - "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" @@ -19,6 +18,15 @@ var MentionRegex, _ = regexp.Compile("<@(\\d+)>") func GetTicket(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + ticketId, err := strconv.Atoi(ctx.Param("ticketId")) if err != nil { ctx.AbortWithStatusJSON(400, gin.H{ @@ -63,7 +71,7 @@ func GetTicket(ctx *gin.Context) { } // Get messages - messages, _ := rest.GetChannelMessages(config.Conf.Bot.Token, ratelimit.Ratelimiter, *ticket.ChannelId, rest.GetChannelMessagesData{Limit: 100}) + messages, _ := rest.GetChannelMessages(botContext.Token, botContext.RateLimiter, *ticket.ChannelId, rest.GetChannelMessagesData{Limit: 100}) // Format messages, exclude unneeded data messagesFormatted := make([]map[string]interface{}, 0) diff --git a/app/http/endpoints/api/guilds.go b/app/http/endpoints/api/guilds.go index a49af30..64cf973 100644 --- a/app/http/endpoints/api/guilds.go +++ b/app/http/endpoints/api/guilds.go @@ -3,6 +3,7 @@ package api import ( "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/common/permission" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/objects/guild" ) @@ -36,9 +37,7 @@ func GetGuilds(ctx *gin.Context) { fakeGuild.OwnerId = userId } - isAdmin := make(chan bool) - go utils.IsAdmin(fakeGuild, userId, isAdmin) - if <-isAdmin { + if utils.GetPermissionLevel(g.GuildId, userId) >= permission.Admin { adminGuilds = append(adminGuilds, wrappedGuild{ Id: g.GuildId, Name: g.Name, diff --git a/app/http/endpoints/api/logslist.go b/app/http/endpoints/api/logslist.go index 376453a..bb945a5 100644 --- a/app/http/endpoints/api/logslist.go +++ b/app/http/endpoints/api/logslist.go @@ -3,10 +3,9 @@ package api import ( "context" "fmt" - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" dbclient "github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/rpc/cache" - "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/database" "github.com/apex/log" @@ -22,6 +21,15 @@ const ( func GetLogs(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + before, err := strconv.Atoi(ctx.Query("before")) if before < 0 { before = 0 @@ -102,7 +110,7 @@ func GetLogs(ctx *gin.Context) { // get username user, found := cache.Instance.GetUser(ticket.UserId) if !found { - user, err = rest.GetUser(config.Conf.Bot.Token, ratelimit.Ratelimiter, ticket.UserId) + user, err = rest.GetUser(botContext.Token, botContext.RateLimiter, ticket.UserId) if err != nil { log.Error(err.Error()) } diff --git a/app/http/endpoints/api/panelcreate.go b/app/http/endpoints/api/panelcreate.go index 5da647f..bfc3820 100644 --- a/app/http/endpoints/api/panelcreate.go +++ b/app/http/endpoints/api/panelcreate.go @@ -1,11 +1,10 @@ package api import ( - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" 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" @@ -21,6 +20,16 @@ import ( func CreatePanel(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) + + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + var data panel if err := ctx.BindJSON(&data); err != nil { @@ -34,8 +43,7 @@ func CreatePanel(ctx *gin.Context) { data.MessageId = 0 // Check panel quota - // TODO: Whitelabel tokens & ratelimiters - premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, botContext.Token, botContext.RateLimiter) if premiumTier == premium.None { panels, err := dbclient.Client.Panel.GetByGuild(guildId) @@ -59,7 +67,7 @@ func CreatePanel(ctx *gin.Context) { return } - msgId, err := data.sendEmbed(premiumTier > premium.None) + msgId, err := data.sendEmbed(&botContext, premiumTier > premium.None) if err != nil { if err == request.ErrForbidden { ctx.AbortWithStatusJSON(500, gin.H{ @@ -79,7 +87,7 @@ func CreatePanel(ctx *gin.Context) { // Add reaction emoji, _ := data.getEmoji() // already validated - if err = rest.CreateReaction(config.Conf.Bot.Token, ratelimit.Ratelimiter, data.ChannelId, msgId, emoji); err != nil { + if err = rest.CreateReaction(botContext.Token, botContext.RateLimiter, data.ChannelId, msgId, emoji); err != nil { if err == request.ErrForbidden { ctx.AbortWithStatusJSON(500, gin.H{ "success": false, @@ -208,7 +216,7 @@ func (p *panel) verifyCategory(channels []channel.Channel) bool { return valid } -func (p *panel) sendEmbed(isPremium bool) (messageId uint64, err error) { +func (p *panel) sendEmbed(ctx *botcontext.BotContext, isPremium bool) (messageId uint64, err error) { e := embed.NewEmbed(). SetTitle(p.Title). SetDescription(p.Content). @@ -220,7 +228,7 @@ func (p *panel) sendEmbed(isPremium bool) (messageId uint64, err error) { } var msg message.Message - msg, err = rest.CreateMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, p.ChannelId, rest.CreateMessageData{Embed: e}) + msg, err = rest.CreateMessage(ctx.Token, ctx.RateLimiter, p.ChannelId, rest.CreateMessageData{Embed: e}) if err != nil { return } diff --git a/app/http/endpoints/api/paneldelete.go b/app/http/endpoints/api/paneldelete.go index 11ae81a..6d11116 100644 --- a/app/http/endpoints/api/paneldelete.go +++ b/app/http/endpoints/api/paneldelete.go @@ -1,9 +1,8 @@ package api import ( - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" "github.com/TicketsBot/GoPanel/database" - "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" "strconv" @@ -12,6 +11,15 @@ import ( func DeletePanel(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + messageId, err := strconv.ParseUint(ctx.Param("message"), 10, 64) if err != nil { ctx.AbortWithStatusJSON(400, gin.H{ @@ -47,7 +55,7 @@ func DeletePanel(ctx *gin.Context) { return } - if err := rest.DeleteMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, panel.ChannelId, panel.MessageId); err != nil { + if err := rest.DeleteMessage(botContext.Token, botContext.RateLimiter, panel.ChannelId, panel.MessageId); err != nil { ctx.JSON(500, gin.H{ "success": false, "error": err.Error(), diff --git a/app/http/endpoints/api/premium.go b/app/http/endpoints/api/premium.go index df0db51..d30672a 100644 --- a/app/http/endpoints/api/premium.go +++ b/app/http/endpoints/api/premium.go @@ -1,9 +1,8 @@ package api import ( - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" "github.com/TicketsBot/GoPanel/rpc" - "github.com/TicketsBot/GoPanel/rpc/ratelimit" "github.com/TicketsBot/common/premium" "github.com/gin-gonic/gin" ) @@ -11,8 +10,16 @@ import ( func PremiumHandler(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) - // TODO: Whitelabel tokens & ratelimiters - premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, botContext.Token, botContext.RateLimiter) ctx.JSON(200, gin.H{ "premium": premiumTier >= premium.Premium, diff --git a/app/http/endpoints/api/sendmessage.go b/app/http/endpoints/api/sendmessage.go index 6c182e9..c305d63 100644 --- a/app/http/endpoints/api/sendmessage.go +++ b/app/http/endpoints/api/sendmessage.go @@ -2,11 +2,10 @@ package api import ( "fmt" - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" "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/common/premium" "github.com/gin-gonic/gin" "github.com/rxdn/gdl/rest" @@ -22,6 +21,15 @@ func SendMessage(ctx *gin.Context) { guildId := ctx.Keys["guildid"].(uint64) userId := ctx.Keys["userid"].(uint64) + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + // Get ticket ID ticketId, err := strconv.Atoi(ctx.Param("ticketId")) if err != nil { @@ -42,8 +50,7 @@ func SendMessage(ctx *gin.Context) { } // Verify guild is premium - // TODO: Whitelabel tokens & ratelimiters - premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildId, true, botContext.Token, botContext.RateLimiter) if premiumTier == premium.None { ctx.AbortWithStatusJSON(402, gin.H{ "success": false, @@ -90,8 +97,8 @@ func SendMessage(ctx *gin.Context) { } if webhook.Id != 0 { - // TODO: Use gdl execute webhook wrapper - _, err = rest.ExecuteWebhook(webhook.Token, ratelimit.Ratelimiter, webhook.Id, true, rest.WebhookBody{ + // TODO: Ratelimit + _, err = rest.ExecuteWebhook(webhook.Token, nil, webhook.Id, true, rest.WebhookBody{ Content: body.Message, Username: user.Username, AvatarUrl: user.AvatarUrl(256), @@ -124,7 +131,7 @@ func SendMessage(ctx *gin.Context) { return } - if _, err = rest.CreateMessage(config.Conf.Bot.Token, ratelimit.Ratelimiter, *ticket.ChannelId, rest.CreateMessageData{Content: body.Message}); err != nil { + if _, err = rest.CreateMessage(botContext.Token, botContext.RateLimiter, *ticket.ChannelId, rest.CreateMessageData{Content: body.Message}); err != nil { ctx.AbortWithStatusJSON(500, gin.H{ "success": false, "error": err.Error(), diff --git a/app/http/endpoints/manage/logsview.go b/app/http/endpoints/manage/logsview.go index f9e3f3b..c4b4e6e 100644 --- a/app/http/endpoints/manage/logsview.go +++ b/app/http/endpoints/manage/logsview.go @@ -8,6 +8,7 @@ import ( "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/archiverclient" + "github.com/TicketsBot/common/permission" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" "strconv" @@ -58,10 +59,7 @@ func LogViewHandler(ctx *gin.Context) { } // Verify the user has permissions to be here - // TODO: Allow support reps to view - isAdmin := make(chan bool) - go utils.IsAdmin(guild, userId, isAdmin) - if !<-isAdmin && ticket.UserId != userId { + if utils.GetPermissionLevel(guildId, userId) < permission.Support && ticket.UserId != userId { ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page return } diff --git a/app/http/endpoints/manage/modmaillogsview.go b/app/http/endpoints/manage/modmaillogsview.go index 1783401..f35a864 100644 --- a/app/http/endpoints/manage/modmaillogsview.go +++ b/app/http/endpoints/manage/modmaillogsview.go @@ -8,6 +8,7 @@ import ( "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/archiverclient" + "github.com/TicketsBot/common/permission" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" "github.com/gofrs/uuid" @@ -68,9 +69,7 @@ func ModmailLogViewHandler(ctx *gin.Context) { } // Verify the user has permissions to be here - isAdmin := make(chan bool) - go utils.IsAdmin(guild, userId, isAdmin) - if !<-isAdmin && archive.UserId != userId { + if utils.GetPermissionLevel(guildId, userId) < permission.Support && archive.UserId != userId { ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page return } diff --git a/app/http/endpoints/manage/webchatws.go b/app/http/endpoints/manage/webchatws.go index baf6975..73075ff 100644 --- a/app/http/endpoints/manage/webchatws.go +++ b/app/http/endpoints/manage/webchatws.go @@ -2,11 +2,11 @@ package manage import ( "fmt" - "github.com/TicketsBot/GoPanel/config" + "github.com/TicketsBot/GoPanel/botcontext" "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/permission" "github.com/TicketsBot/common/premium" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" @@ -117,17 +117,23 @@ func WebChatWs(ctx *gin.Context) { guild, _ := cache.Instance.GetGuild(guildIdParsed, false) // Verify the user has permissions to be here - isAdmin := make(chan bool) - go utils.IsAdmin(guild, userId, isAdmin) - if !<-isAdmin { + if utils.GetPermissionLevel(guild.Id, userId) < permission.Admin { fmt.Println(err.Error()) conn.Close() return } + botContext, err := botcontext.ContextForGuild(guildIdParsed) + if err != nil { + ctx.AbortWithStatusJSON(500, gin.H{ + "success": false, + "error": err.Error(), + }) + return + } + // Verify the guild is premium - // TODO: Whitelabel tokens & ratelimiters - premiumTier := rpc.PremiumClient.GetTierByGuildId(guildIdParsed, true, config.Conf.Bot.Token, ratelimit.Ratelimiter) + premiumTier := rpc.PremiumClient.GetTierByGuildId(guildIdParsed, true, botContext.Token, botContext.RateLimiter) if premiumTier == premium.None { conn.Close() return diff --git a/app/http/middleware/authenticateguild.go b/app/http/middleware/authenticateguild.go index 18a7fab..d891179 100644 --- a/app/http/middleware/authenticateguild.go +++ b/app/http/middleware/authenticateguild.go @@ -5,6 +5,7 @@ import ( "github.com/TicketsBot/GoPanel/config" "github.com/TicketsBot/GoPanel/rpc/cache" "github.com/TicketsBot/GoPanel/utils" + "github.com/TicketsBot/common/permission" "github.com/gin-gonic/gin" "strconv" ) @@ -43,9 +44,8 @@ func AuthenticateGuild(isApiMethod bool) gin.HandlerFunc { ctx.Keys["guild"] = guild // Verify the user has permissions to be here - isAdmin := make(chan bool) - go utils.IsAdmin(guild, ctx.Keys["userid"].(uint64), isAdmin) - if !<-isAdmin { + userId := ctx.Keys["userid"].(uint64) + if utils.GetPermissionLevel(guild.Id, userId) != permission.Admin { if isApiMethod { ctx.AbortWithStatusJSON(403, gin.H{ "success": false, diff --git a/botcontext/botcontext.go b/botcontext/botcontext.go new file mode 100644 index 0000000..a3847a1 --- /dev/null +++ b/botcontext/botcontext.go @@ -0,0 +1,90 @@ +package botcontext + +import ( + "github.com/TicketsBot/GoPanel/config" + dbclient "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/GoPanel/messagequeue" + "github.com/TicketsBot/GoPanel/rpc/cache" + "github.com/TicketsBot/database" + "github.com/go-redis/redis" + "github.com/rxdn/gdl/objects/channel" + "github.com/rxdn/gdl/objects/guild" + "github.com/rxdn/gdl/objects/member" + "github.com/rxdn/gdl/rest" + "github.com/rxdn/gdl/rest/ratelimit" +) + +type BotContext struct { + Token string + RateLimiter *ratelimit.Ratelimiter +} + +func (ctx BotContext) Db() *database.Database { + return dbclient.Client +} + +func (ctx BotContext) Redis() *redis.Client { + return messagequeue.Client.Client +} + +func (ctx BotContext) IsBotAdmin(userId uint64) bool { + for _, id := range config.Conf.Admins { + if id == userId { + return true + } + } + + return false +} + +func (ctx BotContext) GetGuild(guildId uint64) (g guild.Guild, err error) { + if guild, found := cache.Instance.GetGuild(guildId, false); found { + return guild, nil + } + + g, err = rest.GetGuild(ctx.Token, ctx.RateLimiter, guildId) + if err == nil { + go cache.Instance.StoreGuild(g) + } + + return +} + +func (ctx BotContext) GetChannel(channelId uint64) (ch channel.Channel, err error) { + if channel, found := cache.Instance.GetChannel(channelId); found { + return channel, nil + } + + ch, err = rest.GetChannel(ctx.Token, ctx.RateLimiter, channelId) + if err == nil { + go cache.Instance.StoreChannel(ch) + } + + return +} + +func (ctx BotContext) GetGuildMember(guildId, userId uint64) (m member.Member, err error) { + if guild, found := cache.Instance.GetMember(guildId, userId); found { + return guild, nil + } + + m, err = rest.GetGuildMember(ctx.Token, ctx.RateLimiter, guildId, userId) + if err == nil { + go cache.Instance.StoreMember(m, guildId) + } + + return +} + +func (ctx BotContext) GetGuildRoles(guildId uint64) (roles []guild.Role, err error) { + if roles := cache.Instance.GetGuildRoles(guildId); len(roles) > 0 { + return roles, nil + } + + roles, err = rest.GetGuildRoles(ctx.Token, ctx.RateLimiter, guildId) + if err == nil { + go cache.Instance.StoreRoles(roles, guildId) + } + + return +} diff --git a/botcontext/get.go b/botcontext/get.go new file mode 100644 index 0000000..4a2452a --- /dev/null +++ b/botcontext/get.go @@ -0,0 +1,36 @@ +package botcontext + +import ( + "fmt" + "github.com/TicketsBot/GoPanel/config" + dbclient "github.com/TicketsBot/GoPanel/database" + "github.com/TicketsBot/GoPanel/messagequeue" + "github.com/rxdn/gdl/rest/ratelimit" +) + +func ContextForGuild(guildId uint64) (ctx BotContext, err error) { + whitelabelBotId, isWhitelabel, err := dbclient.Client.WhitelabelGuilds.GetBotByGuild(guildId) + if err != nil { + return + } + + var keyPrefix string + + if isWhitelabel { + res, err := dbclient.Client.Whitelabel.GetByBotId(whitelabelBotId) + if err != nil { + return ctx, err + } + + ctx.Token = res.Token + keyPrefix = fmt.Sprintf("ratelimiter:%d", whitelabelBotId) + } else { + ctx.Token = config.Conf.Bot.Token + keyPrefix = "ratelimiter:public" + } + + // TODO: Large sharding buckets + ctx.RateLimiter = ratelimit.NewRateLimiter(ratelimit.NewRedisStore(messagequeue.Client.Client, keyPrefix), 1) + + return +} diff --git a/cmd/panel/main.go b/cmd/panel/main.go index c05610f..923fa80 100644 --- a/cmd/panel/main.go +++ b/cmd/panel/main.go @@ -11,12 +11,10 @@ import ( "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" "time" ) @@ -49,8 +47,6 @@ func main() { database.Client, ) - ratelimit.Ratelimiter = gdlratelimit.NewRateLimiter(gdlratelimit.NewRedisStore(messagequeue.Client.Client, "ratelimit"), 1) // TODO: Use values from config - http.StartServer() } diff --git a/config.toml.example b/config.toml.example index fb83577..8370371 100644 --- a/config.toml.example +++ b/config.toml.example @@ -1,4 +1,4 @@ -admins=["217617036749176833"] +admins=[585576154958921739] [server] host="0.0.0.0:3000" diff --git a/config/config.go b/config/config.go index 38d935e..073345e 100644 --- a/config/config.go +++ b/config/config.go @@ -7,7 +7,7 @@ import ( type ( Config struct { - Admins []string + Admins []uint64 Server Server Oauth Oauth Database Database diff --git a/go.mod b/go.mod index 84142a6..132e74b 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +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/common v0.0.0-20200526165242-b17694befe05 - github.com/TicketsBot/database v0.0.0-20200526163954-2cb21ac72d23 + github.com/TicketsBot/common v0.0.0-20200527174950-d8ebbcbf49c9 + github.com/TicketsBot/database v0.0.0-20200527183847-2fbafde7649e 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 diff --git a/rpc/ratelimit/ratelimit.go b/rpc/ratelimit/ratelimit.go deleted file mode 100644 index 876f6dc..0000000 --- a/rpc/ratelimit/ratelimit.go +++ /dev/null @@ -1,7 +0,0 @@ -package ratelimit - -import ( - "github.com/rxdn/gdl/rest/ratelimit" -) - -var Ratelimiter *ratelimit.Ratelimiter diff --git a/utils/permissionutils.go b/utils/permissionutils.go index 2c03dfd..b200608 100644 --- a/utils/permissionutils.go +++ b/utils/permissionutils.go @@ -1,133 +1,21 @@ package utils import ( - "context" - "errors" - "github.com/TicketsBot/GoPanel/config" - "github.com/TicketsBot/GoPanel/database" - "github.com/TicketsBot/GoPanel/rpc/cache" - "github.com/TicketsBot/GoPanel/rpc/ratelimit" - "github.com/apex/log" - "github.com/rxdn/gdl/objects/guild" - "github.com/rxdn/gdl/permission" - "github.com/rxdn/gdl/rest" - "golang.org/x/sync/errgroup" - "strconv" - "sync" + "github.com/TicketsBot/GoPanel/botcontext" + "github.com/TicketsBot/common/permission" ) -// TODO: Use Redis cache -// TODO: Error handling -func IsAdmin(g guild.Guild, userId uint64, res chan bool) { - if Contains(config.Conf.Admins, strconv.FormatUint(userId, 10)) { - res <- true - return +func GetPermissionLevel(guildId, userId uint64) permission.PermissionLevel { + botContext, err := botcontext.ContextForGuild(guildId) + if err != nil { + return permission.Everyone } - if g.OwnerId == userId { - res <- true - return + // get member + member, err := botContext.GetGuildMember(guildId, userId) + if err != nil { + return permission.Everyone } - if isAdmin, _ := database.Client.Permissions.IsAdmin(g.Id, userId); isAdmin { - res <- true - return - } - - userRoles, _ := getRoles(g.Id, userId) - - // check if user has administrator permission - if hasAdministratorPermission(g.Id, userRoles) { - res <- true - return - } - - adminRoles, _ := database.Client.RolePermissions.GetAdminRoles(g.Id) - - hasTicketAdminRole := false - for _, userRole := range userRoles { - for _, adminRole := range adminRoles { - if userRole == adminRole { - hasTicketAdminRole = true - break - } - } - } - - if hasTicketAdminRole { - res <- true - return - } - - res <- false -} - -func getRoles(guildId, userId uint64) ([]uint64, bool) { - member, found := cache.Instance.GetMember(guildId, userId) - if !found { // get from rest - var err error - member, err = rest.GetGuildMember(config.Conf.Bot.Token, ratelimit.Ratelimiter, guildId, userId) - if err != nil { - return nil, false - } - - // cache - cache.Instance.StoreMember(member, guildId) - } - - return member.Roles, true -} - -func hasAdministratorPermission(guildId uint64, roles []uint64) bool { - var lock sync.Mutex - var hasAdministrator bool - - group, _ := errgroup.WithContext(context.Background()) - for _, roleId := range roles { - group.Go(func() error { - roleHasAdmin, err := roleHasAdministrator(guildId, roleId) - if err != nil { - return err - } - - if roleHasAdmin { - lock.Lock() - hasAdministrator = true - lock.Unlock() - } - - return nil - }) - } - - if err := group.Wait(); err != nil { - return false - } - - return hasAdministrator -} - -func roleHasAdministrator(guildId, roleId uint64) (bool, error) { - role, found := cache.Instance.GetRole(roleId) - if !found { - roles, err := rest.GetGuildRoles(config.Conf.Bot.Token, ratelimit.Ratelimiter, guildId) - if err != nil { - log.Error(err.Error()) - return false, err - } - - go cache.Instance.StoreRoles(roles, guildId) - for _, r := range roles { - if r.Id == roleId { - role = r - found = true - break - } - } - if !found { - return false, errors.New("role does not exist") - } - } - - return permission.HasPermissionRaw(role.Permissions, permission.Administrator), nil -} + return permission.GetPermissionLevel(botContext, member, guildId) +} \ No newline at end of file