110 lines
2.3 KiB
Go
110 lines
2.3 KiB
Go
package tickets
|
|
|
|
import (
|
|
"github.com/leolionad58/ticketbot/internal/config"
|
|
"github.com/leolionad58/ticketbot/internal/db"
|
|
)
|
|
|
|
type Action int
|
|
|
|
const (
|
|
ActionAdmin Action = iota
|
|
ActionClaim
|
|
ActionClose
|
|
ActionAdd
|
|
ActionRemove
|
|
ActionRename
|
|
ActionTranscript
|
|
ActionConvocation
|
|
ActionReclaim
|
|
)
|
|
|
|
type AuthService struct {
|
|
Config *config.Provider
|
|
}
|
|
|
|
func NewAuthService(cfg *config.Provider) *AuthService {
|
|
return &AuthService{Config: cfg}
|
|
}
|
|
|
|
// CanClose returns true if the user can close the given ticket.
|
|
// Ticket owner can close if status is 'open' (not yet claimed). Staff/admin can always close.
|
|
func (a *AuthService) CanClose(memberRoles []string, userID string, ticket *db.Ticket) bool {
|
|
if ticket == nil {
|
|
return false
|
|
}
|
|
// Owner can close their own unclaimed ticket
|
|
if userID == ticket.UserID && ticket.Status == "open" {
|
|
return true
|
|
}
|
|
return a.Can(memberRoles, ActionClose, ticket)
|
|
}
|
|
|
|
// Can returns true if the member (by their role IDs) is authorized to perform action on ticket.
|
|
// ticket may be nil for actions that don't require a specific ticket context (e.g. ActionAdmin, ActionConvocation).
|
|
func (a *AuthService) Can(memberRoles []string, action Action, ticket *db.Ticket) bool {
|
|
cfg := a.Config.Get()
|
|
|
|
hasRole := func(roleID string) bool {
|
|
for _, r := range memberRoles {
|
|
if r == roleID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
isAdmin := hasRole(cfg.Bot.AdminRole)
|
|
|
|
staffRoleForTicket := func() string {
|
|
if ticket == nil {
|
|
return ""
|
|
}
|
|
// Prefer role stored on the ticket itself (populated at open time for DB panels)
|
|
if ticket.StaffRoleID != "" {
|
|
return ticket.StaffRoleID
|
|
}
|
|
if p, ok := cfg.Panels[ticket.Panel]; ok {
|
|
if t, ok := p.Types[ticket.Type]; ok {
|
|
return t.StaffRole
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
switch action {
|
|
case ActionAdmin:
|
|
return isAdmin
|
|
|
|
case ActionClaim:
|
|
if isAdmin {
|
|
return true
|
|
}
|
|
role := staffRoleForTicket()
|
|
return role != "" && hasRole(role)
|
|
|
|
case ActionClose, ActionAdd, ActionRemove, ActionRename, ActionTranscript, ActionReclaim:
|
|
if isAdmin {
|
|
return true
|
|
}
|
|
role := staffRoleForTicket()
|
|
return role != "" && hasRole(role)
|
|
|
|
case ActionConvocation:
|
|
if isAdmin {
|
|
return true
|
|
}
|
|
for _, panel := range cfg.Panels {
|
|
for _, t := range panel.Types {
|
|
if hasRole(t.StaffRole) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
|
|
default:
|
|
return false
|
|
}
|
|
}
|