Add support for read/write permissive overrides in policies
Some checks failed
Go / build-and-release (push) Has been cancelled
Some checks failed
Go / build-and-release (push) Has been cancelled
Introduce `read_allow_permissive` and `write_allow_permissive` flags in the global rule to override kind whitelists for read or write operations. These flags allow more flexible policy configurations while maintaining blacklist enforcement and preventing conflicting settings. Updated tests and documentation for clarity.
This commit is contained in:
@@ -19,6 +19,7 @@ The policy system provides fine-grained control over event storage and retrieval
|
||||
- [Dynamic Policy Updates](#dynamic-policy-updates)
|
||||
- [Evaluation Order](#evaluation-order)
|
||||
- [Examples](#examples)
|
||||
- [Permissive Mode Examples](#permissive-mode-examples)
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -271,6 +272,38 @@ Validates that tag values match the specified regex patterns. Only validates tag
|
||||
|
||||
See [Follows-Based Whitelisting](#follows-based-whitelisting) for details.
|
||||
|
||||
#### Permissive Mode Overrides
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `read_allow_permissive` | boolean | Override kind whitelist for READ access (reads allowed for all kinds) |
|
||||
| `write_allow_permissive` | boolean | Override kind whitelist for WRITE access (writes use global rule only) |
|
||||
|
||||
These fields, when set on the **global** rule, allow independent control over read and write access relative to the kind whitelist/blacklist:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 5, 7]
|
||||
},
|
||||
"global": {
|
||||
"read_allow_permissive": true,
|
||||
"size_limit": 100000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example:
|
||||
- **READ**: Allowed for ALL kinds (permissive override ignores whitelist)
|
||||
- **WRITE**: Only kinds 1, 3, 5, 7 can be written (whitelist applies)
|
||||
|
||||
**Important constraints:**
|
||||
- These flags only work on the **global** rule (ignored on kind-specific rules)
|
||||
- You cannot enable BOTH `read_allow_permissive` AND `write_allow_permissive` when a kind whitelist/blacklist is configured (this would make the whitelist meaningless)
|
||||
- Blacklists always take precedence—permissive flags do NOT override explicit blacklist entries
|
||||
|
||||
See [Permissive Mode Examples](#permissive-mode-examples) for detailed use cases.
|
||||
|
||||
#### Rate Limiting
|
||||
|
||||
| Field | Type | Unit | Description |
|
||||
@@ -809,6 +842,83 @@ access_allowed = (
|
||||
}
|
||||
```
|
||||
|
||||
### Permissive Mode Examples
|
||||
|
||||
#### Read-Permissive Relay (Write-Restricted)
|
||||
|
||||
Allow anyone to read all events, but restrict writes to specific kinds:
|
||||
|
||||
```json
|
||||
{
|
||||
"default_policy": "allow",
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7, 9735]
|
||||
},
|
||||
"global": {
|
||||
"read_allow_permissive": true,
|
||||
"size_limit": 100000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- **READ**: Any kind can be read (permissive override)
|
||||
- **WRITE**: Only kinds 1, 3, 7, 9735 can be written
|
||||
|
||||
This is useful for relays that want to serve as aggregators (read any event type) but only accept specific event types from clients.
|
||||
|
||||
#### Write-Permissive with Read Restrictions
|
||||
|
||||
Allow writes of any kind (with global constraints), but restrict reads:
|
||||
|
||||
```json
|
||||
{
|
||||
"default_policy": "allow",
|
||||
"kind": {
|
||||
"whitelist": [0, 1, 3]
|
||||
},
|
||||
"global": {
|
||||
"write_allow_permissive": true,
|
||||
"size_limit": 50000,
|
||||
"max_age_of_event": 86400
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- **READ**: Only kinds 0, 1, 3 can be read (whitelist applies)
|
||||
- **WRITE**: Any kind can be written (with size and age limits from global rule)
|
||||
|
||||
This is useful for relays that want to accept any event type but only serve a curated subset.
|
||||
|
||||
#### Archive Relay (Read Any, Accept Specific)
|
||||
|
||||
Perfect for archive/backup relays:
|
||||
|
||||
```json
|
||||
{
|
||||
"default_policy": "allow",
|
||||
"kind": {
|
||||
"whitelist": [0, 1, 3, 4, 7, 30023]
|
||||
},
|
||||
"global": {
|
||||
"read_allow_permissive": true,
|
||||
"size_limit": 500000
|
||||
},
|
||||
"rules": {
|
||||
"30023": {
|
||||
"description": "Long-form articles with validation",
|
||||
"identifier_regex": "^[a-z0-9-]{1,64}$",
|
||||
"max_expiry_duration": "P365D"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- **READ**: All kinds can be read (historical data)
|
||||
- **WRITE**: Only whitelisted kinds accepted, with specific rules for articles
|
||||
|
||||
## Testing
|
||||
|
||||
### Run Policy Tests
|
||||
|
||||
@@ -40,7 +40,7 @@ func BenchmarkCheckKindsPolicy(b *testing.B) {
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.checkKindsPolicy(1)
|
||||
policy.checkKindsPolicy("write", 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,8 +168,8 @@ func TestBugReproduction_DebugPolicyFlow(t *testing.T) {
|
||||
t.Logf("=== Policy Check Flow ===")
|
||||
|
||||
// Step 1: Check kinds policy
|
||||
kindsAllowed := policy.checkKindsPolicy(event.Kind)
|
||||
t.Logf("1. checkKindsPolicy(kind=%d) returned: %v", event.Kind, kindsAllowed)
|
||||
kindsAllowed := policy.checkKindsPolicy("write", event.Kind)
|
||||
t.Logf("1. checkKindsPolicy(access=write, kind=%d) returned: %v", event.Kind, kindsAllowed)
|
||||
|
||||
// Full policy check
|
||||
allowed, err := policy.CheckPolicy("write", event, testPubkey, "127.0.0.1")
|
||||
|
||||
@@ -1351,6 +1351,57 @@ func TestValidateJSONNewFields(t *testing.T) {
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
// Tests for read_allow_permissive and write_allow_permissive
|
||||
{
|
||||
name: "valid read_allow_permissive alone with whitelist",
|
||||
json: `{
|
||||
"kind": {"whitelist": [1, 3, 5]},
|
||||
"global": {"read_allow_permissive": true}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "valid write_allow_permissive alone with whitelist",
|
||||
json: `{
|
||||
"kind": {"whitelist": [1, 3, 5]},
|
||||
"global": {"write_allow_permissive": true}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid both permissive flags with whitelist",
|
||||
json: `{
|
||||
"kind": {"whitelist": [1, 3, 5]},
|
||||
"global": {
|
||||
"read_allow_permissive": true,
|
||||
"write_allow_permissive": true
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMatch: "read_allow_permissive and write_allow_permissive cannot be enabled together",
|
||||
},
|
||||
{
|
||||
name: "invalid both permissive flags with blacklist",
|
||||
json: `{
|
||||
"kind": {"blacklist": [2, 4, 6]},
|
||||
"global": {
|
||||
"read_allow_permissive": true,
|
||||
"write_allow_permissive": true
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMatch: "read_allow_permissive and write_allow_permissive cannot be enabled together",
|
||||
},
|
||||
{
|
||||
name: "valid both permissive flags without any kind restriction",
|
||||
json: `{
|
||||
"global": {
|
||||
"read_allow_permissive": true,
|
||||
"write_allow_permissive": true
|
||||
}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -144,6 +144,23 @@ type Rule struct {
|
||||
// Example: "^[a-z0-9-]{1,64}$" requires lowercase alphanumeric with hyphens, max 64 chars.
|
||||
IdentifierRegex string `json:"identifier_regex,omitempty"`
|
||||
|
||||
// ReadAllowPermissive when set on a GLOBAL rule, allows read access for ALL kinds,
|
||||
// even when a kind whitelist is configured. This allows the kind whitelist to
|
||||
// restrict WRITE operations while keeping reads permissive.
|
||||
// When true:
|
||||
// - READ: Allowed for all kinds (global rule still applies for other read restrictions)
|
||||
// - WRITE: Kind whitelist/blacklist applies as normal
|
||||
// Only meaningful on the Global rule - ignored on kind-specific rules.
|
||||
ReadAllowPermissive bool `json:"read_allow_permissive,omitempty"`
|
||||
|
||||
// WriteAllowPermissive when set on a GLOBAL rule, allows write access for kinds
|
||||
// that don't have specific rules defined, bypassing the implicit kind whitelist.
|
||||
// When true:
|
||||
// - Kinds without specific rules apply global rule constraints only
|
||||
// - Kind whitelist still blocks reads for unlisted kinds (unless ReadAllowPermissive is also set)
|
||||
// Only meaningful on the Global rule - ignored on kind-specific rules.
|
||||
WriteAllowPermissive bool `json:"write_allow_permissive,omitempty"`
|
||||
|
||||
// Binary caches for faster comparison (populated from hex strings above)
|
||||
// These are not exported and not serialized to JSON
|
||||
writeAllowBin [][]byte
|
||||
@@ -178,7 +195,8 @@ func (r *Rule) hasAnyRules() bool {
|
||||
len(r.ReadFollowsWhitelist) > 0 || len(r.WriteFollowsWhitelist) > 0 ||
|
||||
len(r.readFollowsWhitelistBin) > 0 || len(r.writeFollowsWhitelistBin) > 0 ||
|
||||
len(r.TagValidation) > 0 ||
|
||||
r.ProtectedRequired || r.IdentifierRegex != ""
|
||||
r.ProtectedRequired || r.IdentifierRegex != "" ||
|
||||
r.ReadAllowPermissive || r.WriteAllowPermissive
|
||||
}
|
||||
|
||||
// populateBinaryCache converts hex-encoded pubkey strings to binary for faster comparison.
|
||||
@@ -1280,7 +1298,7 @@ func (p *P) CheckPolicy(
|
||||
// ==========================================================================
|
||||
// STEP 1: Check kinds whitelist/blacklist (applies before any rule checks)
|
||||
// ==========================================================================
|
||||
if !p.checkKindsPolicy(ev.Kind) {
|
||||
if !p.checkKindsPolicy(access, ev.Kind) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -1341,19 +1359,32 @@ func (p *P) CheckPolicy(
|
||||
return p.getDefaultPolicyAction(), nil
|
||||
}
|
||||
|
||||
// checkKindsPolicy checks if the event kind is allowed.
|
||||
// checkKindsPolicy checks if the event kind is allowed for the given access type.
|
||||
// Logic:
|
||||
// 1. If explicit whitelist exists, use it (backwards compatibility)
|
||||
// 2. If explicit blacklist exists, use it (backwards compatibility)
|
||||
// 3. Otherwise, kinds with defined rules are implicitly allowed, others denied
|
||||
func (p *P) checkKindsPolicy(kind uint16) bool {
|
||||
// If whitelist is present, only allow whitelisted kinds
|
||||
// 1. If explicit whitelist exists, use it (but respect permissive flags for read/write)
|
||||
// 2. If explicit blacklist exists, use it (but respect permissive flags for read/write)
|
||||
// 3. Otherwise, kinds with defined rules are implicitly allowed, others denied (with permissive overrides)
|
||||
//
|
||||
// Permissive flags (set on Global rule):
|
||||
// - ReadAllowPermissive: Allows READ access for kinds not in whitelist (write still restricted)
|
||||
// - WriteAllowPermissive: Allows WRITE access for kinds not in whitelist (uses global rule constraints)
|
||||
func (p *P) checkKindsPolicy(access string, kind uint16) bool {
|
||||
// If whitelist is present, only allow whitelisted kinds (with permissive overrides)
|
||||
if len(p.Kind.Whitelist) > 0 {
|
||||
for _, allowedKind := range p.Kind.Whitelist {
|
||||
if kind == uint16(allowedKind) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Kind not in whitelist - check permissive flags
|
||||
if access == "read" && p.Global.ReadAllowPermissive {
|
||||
log.D.F("read_allow_permissive: allowing read for kind %d not in whitelist", kind)
|
||||
return true // Allow read even though kind not whitelisted
|
||||
}
|
||||
if access == "write" && p.Global.WriteAllowPermissive {
|
||||
log.D.F("write_allow_permissive: allowing write for kind %d not in whitelist (global rules apply)", kind)
|
||||
return true // Allow write even though kind not whitelisted, global rule will be applied
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1361,12 +1392,25 @@ func (p *P) checkKindsPolicy(kind uint16) bool {
|
||||
if len(p.Kind.Blacklist) > 0 {
|
||||
for _, deniedKind := range p.Kind.Blacklist {
|
||||
if kind == uint16(deniedKind) {
|
||||
// Kind is explicitly blacklisted - permissive flags don't override blacklist
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Not in blacklist - check if rule exists for implicit whitelist
|
||||
_, hasRule := p.rules[int(kind)]
|
||||
return hasRule // Only allow if there's a rule defined
|
||||
if hasRule {
|
||||
return true
|
||||
}
|
||||
// No kind-specific rule - check permissive flags
|
||||
if access == "read" && p.Global.ReadAllowPermissive {
|
||||
log.D.F("read_allow_permissive: allowing read for kind %d (not blacklisted, no rule)", kind)
|
||||
return true
|
||||
}
|
||||
if access == "write" && p.Global.WriteAllowPermissive {
|
||||
log.D.F("write_allow_permissive: allowing write for kind %d (not blacklisted, no rule)", kind)
|
||||
return true
|
||||
}
|
||||
return false // Only allow if there's a rule defined
|
||||
}
|
||||
|
||||
// No explicit whitelist or blacklist
|
||||
@@ -1374,6 +1418,7 @@ func (p *P) checkKindsPolicy(kind uint16) bool {
|
||||
// - If default_policy is explicitly "allow", allow all kinds (rules add constraints, not restrictions)
|
||||
// - If default_policy is unset or "deny", use implicit whitelist (only allow kinds with rules)
|
||||
// - If global rule has any configuration, allow kinds through for global rule checking
|
||||
// - Permissive flags can override implicit whitelist behavior
|
||||
if len(p.rules) > 0 {
|
||||
// If default_policy is explicitly "allow", don't use implicit whitelist
|
||||
if p.DefaultPolicy == "allow" {
|
||||
@@ -1388,6 +1433,15 @@ func (p *P) checkKindsPolicy(kind uint16) bool {
|
||||
if p.Global.hasAnyRules() {
|
||||
return true // Allow through for global rule check
|
||||
}
|
||||
// Check permissive flags for implicit whitelist override
|
||||
if access == "read" && p.Global.ReadAllowPermissive {
|
||||
log.D.F("read_allow_permissive: allowing read for kind %d (implicit whitelist override)", kind)
|
||||
return true
|
||||
}
|
||||
if access == "write" && p.Global.WriteAllowPermissive {
|
||||
log.D.F("write_allow_permissive: allowing write for kind %d (implicit whitelist override)", kind)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
// No kind-specific rules - check if global rule exists
|
||||
@@ -2052,6 +2106,13 @@ func (p *P) ValidateJSON(policyJSON []byte) error {
|
||||
return fmt.Errorf("invalid default_policy value: %q (must be \"allow\" or \"deny\")", tempPolicy.DefaultPolicy)
|
||||
}
|
||||
|
||||
// Validate permissive flags: if both read_allow_permissive AND write_allow_permissive are set
|
||||
// with a kind whitelist or blacklist, this makes the whitelist/blacklist meaningless
|
||||
hasKindRestriction := len(tempPolicy.Kind.Whitelist) > 0 || len(tempPolicy.Kind.Blacklist) > 0
|
||||
if hasKindRestriction && tempPolicy.Global.ReadAllowPermissive && tempPolicy.Global.WriteAllowPermissive {
|
||||
return fmt.Errorf("invalid policy: both read_allow_permissive and write_allow_permissive cannot be enabled together with a kind whitelist or blacklist (this would make the kind restriction meaningless)")
|
||||
}
|
||||
|
||||
log.D.F("policy JSON validation passed")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
policy *P
|
||||
access string // "read" or "write"
|
||||
kind uint16
|
||||
expected bool
|
||||
}{
|
||||
@@ -155,6 +156,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
Kind: Kinds{},
|
||||
rules: map[int]Rule{}, // No rules defined
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: true, // Should be allowed (no rules = allow all kinds)
|
||||
},
|
||||
@@ -166,6 +168,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
2: {Description: "Rule for kind 2"},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: false, // Should be denied (implicit whitelist, no rule for kind 1)
|
||||
},
|
||||
@@ -177,6 +180,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
1: {Description: "Rule for kind 1"},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: true, // Should be allowed (has rule)
|
||||
},
|
||||
@@ -189,6 +193,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
},
|
||||
rules: map[int]Rule{}, // No specific rules
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: true, // Should be allowed (global rule exists)
|
||||
},
|
||||
@@ -199,6 +204,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: true,
|
||||
},
|
||||
@@ -209,6 +215,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 2,
|
||||
expected: false,
|
||||
},
|
||||
@@ -222,6 +229,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
3: {Description: "Rule for kind 3"}, // Has at least one rule
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: false, // Should be denied (not blacklisted but no rule for kind 1)
|
||||
},
|
||||
@@ -235,6 +243,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
1: {Description: "Rule for kind 1"},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: true, // Should be allowed (not blacklisted and has rule)
|
||||
},
|
||||
@@ -245,6 +254,7 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
Blacklist: []int{2, 4, 6},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 2,
|
||||
expected: false,
|
||||
},
|
||||
@@ -256,14 +266,87 @@ func TestCheckKindsPolicy(t *testing.T) {
|
||||
Blacklist: []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 1,
|
||||
expected: true,
|
||||
},
|
||||
// Tests for new permissive flags
|
||||
{
|
||||
name: "read_allow_permissive - allows read for non-whitelisted kind",
|
||||
policy: &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
Global: Rule{
|
||||
ReadAllowPermissive: true,
|
||||
},
|
||||
},
|
||||
access: "read",
|
||||
kind: 2,
|
||||
expected: true, // Should be allowed (read permissive overrides whitelist)
|
||||
},
|
||||
{
|
||||
name: "read_allow_permissive - write still blocked for non-whitelisted kind",
|
||||
policy: &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
Global: Rule{
|
||||
ReadAllowPermissive: true,
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 2,
|
||||
expected: false, // Should be denied (only read is permissive)
|
||||
},
|
||||
{
|
||||
name: "write_allow_permissive - allows write for non-whitelisted kind",
|
||||
policy: &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
Global: Rule{
|
||||
WriteAllowPermissive: true,
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 2,
|
||||
expected: true, // Should be allowed (write permissive overrides whitelist)
|
||||
},
|
||||
{
|
||||
name: "write_allow_permissive - read still blocked for non-whitelisted kind",
|
||||
policy: &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
Global: Rule{
|
||||
WriteAllowPermissive: true,
|
||||
},
|
||||
},
|
||||
access: "read",
|
||||
kind: 2,
|
||||
expected: false, // Should be denied (only write is permissive)
|
||||
},
|
||||
{
|
||||
name: "blacklist - permissive flags do NOT override blacklist",
|
||||
policy: &P{
|
||||
Kind: Kinds{
|
||||
Blacklist: []int{2, 4, 6},
|
||||
},
|
||||
Global: Rule{
|
||||
ReadAllowPermissive: true,
|
||||
WriteAllowPermissive: true,
|
||||
},
|
||||
},
|
||||
access: "write",
|
||||
kind: 2,
|
||||
expected: false, // Should be denied (blacklist always applies)
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := tt.policy.checkKindsPolicy(tt.kind)
|
||||
result := tt.policy.checkKindsPolicy(tt.access, tt.kind)
|
||||
if result != tt.expected {
|
||||
t.Errorf("Expected %v, got %v", tt.expected, result)
|
||||
}
|
||||
@@ -996,19 +1079,19 @@ func TestEdgeCasesWhitelistBlacklistConflict(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test kind in both whitelist and blacklist - whitelist should win
|
||||
allowed := policy.checkKindsPolicy(1)
|
||||
allowed := policy.checkKindsPolicy("write", 1)
|
||||
if !allowed {
|
||||
t.Error("Expected whitelist to override blacklist")
|
||||
}
|
||||
|
||||
// Test kind in blacklist but not whitelist
|
||||
allowed = policy.checkKindsPolicy(2)
|
||||
allowed = policy.checkKindsPolicy("write", 2)
|
||||
if allowed {
|
||||
t.Error("Expected kind in blacklist but not whitelist to be blocked")
|
||||
}
|
||||
|
||||
// Test kind in whitelist but not blacklist
|
||||
allowed = policy.checkKindsPolicy(5)
|
||||
allowed = policy.checkKindsPolicy("write", 5)
|
||||
if !allowed {
|
||||
t.Error("Expected kind in whitelist to be allowed")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user