diff --git a/app/http/endpoints/root/callback.go b/app/http/endpoints/root/callback.go index 85637a1..e2d5bd8 100644 --- a/app/http/endpoints/root/callback.go +++ b/app/http/endpoints/root/callback.go @@ -14,6 +14,7 @@ import ( "github.com/apex/log" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" + "strconv" "time" ) @@ -82,6 +83,10 @@ func CallbackHandler(ctx *gin.Context) { ctx.Redirect(302, config.Conf.Server.BaseUrl) + userId, err := strconv.ParseInt(currentUser.Id, 10, 64); if err != nil { // ??? + return + } + // Cache guilds because Discord takes like 2 whole seconds to return then go func() { var guilds []objects.Guild @@ -93,6 +98,12 @@ func CallbackHandler(ctx *gin.Context) { for _, guild := range guilds { go cache.Client.StoreGuild(guild) + + // cache roles + guildId, err := strconv.ParseInt(guild.Id, 10, 64); if err != nil { + continue + } + go cacheRoles(store, guildId, userId) } marshalled, err := json.Marshal(guilds) @@ -106,21 +117,16 @@ func CallbackHandler(ctx *gin.Context) { } func cacheRoles(store sessions.Session, guildId, userId int64) { - rolesChan := make(chan *[]int64, 0) - go utils.GetRolesRest(store, guildId, userId, rolesChan) - roles := <-rolesChan + roles := utils.GetRolesRest(store, guildId, userId) if roles == nil { return } - memberIdChan := make(chan *int) - go table.GetMemberId(guildId, userId, memberIdChan) - memberId := <-memberIdChan + // Delete old roles + table.DeleteRoles(guildId, userId) - if memberId == nil { - return + for _, role := range *roles { + table.CacheRole(guildId, userId, role) } - - } diff --git a/database/table/memberids.go b/database/table/memberids.go deleted file mode 100644 index 29e43b4..0000000 --- a/database/table/memberids.go +++ /dev/null @@ -1,38 +0,0 @@ -package table - -import ( - "github.com/TicketsBot/GoPanel/database" - "github.com/apex/log" -) - -// Use an intermediary table to prevent a many-to-many relationship -type MemberId struct { - MemberId int `gorm:"column:MEMBERID;primary_key;auto_increment"` - GuildId int64 `gorm:"column:GUILDID"` - UserId int64 `gorm:"column:USERID"` -} - -func (MemberId) TableName() string { - return "cache_memberids" -} - -func GetMemberId(guildId, userId int64, ch chan *int) { - var row MemberId - database.Database.Where(&MemberId{GuildId: guildId, UserId: userId}).Take(&row) - - if row.MemberId == 0 { - row = MemberId{ - GuildId: guildId, - UserId: userId, - } - if db := database.Database.Create(row).Scan(&row); db.Error != nil { - log.Error(db.Error.Error()) - ch <- nil - return - } - - ch <- &row.MemberId - } else { - ch <- &row.MemberId - } -} diff --git a/database/table/rolescache.go b/database/table/rolescache.go index cb1b264..b0807cc 100644 --- a/database/table/rolescache.go +++ b/database/table/rolescache.go @@ -1,11 +1,44 @@ package table -// Use an intermediary table to prevent a many-to-many relationship -type RoleCache struct { - MemberId int `gorm:"column:MEMBERID;primary_key"` - RoleId int64 `gorm:"column:ROLEID"` +import "github.com/TicketsBot/TicketsGo/database" + +type CachedRole struct { + AssociationId int `gorm:"column:ASSOCIATIONID;primary_key;auto_increment"` + GuildId int64 `gorm:"column:GUILDID"` + UserId int64 `gorm:"column:USERID"` + RoleId int64 `gorm:"column:ROLEID"` } -func (RoleCache) TableName() string { +func (CachedRole) TableName() string { return "cache_roles" } + +func DeleteRoles(guildId, userId int64) { + database.Db.Where(CachedRole{ + GuildId: guildId, + UserId: userId, + }).Delete(CachedRole{}) +} + +// TODO: Cache invalidation +func CacheRole(guildId, userId, roleId int64) { + database.Db.Create(&CachedRole{ + GuildId: guildId, + UserId: userId, + RoleId: roleId, + }) +} + +func GetCachedRoles(guildId, userId int64, res chan []int64) { + var rows []CachedRole + database.Db.Where(&CachedRole{ + GuildId: guildId, + UserId: userId, + }).Find(&rows) + + roles := make([]int64, 0) + for _, row := range rows { + roles = append(roles, row.RoleId) + } + res <- roles +} diff --git a/utils/permissionutils.go b/utils/permissionutils.go index d836971..540367e 100644 --- a/utils/permissionutils.go +++ b/utils/permissionutils.go @@ -1,7 +1,6 @@ package utils import ( - "fmt" "github.com/TicketsBot/GoPanel/config" "github.com/TicketsBot/GoPanel/database/table" "github.com/TicketsBot/GoPanel/utils/discord/endpoints/guild" @@ -31,7 +30,9 @@ func IsAdmin(store sessions.Session, guild objects.Guild, guildId, userId int64, res <- true } - userRoles := GetRoles(store, guildId, userId) + userRolesChan := make(chan []int64) + go table.GetCachedRoles(guildId, userId, userRolesChan) + userRoles := <-userRolesChan adminRolesChan := make(chan []int64) go table.GetAdminRoles(strconv.Itoa(int(guildId)), adminRolesChan) @@ -54,12 +55,7 @@ func IsAdmin(store sessions.Session, guild objects.Guild, guildId, userId int64, res <- false } -func GetRoles(store sessions.Session, guildId, userId int64) []int64 { - key := fmt.Sprintf("%d-%d", guildId, userId) - if cached, ok := roleCache.Get(key); ok { - return cached.([]int64) - } - +func GetRolesRest(store sessions.Session, guildId, userId int64) *[]int64 { var member objects.Member endpoint := guild.GetGuildMember(int(guildId), int(userId)) @@ -67,7 +63,5 @@ func GetRoles(store sessions.Session, guildId, userId int64) []int64 { return nil } - roleCache.Set(key, &member.Roles, time.Minute) - - return member.Roles + return &member.Roles }