Some checks failed
CI / build (push) Failing after 36s
WASM reactive UI framework for Go: - reactive/ - Signal[T], Effect, Runtime - ui/ - Button, Text, Input, View, Canvas, SVG components - navigation/ - Router, guards, history management - auth/ - OIDC client for WASM applications - host/ - Static file server Extracted from arcadia as open-source component. Co-Authored-By: Claude <noreply@anthropic.com>
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package navigation
|
|
|
|
import "strings"
|
|
|
|
// Common route guards
|
|
|
|
// AuthGuard checks if user is authenticated
|
|
func AuthGuard(isAuthenticated func() bool) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
return isAuthenticated()
|
|
}
|
|
}
|
|
|
|
// RoleGuard checks if user has required role
|
|
func RoleGuard(userRole func() string, requiredRole string) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
return userRole() == requiredRole
|
|
}
|
|
}
|
|
|
|
// PermissionGuard checks if user has specific permission
|
|
func PermissionGuard(hasPermission func(permission string) bool, permission string) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
return hasPermission(permission)
|
|
}
|
|
}
|
|
|
|
// ParamValidationGuard validates route parameters
|
|
func ParamValidationGuard(validator func(params map[string]string) bool) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
return validator(params)
|
|
}
|
|
}
|
|
|
|
// PathPrefixGuard checks if the current path starts with a specific prefix
|
|
func PathPrefixGuard(prefix string) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
currentPath := GetCurrentPath()
|
|
return strings.HasPrefix(currentPath, prefix)
|
|
}
|
|
}
|
|
|
|
// CombineGuards combines multiple guards with AND logic
|
|
func CombineGuards(guards ...RouteGuard) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
for _, guard := range guards {
|
|
if !guard(route, params) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
// AnyGuard combines multiple guards with OR logic
|
|
func AnyGuard(guards ...RouteGuard) RouteGuard {
|
|
return func(route *Route, params map[string]string) bool {
|
|
for _, guard := range guards {
|
|
if guard(route, params) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Example usage patterns:
|
|
|
|
// AdminOnlyGuard - combines authentication and role checks
|
|
func AdminOnlyGuard(isAuth func() bool, userRole func() string) RouteGuard {
|
|
return CombineGuards(
|
|
AuthGuard(isAuth),
|
|
RoleGuard(userRole, "admin"),
|
|
)
|
|
}
|
|
|
|
// NumericIdGuard - validates that :id parameter is numeric
|
|
func NumericIdGuard() RouteGuard {
|
|
return ParamValidationGuard(func(params map[string]string) bool {
|
|
if id, exists := params["id"]; exists {
|
|
// Simple numeric check
|
|
for _, char := range id {
|
|
if char < '0' || char > '9' {
|
|
return false
|
|
}
|
|
}
|
|
return len(id) > 0
|
|
}
|
|
return true // No id param, so validation passes
|
|
})
|
|
} |