diff --git a/app/http/endpoints/api/admin/botstaff/add.go b/app/http/endpoints/api/admin/botstaff/add.go
new file mode 100644
index 0000000..733e6aa
--- /dev/null
+++ b/app/http/endpoints/api/admin/botstaff/add.go
@@ -0,0 +1,23 @@
+package botstaff
+
+import (
+ "github.com/TicketsBot/GoPanel/database"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+ "strconv"
+)
+
+func AddBotStaffHandler(ctx *gin.Context) {
+ userId, err := strconv.ParseUint(ctx.Param("userid"), 10, 64)
+ if err != nil {
+ ctx.JSON(400, utils.ErrorJson(err))
+ return
+ }
+
+ if err := database.Client.BotStaff.Add(userId); err != nil {
+ ctx.JSON(500, utils.ErrorJson(err))
+ return
+ }
+
+ ctx.Status(204)
+}
diff --git a/app/http/endpoints/api/admin/botstaff/list.go b/app/http/endpoints/api/admin/botstaff/list.go
new file mode 100644
index 0000000..4badd2a
--- /dev/null
+++ b/app/http/endpoints/api/admin/botstaff/list.go
@@ -0,0 +1,57 @@
+package botstaff
+
+import (
+ "context"
+ "github.com/TicketsBot/GoPanel/database"
+ "github.com/TicketsBot/GoPanel/rpc/cache"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+ "github.com/rxdn/gdl/objects/user"
+ "golang.org/x/sync/errgroup"
+)
+
+type userData struct {
+ Id uint64 `json:"id,string"`
+ Username string `json:"username"`
+ Discriminator user.Discriminator `json:"discriminator"`
+}
+
+func ListBotStaffHandler(ctx *gin.Context) {
+ staff, err := database.Client.BotStaff.GetAll()
+ if err != nil {
+ ctx.JSON(500, utils.ErrorJson(err))
+ return
+ }
+
+ // Get usernames
+ group, _ := errgroup.WithContext(context.Background())
+
+ users := make([]userData, len(staff))
+ for i, userId := range staff {
+ i := i
+ userId := userId
+
+ group.Go(func() error {
+ user, ok := cache.Instance.GetUser(userId)
+
+ data := userData{
+ Id: userId,
+ }
+
+ if ok {
+ data.Username = user.Username
+ data.Discriminator = user.Discriminator
+ } else {
+ data.Username = "Unknown User"
+ }
+
+ users[i] = data
+
+ return nil
+ })
+ }
+
+ _ = group.Wait() // error not possible
+
+ ctx.JSON(200, users)
+}
diff --git a/app/http/endpoints/api/admin/botstaff/remove.go b/app/http/endpoints/api/admin/botstaff/remove.go
new file mode 100644
index 0000000..f2096a4
--- /dev/null
+++ b/app/http/endpoints/api/admin/botstaff/remove.go
@@ -0,0 +1,23 @@
+package botstaff
+
+import (
+ "github.com/TicketsBot/GoPanel/database"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+ "strconv"
+)
+
+func RemoveBotStaffHandler(ctx *gin.Context) {
+ userId, err := strconv.ParseUint(ctx.Param("userid"), 10, 64)
+ if err != nil {
+ ctx.JSON(400, utils.ErrorJson(err))
+ return
+ }
+
+ if err := database.Client.BotStaff.Delete(userId); err != nil {
+ ctx.JSON(500, utils.ErrorJson(err))
+ return
+ }
+
+ ctx.Status(204)
+}
diff --git a/app/http/endpoints/api/session.go b/app/http/endpoints/api/session.go
index a29d5c6..18e7451 100644
--- a/app/http/endpoints/api/session.go
+++ b/app/http/endpoints/api/session.go
@@ -33,17 +33,12 @@ func SessionHandler(ctx *gin.Context) {
return
}
- var whitelabelOverride bool
- for _, id := range config.Conf.ForceWhitelabel {
- if id == userId {
- whitelabelOverride = true
- break
- }
- }
+ whitelabelOverride := utils.Contains(config.Conf.ForceWhitelabel, userId)
ctx.JSON(200, gin.H{
"username": store.Name,
"avatar": store.Avatar,
"whitelabel": tier >= premium.Whitelabel || whitelabelOverride,
+ "admin": utils.Contains(config.Conf.Admins, userId),
})
}
diff --git a/app/http/endpoints/api/staffoverride/createoverride.go b/app/http/endpoints/api/staffoverride/createoverride.go
new file mode 100644
index 0000000..eb75c1a
--- /dev/null
+++ b/app/http/endpoints/api/staffoverride/createoverride.go
@@ -0,0 +1,32 @@
+package api
+
+import (
+ "fmt"
+ "github.com/TicketsBot/GoPanel/database"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+ "time"
+)
+
+type createOverrideBody struct {
+ TimePeriod int `json:"time_period"`
+}
+
+func CreateOverrideHandler(ctx *gin.Context) {
+ guildId := ctx.Keys["guildid"].(uint64)
+
+ var body createOverrideBody
+ if err := ctx.BindJSON(&body); err != nil {
+ ctx.JSON(400, utils.ErrorStr("Invalid request body"))
+ fmt.Println(err.Error())
+ return
+ }
+
+ expires := time.Now().Add(time.Hour * time.Duration(body.TimePeriod))
+ if err := database.Client.StaffOverride.Set(guildId, expires); err != nil {
+ ctx.JSON(500, utils.ErrorJson(err))
+ return
+ }
+
+ ctx.Status(204)
+}
diff --git a/app/http/endpoints/api/staffoverride/deleteoverride.go b/app/http/endpoints/api/staffoverride/deleteoverride.go
new file mode 100644
index 0000000..befe418
--- /dev/null
+++ b/app/http/endpoints/api/staffoverride/deleteoverride.go
@@ -0,0 +1,18 @@
+package api
+
+import (
+ "github.com/TicketsBot/GoPanel/database"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+)
+
+func DeleteOverrideHandler(ctx *gin.Context) {
+ guildId := ctx.Keys["guildid"].(uint64)
+
+ if err := database.Client.StaffOverride.Delete(guildId); err != nil {
+ ctx.JSON(500, utils.ErrorJson(err))
+ return
+ }
+
+ ctx.Status(204)
+}
diff --git a/app/http/endpoints/api/staffoverride/getoverride.go b/app/http/endpoints/api/staffoverride/getoverride.go
new file mode 100644
index 0000000..4161762
--- /dev/null
+++ b/app/http/endpoints/api/staffoverride/getoverride.go
@@ -0,0 +1,21 @@
+package api
+
+import (
+ "github.com/TicketsBot/GoPanel/database"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+)
+
+func GetOverrideHandler(ctx *gin.Context) {
+ guildId := ctx.Keys["guildid"].(uint64)
+
+ hasOverride, err := database.Client.StaffOverride.HasActiveOverride(guildId)
+ if err != nil {
+ ctx.JSON(500, utils.ErrorJson(err))
+ return
+ }
+
+ ctx.JSON(200, gin.H{
+ "has_override": hasOverride,
+ })
+}
diff --git a/app/http/middleware/adminonly.go b/app/http/middleware/adminonly.go
new file mode 100644
index 0000000..d2c1014
--- /dev/null
+++ b/app/http/middleware/adminonly.go
@@ -0,0 +1,17 @@
+package middleware
+
+import (
+ "github.com/TicketsBot/GoPanel/config"
+ "github.com/TicketsBot/GoPanel/utils"
+ "github.com/gin-gonic/gin"
+)
+
+func AdminOnly(ctx *gin.Context) {
+ userId := ctx.Keys["userid"].(uint64)
+
+ if !utils.Contains(config.Conf.Admins, userId) {
+ ctx.JSON(401, utils.ErrorStr("Unauthorized"))
+ ctx.Abort()
+ return
+ }
+}
diff --git a/app/http/middleware/authenticateguild.go b/app/http/middleware/authenticateguild.go
index 278f366..17b20d0 100644
--- a/app/http/middleware/authenticateguild.go
+++ b/app/http/middleware/authenticateguild.go
@@ -42,10 +42,12 @@ func AuthenticateGuild(requiredPermissionLevel permission.PermissionLevel) gin.H
if permLevel < requiredPermissionLevel {
ctx.JSON(403, utils.ErrorStr("Unauthorized"))
ctx.Abort()
+ return
}
} else {
ctx.JSON(400, utils.ErrorStr("Invalid guild ID"))
ctx.Abort()
+ return
}
}
}
diff --git a/app/http/middleware/logging.go b/app/http/middleware/logging.go
index 99e2637..0bcec8a 100644
--- a/app/http/middleware/logging.go
+++ b/app/http/middleware/logging.go
@@ -5,6 +5,7 @@ import (
"github.com/getsentry/sentry-go"
"github.com/gin-gonic/gin"
"io/ioutil"
+ "runtime/debug"
"strconv"
)
@@ -46,6 +47,7 @@ func Logging(minLevel sentry.Level) gin.HandlerFunc {
"user_id": ctx.Keys["userid"],
"request_body": string(requestBody),
"response": string(responseBody),
+ "stacktrace": string(debug.Stack()),
},
Level: level,
Message: fmt.Sprintf("HTTP %d on %s %s", statusCode, ctx.Request.Method, ctx.FullPath()),
diff --git a/app/http/server.go b/app/http/server.go
index 825846d..5d864a4 100644
--- a/app/http/server.go
+++ b/app/http/server.go
@@ -2,12 +2,14 @@ package http
import (
"github.com/TicketsBot/GoPanel/app/http/endpoints/api"
+ "github.com/TicketsBot/GoPanel/app/http/endpoints/api/admin/botstaff"
api_autoclose "github.com/TicketsBot/GoPanel/app/http/endpoints/api/autoclose"
api_blacklist "github.com/TicketsBot/GoPanel/app/http/endpoints/api/blacklist"
api_customisation "github.com/TicketsBot/GoPanel/app/http/endpoints/api/customisation"
api_forms "github.com/TicketsBot/GoPanel/app/http/endpoints/api/forms"
api_panels "github.com/TicketsBot/GoPanel/app/http/endpoints/api/panel"
api_settings "github.com/TicketsBot/GoPanel/app/http/endpoints/api/settings"
+ api_override "github.com/TicketsBot/GoPanel/app/http/endpoints/api/staffoverride"
api_tags "github.com/TicketsBot/GoPanel/app/http/endpoints/api/tags"
api_team "github.com/TicketsBot/GoPanel/app/http/endpoints/api/team"
api_ticket "github.com/TicketsBot/GoPanel/app/http/endpoints/api/ticket"
@@ -67,8 +69,8 @@ func StartServer() {
apiGroup.GET("/session", api.SessionHandler)
}
- guildAuthApiAdmin := apiGroup.Group("/:id", middleware.AuthenticateGuild(true, permission.Admin))
- guildAuthApiSupport := apiGroup.Group("/:id", middleware.AuthenticateGuild(true, permission.Support))
+ guildAuthApiAdmin := apiGroup.Group("/:id", middleware.AuthenticateGuild(permission.Admin))
+ guildAuthApiSupport := apiGroup.Group("/:id", middleware.AuthenticateGuild(permission.Support))
guildApiNoAuth := apiGroup.Group("/:id", middleware.ParseGuildId)
{
guildAuthApiSupport.GET("/channels", api.ChannelsHandler)
@@ -150,6 +152,10 @@ func StartServer() {
guildAuthApiAdmin.PUT("/team/:teamid/:snowflake", rl(middleware.RateLimitTypeGuild, 5, time.Second*10), api_team.AddMember)
guildAuthApiAdmin.DELETE("/team/:teamid", api_team.DeleteTeam)
guildAuthApiAdmin.DELETE("/team/:teamid/:snowflake", rl(middleware.RateLimitTypeGuild, 30, time.Minute), api_team.RemoveMember)
+
+ guildAuthApiAdmin.GET("/staff-override", api_override.GetOverrideHandler)
+ guildAuthApiAdmin.POST("/staff-override", api_override.CreateOverrideHandler)
+ guildAuthApiAdmin.DELETE("/staff-override", api_override.DeleteOverrideHandler)
}
userGroup := router.Group("/user", middleware.AuthenticateToken)
@@ -173,6 +179,13 @@ func StartServer() {
}
}
+ adminGroup := apiGroup.Group("/admin", middleware.AdminOnly)
+ {
+ adminGroup.GET("/bot-staff", botstaff.ListBotStaffHandler)
+ adminGroup.POST("/bot-staff/:userid", botstaff.AddBotStaffHandler)
+ adminGroup.DELETE("/bot-staff/:userid", botstaff.RemoveBotStaffHandler)
+ }
+
if err := router.Run(config.Conf.Server.Host); err != nil {
panic(err)
}
diff --git a/frontend/src/components/Button.svelte b/frontend/src/components/Button.svelte
index 37bb5ae..c151a7f 100644
--- a/frontend/src/components/Button.svelte
+++ b/frontend/src/components/Button.svelte
@@ -3,66 +3,66 @@
{/if}
-
Username | +Remove | +
---|---|
{user.username}#{user.discriminator} ({user.id}) | ++ + | +