Files
notifier/internal/auth/authz.go
T
igodwin eda033ff9b
CI / Lint (push) Successful in 2m29s
Build and Publish Container / build-and-publish (push) Successful in 2m58s
CI / Vulnerability scan (push) Successful in 44s
CI / Test (push) Successful in 1m45s
fix: clear golangci-lint backlog and make lint job blocking
Addresses errcheck, gosec, revive, staticcheck, and unused findings
across the codebase (unchecked error returns, unsafe file inclusion
warnings on operator/test-controlled paths, missing package comments,
unused parameters, deprecated API usage). Also fixes two suppression
comments that were silently no-ops due to wrong syntax (#nosec needs
a leading '#', nolint reasons need '//' not '--').

With the backlog clear, drop continue-on-error from the CI lint job
per the plan left in b4b4806.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 10:32:51 -07:00

84 lines
2.6 KiB
Go

package auth
import (
"fmt"
"github.com/igodwin/notifier/internal/domain"
)
// NotifierAuthz manages authorization rules for notifiers
type NotifierAuthz struct {
// Map of "type:account" -> allowed roles
rules map[string][]string
}
// NewNotifierAuthz creates a new notifier authorization manager
func NewNotifierAuthz() *NotifierAuthz {
return &NotifierAuthz{
rules: make(map[string][]string),
}
}
// RegisterRule registers authorization rule for a notifier type and account
func (a *NotifierAuthz) RegisterRule(notificationType domain.NotificationType, account string, allowedRoles []string) {
key := makeAuthzKey(notificationType, account)
a.rules[key] = allowedRoles
}
// IsAuthorized checks if an auth context is authorized to use a specific notifier
func (a *NotifierAuthz) IsAuthorized(auth *Context, notificationType domain.NotificationType, account string) bool {
if auth == nil || len(auth.Roles) == 0 {
return false
}
key := makeAuthzKey(notificationType, account)
allowedRoles, exists := a.rules[key]
// If RBAC is enabled (at least one rule exists), restrict access:
// - Notifiers with explicit rules: check if user has allowed roles
// - Notifiers without rules: deny access (must be explicitly allowed)
if a.HasRules() {
if !exists {
// RBAC is enabled but this notifier has no rule - deny access
return false
}
// Check if any of the user's roles is in the allowed roles
for _, userRole := range auth.Roles {
for _, allowedRole := range allowedRoles {
if userRole == allowedRole {
return true
}
}
}
return false
}
// If no rules are registered at all, allow all authenticated users (open access)
return true
}
// HasRules returns true if any authorization rules have been registered
func (a *NotifierAuthz) HasRules() bool {
return len(a.rules) > 0
}
// GetAllowedRoles returns the allowed roles for a notifier
func (a *NotifierAuthz) GetAllowedRoles(notificationType domain.NotificationType, account string) []string {
key := makeAuthzKey(notificationType, account)
return a.rules[key]
}
// SetAllowedRoles sets the allowed roles for a notifier
func (a *NotifierAuthz) SetAllowedRoles(notificationType domain.NotificationType, account string, allowedRoles []string) {
key := makeAuthzKey(notificationType, account)
a.rules[key] = allowedRoles
}
// makeAuthzKey creates a compound key from notification type and account
func makeAuthzKey(notificationType domain.NotificationType, account string) string {
if account == "" {
return string(notificationType)
}
return fmt.Sprintf("%s:%s", notificationType, account)
}