default_permissive_test.go raw
1 package policy
2
3 import (
4 "testing"
5 "time"
6
7 "next.orly.dev/pkg/nostr/encoders/event"
8 "next.orly.dev/pkg/nostr/encoders/hex"
9 "next.orly.dev/pkg/nostr/encoders/tag"
10 "next.orly.dev/pkg/nostr/interfaces/signer/p8k"
11 "next.orly.dev/pkg/lol/chk"
12 )
13
14 // =============================================================================
15 // Default-Permissive Access Control Tests
16 // =============================================================================
17
18 // TestDefaultPermissiveRead tests that read access is allowed by default
19 // when no read restrictions are configured.
20 func TestDefaultPermissiveRead(t *testing.T) {
21 // No read restrictions configured
22 policyJSON := []byte(`{
23 "default_policy": "deny",
24 "rules": {
25 "1": {
26 "description": "No read restrictions"
27 }
28 }
29 }`)
30
31 policy, err := New(policyJSON)
32 if err != nil {
33 t.Fatalf("Failed to create policy: %v", err)
34 }
35
36 authorSigner, authorPubkey := generateTestKeypair(t)
37 _, readerPubkey := generateTestKeypair(t)
38 _, randomPubkey := generateTestKeypair(t)
39
40 ev := createTestEvent(t, authorSigner, "test content", 1)
41
42 tests := []struct {
43 name string
44 pubkey []byte
45 expectAllow bool
46 }{
47 {
48 name: "author can read (default permissive)",
49 pubkey: authorPubkey,
50 expectAllow: true,
51 },
52 {
53 name: "reader can read (default permissive)",
54 pubkey: readerPubkey,
55 expectAllow: true,
56 },
57 {
58 name: "random user can read (default permissive)",
59 pubkey: randomPubkey,
60 expectAllow: true,
61 },
62 {
63 name: "nil pubkey can read (default permissive)",
64 pubkey: nil,
65 expectAllow: true,
66 },
67 }
68
69 for _, tt := range tests {
70 t.Run(tt.name, func(t *testing.T) {
71 allowed, err := policy.CheckPolicy("read", ev, tt.pubkey, "127.0.0.1")
72 if err != nil {
73 t.Fatalf("CheckPolicy error: %v", err)
74 }
75 if allowed != tt.expectAllow {
76 t.Errorf("CheckPolicy() = %v, expected %v", allowed, tt.expectAllow)
77 }
78 })
79 }
80 }
81
82 // TestDefaultPermissiveWrite tests that write access is allowed by default
83 // when no write restrictions are configured.
84 func TestDefaultPermissiveWrite(t *testing.T) {
85 // No write restrictions configured
86 policyJSON := []byte(`{
87 "default_policy": "deny",
88 "rules": {
89 "1": {
90 "description": "No write restrictions"
91 }
92 }
93 }`)
94
95 policy, err := New(policyJSON)
96 if err != nil {
97 t.Fatalf("Failed to create policy: %v", err)
98 }
99
100 writerSigner, writerPubkey := generateTestKeypair(t)
101 _, randomPubkey := generateTestKeypair(t)
102
103 tests := []struct {
104 name string
105 signer *p8k.Signer
106 pubkey []byte
107 expectAllow bool
108 }{
109 {
110 name: "writer can write (default permissive)",
111 signer: writerSigner,
112 pubkey: writerPubkey,
113 expectAllow: true,
114 },
115 {
116 name: "random user can write (default permissive)",
117 signer: writerSigner,
118 pubkey: randomPubkey,
119 expectAllow: true,
120 },
121 }
122
123 for _, tt := range tests {
124 t.Run(tt.name, func(t *testing.T) {
125 ev := createTestEvent(t, tt.signer, "test content", 1)
126 allowed, err := policy.CheckPolicy("write", ev, tt.pubkey, "127.0.0.1")
127 if err != nil {
128 t.Fatalf("CheckPolicy error: %v", err)
129 }
130 if allowed != tt.expectAllow {
131 t.Errorf("CheckPolicy() = %v, expected %v", allowed, tt.expectAllow)
132 }
133 })
134 }
135 }
136
137 // TestReadFollowsWhitelist tests the read_follows_whitelist field.
138 func TestReadFollowsWhitelist(t *testing.T) {
139 _, curatorPubkey := generateTestKeypair(t)
140 _, followedPubkey := generateTestKeypair(t)
141 _, unfollowedPubkey := generateTestKeypair(t)
142 authorSigner, authorPubkey := generateTestKeypair(t)
143
144 curatorHex := hex.Enc(curatorPubkey)
145
146 policyJSON := []byte(`{
147 "default_policy": "deny",
148 "rules": {
149 "1": {
150 "description": "Only curator follows can read",
151 "read_follows_whitelist": ["` + curatorHex + `"]
152 }
153 }
154 }`)
155
156 policy, err := New(policyJSON)
157 if err != nil {
158 t.Fatalf("Failed to create policy: %v", err)
159 }
160
161 // Simulate loading curator's follows (includes followed user and curator themselves)
162 policy.UpdateRuleReadFollowsWhitelist(1, [][]byte{followedPubkey})
163
164 ev := createTestEvent(t, authorSigner, "test content", 1)
165
166 tests := []struct {
167 name string
168 pubkey []byte
169 expectAllow bool
170 }{
171 {
172 name: "curator can read (is in whitelist pubkeys)",
173 pubkey: curatorPubkey,
174 expectAllow: true,
175 },
176 {
177 name: "followed user can read",
178 pubkey: followedPubkey,
179 expectAllow: true,
180 },
181 {
182 name: "unfollowed user denied",
183 pubkey: unfollowedPubkey,
184 expectAllow: false,
185 },
186 {
187 name: "author cannot read (not in follows)",
188 pubkey: authorPubkey,
189 expectAllow: false,
190 },
191 {
192 name: "nil pubkey denied",
193 pubkey: nil,
194 expectAllow: false,
195 },
196 }
197
198 for _, tt := range tests {
199 t.Run(tt.name, func(t *testing.T) {
200 allowed, err := policy.CheckPolicy("read", ev, tt.pubkey, "127.0.0.1")
201 if err != nil {
202 t.Fatalf("CheckPolicy error: %v", err)
203 }
204 if allowed != tt.expectAllow {
205 t.Errorf("CheckPolicy() = %v, expected %v", allowed, tt.expectAllow)
206 }
207 })
208 }
209
210 // Verify write is still default-permissive (no write restriction)
211 t.Run("write is still default permissive", func(t *testing.T) {
212 allowed, err := policy.CheckPolicy("write", ev, unfollowedPubkey, "127.0.0.1")
213 if err != nil {
214 t.Fatalf("CheckPolicy error: %v", err)
215 }
216 if !allowed {
217 t.Error("Expected write to be allowed (no write restriction)")
218 }
219 })
220 }
221
222 // TestWriteFollowsWhitelist tests the write_follows_whitelist field.
223 func TestWriteFollowsWhitelist(t *testing.T) {
224 moderatorSigner, moderatorPubkey := generateTestKeypair(t)
225 followedSigner, followedPubkey := generateTestKeypair(t)
226 unfollowedSigner, unfollowedPubkey := generateTestKeypair(t)
227
228 moderatorHex := hex.Enc(moderatorPubkey)
229
230 policyJSON := []byte(`{
231 "default_policy": "deny",
232 "rules": {
233 "1": {
234 "description": "Only moderator follows can write",
235 "write_follows_whitelist": ["` + moderatorHex + `"]
236 }
237 }
238 }`)
239
240 policy, err := New(policyJSON)
241 if err != nil {
242 t.Fatalf("Failed to create policy: %v", err)
243 }
244
245 // Simulate loading moderator's follows
246 policy.UpdateRuleWriteFollowsWhitelist(1, [][]byte{followedPubkey})
247
248 tests := []struct {
249 name string
250 signer *p8k.Signer
251 pubkey []byte
252 expectAllow bool
253 }{
254 {
255 name: "moderator can write (is in whitelist pubkeys)",
256 signer: moderatorSigner,
257 pubkey: moderatorPubkey,
258 expectAllow: true,
259 },
260 {
261 name: "followed user can write",
262 signer: followedSigner,
263 pubkey: followedPubkey,
264 expectAllow: true,
265 },
266 {
267 name: "unfollowed user denied",
268 signer: unfollowedSigner,
269 pubkey: unfollowedPubkey,
270 expectAllow: false,
271 },
272 }
273
274 for _, tt := range tests {
275 t.Run(tt.name, func(t *testing.T) {
276 ev := createTestEvent(t, tt.signer, "test content", 1)
277 allowed, err := policy.CheckPolicy("write", ev, tt.pubkey, "127.0.0.1")
278 if err != nil {
279 t.Fatalf("CheckPolicy error: %v", err)
280 }
281 if allowed != tt.expectAllow {
282 t.Errorf("CheckPolicy() = %v, expected %v", allowed, tt.expectAllow)
283 }
284 })
285 }
286
287 // Verify read is still default-permissive (no read restriction)
288 t.Run("read is still default permissive", func(t *testing.T) {
289 ev := createTestEvent(t, unfollowedSigner, "test content", 1)
290 allowed, err := policy.CheckPolicy("read", ev, unfollowedPubkey, "127.0.0.1")
291 if err != nil {
292 t.Fatalf("CheckPolicy error: %v", err)
293 }
294 if !allowed {
295 t.Error("Expected read to be allowed (no read restriction)")
296 }
297 })
298 }
299
300 // TestGlobalReadFollowsWhitelist tests read_follows_whitelist in global rule.
301 func TestGlobalReadFollowsWhitelist(t *testing.T) {
302 _, curatorPubkey := generateTestKeypair(t)
303 _, followedPubkey := generateTestKeypair(t)
304 _, unfollowedPubkey := generateTestKeypair(t)
305 authorSigner, _ := generateTestKeypair(t)
306
307 curatorHex := hex.Enc(curatorPubkey)
308
309 policyJSON := []byte(`{
310 "default_policy": "deny",
311 "global": {
312 "description": "Global read follows whitelist",
313 "read_follows_whitelist": ["` + curatorHex + `"]
314 }
315 }`)
316
317 policy, err := New(policyJSON)
318 if err != nil {
319 t.Fatalf("Failed to create policy: %v", err)
320 }
321
322 // Update global read follows whitelist
323 policy.UpdateGlobalReadFollowsWhitelist([][]byte{followedPubkey})
324
325 // Test with kind 1
326 t.Run("kind 1", func(t *testing.T) {
327 ev := createTestEvent(t, authorSigner, "test content", 1)
328
329 // Followed user can read
330 allowed, err := policy.CheckPolicy("read", ev, followedPubkey, "127.0.0.1")
331 if err != nil {
332 t.Fatalf("CheckPolicy error: %v", err)
333 }
334 if !allowed {
335 t.Error("Expected followed user to be allowed to read")
336 }
337
338 // Unfollowed user denied
339 allowed, err = policy.CheckPolicy("read", ev, unfollowedPubkey, "127.0.0.1")
340 if err != nil {
341 t.Fatalf("CheckPolicy error: %v", err)
342 }
343 if allowed {
344 t.Error("Expected unfollowed user to be denied")
345 }
346 })
347 }
348
349 // TestGlobalWriteFollowsWhitelist tests write_follows_whitelist in global rule.
350 func TestGlobalWriteFollowsWhitelist(t *testing.T) {
351 _, moderatorPubkey := generateTestKeypair(t)
352 followedSigner, followedPubkey := generateTestKeypair(t)
353 unfollowedSigner, unfollowedPubkey := generateTestKeypair(t)
354
355 moderatorHex := hex.Enc(moderatorPubkey)
356
357 policyJSON := []byte(`{
358 "default_policy": "deny",
359 "global": {
360 "description": "Global write follows whitelist",
361 "write_follows_whitelist": ["` + moderatorHex + `"]
362 }
363 }`)
364
365 policy, err := New(policyJSON)
366 if err != nil {
367 t.Fatalf("Failed to create policy: %v", err)
368 }
369
370 // Update global write follows whitelist
371 policy.UpdateGlobalWriteFollowsWhitelist([][]byte{followedPubkey})
372
373 // Test with kind 1
374 t.Run("kind 1", func(t *testing.T) {
375 // Followed user can write
376 ev := createTestEvent(t, followedSigner, "test content", 1)
377 allowed, err := policy.CheckPolicy("write", ev, followedPubkey, "127.0.0.1")
378 if err != nil {
379 t.Fatalf("CheckPolicy error: %v", err)
380 }
381 if !allowed {
382 t.Error("Expected followed user to be allowed to write")
383 }
384
385 // Unfollowed user denied
386 ev = createTestEvent(t, unfollowedSigner, "test content", 1)
387 allowed, err = policy.CheckPolicy("write", ev, unfollowedPubkey, "127.0.0.1")
388 if err != nil {
389 t.Fatalf("CheckPolicy error: %v", err)
390 }
391 if allowed {
392 t.Error("Expected unfollowed user to be denied")
393 }
394 })
395 }
396
397 // TestPrivilegedOnlyAppliesToReadDP tests that privileged only affects read access.
398 func TestPrivilegedOnlyAppliesToReadDP(t *testing.T) {
399 authorSigner, authorPubkey := generateTestKeypair(t)
400 _, recipientPubkey := generateTestKeypair(t)
401 thirdPartySigner, thirdPartyPubkey := generateTestKeypair(t)
402
403 policyJSON := []byte(`{
404 "default_policy": "deny",
405 "rules": {
406 "4": {
407 "description": "Encrypted DMs - privileged",
408 "privileged": true
409 }
410 }
411 }`)
412
413 policy, err := New(policyJSON)
414 if err != nil {
415 t.Fatalf("Failed to create policy: %v", err)
416 }
417
418 // Create event with p-tag for recipient
419 ev := event.New()
420 ev.Kind = 4
421 ev.Content = []byte("encrypted content")
422 ev.CreatedAt = time.Now().Unix()
423 ev.Tags = tag.NewS()
424 pTag := tag.NewFromAny("p", hex.Enc(recipientPubkey))
425 ev.Tags.Append(pTag)
426 if err := ev.Sign(authorSigner); chk.E(err) {
427 t.Fatalf("Failed to sign event: %v", err)
428 }
429
430 // READ tests
431 t.Run("author can read", func(t *testing.T) {
432 allowed, err := policy.CheckPolicy("read", ev, authorPubkey, "127.0.0.1")
433 if err != nil {
434 t.Fatalf("CheckPolicy error: %v", err)
435 }
436 if !allowed {
437 t.Error("Expected author to be allowed to read")
438 }
439 })
440
441 t.Run("recipient can read", func(t *testing.T) {
442 allowed, err := policy.CheckPolicy("read", ev, recipientPubkey, "127.0.0.1")
443 if err != nil {
444 t.Fatalf("CheckPolicy error: %v", err)
445 }
446 if !allowed {
447 t.Error("Expected recipient to be allowed to read")
448 }
449 })
450
451 t.Run("third party cannot read", func(t *testing.T) {
452 allowed, err := policy.CheckPolicy("read", ev, thirdPartyPubkey, "127.0.0.1")
453 if err != nil {
454 t.Fatalf("CheckPolicy error: %v", err)
455 }
456 if allowed {
457 t.Error("Expected third party to be denied read access")
458 }
459 })
460
461 // WRITE tests - privileged should NOT affect write
462 t.Run("third party CAN write (privileged doesn't affect write)", func(t *testing.T) {
463 ev := createTestEvent(t, thirdPartySigner, "test content", 4)
464 allowed, err := policy.CheckPolicy("write", ev, thirdPartyPubkey, "127.0.0.1")
465 if err != nil {
466 t.Fatalf("CheckPolicy error: %v", err)
467 }
468 if !allowed {
469 t.Error("Expected third party to be allowed to write (privileged doesn't restrict write)")
470 }
471 })
472 }
473
474 // TestCombinedReadWriteFollowsWhitelists tests using both whitelists on same rule.
475 func TestCombinedReadWriteFollowsWhitelists(t *testing.T) {
476 _, curatorPubkey := generateTestKeypair(t)
477 _, moderatorPubkey := generateTestKeypair(t)
478 readerSigner, readerPubkey := generateTestKeypair(t)
479 writerSigner, writerPubkey := generateTestKeypair(t)
480 _, outsiderPubkey := generateTestKeypair(t)
481
482 curatorHex := hex.Enc(curatorPubkey)
483 moderatorHex := hex.Enc(moderatorPubkey)
484
485 policyJSON := []byte(`{
486 "default_policy": "deny",
487 "rules": {
488 "30023": {
489 "description": "Articles - different read/write follows",
490 "read_follows_whitelist": ["` + curatorHex + `"],
491 "write_follows_whitelist": ["` + moderatorHex + `"]
492 }
493 }
494 }`)
495
496 policy, err := New(policyJSON)
497 if err != nil {
498 t.Fatalf("Failed to create policy: %v", err)
499 }
500
501 // Curator follows reader, moderator follows writer
502 policy.UpdateRuleReadFollowsWhitelist(30023, [][]byte{readerPubkey})
503 policy.UpdateRuleWriteFollowsWhitelist(30023, [][]byte{writerPubkey})
504
505 tests := []struct {
506 name string
507 access string
508 signer *p8k.Signer
509 pubkey []byte
510 expectAllow bool
511 }{
512 // Read tests
513 {
514 name: "reader can read",
515 access: "read",
516 signer: readerSigner,
517 pubkey: readerPubkey,
518 expectAllow: true,
519 },
520 {
521 name: "writer cannot read (not in read follows)",
522 access: "read",
523 signer: writerSigner,
524 pubkey: writerPubkey,
525 expectAllow: false,
526 },
527 {
528 name: "outsider cannot read",
529 access: "read",
530 signer: readerSigner,
531 pubkey: outsiderPubkey,
532 expectAllow: false,
533 },
534 // Write tests
535 {
536 name: "writer can write",
537 access: "write",
538 signer: writerSigner,
539 pubkey: writerPubkey,
540 expectAllow: true,
541 },
542 {
543 name: "reader cannot write (not in write follows)",
544 access: "write",
545 signer: readerSigner,
546 pubkey: readerPubkey,
547 expectAllow: false,
548 },
549 {
550 name: "outsider cannot write",
551 access: "write",
552 signer: readerSigner,
553 pubkey: outsiderPubkey,
554 expectAllow: false,
555 },
556 }
557
558 for _, tt := range tests {
559 t.Run(tt.name, func(t *testing.T) {
560 ev := createTestEvent(t, tt.signer, "test content", 30023)
561 allowed, err := policy.CheckPolicy(tt.access, ev, tt.pubkey, "127.0.0.1")
562 if err != nil {
563 t.Fatalf("CheckPolicy error: %v", err)
564 }
565 if allowed != tt.expectAllow {
566 t.Errorf("CheckPolicy() = %v, expected %v", allowed, tt.expectAllow)
567 }
568 })
569 }
570 }
571
572 // TestReadAllowWithReadFollowsWhitelist tests combining read_allow and read_follows_whitelist.
573 func TestReadAllowWithReadFollowsWhitelist(t *testing.T) {
574 _, curatorPubkey := generateTestKeypair(t)
575 _, followedPubkey := generateTestKeypair(t)
576 _, explicitPubkey := generateTestKeypair(t)
577 _, outsiderPubkey := generateTestKeypair(t)
578 authorSigner, _ := generateTestKeypair(t)
579
580 curatorHex := hex.Enc(curatorPubkey)
581 explicitHex := hex.Enc(explicitPubkey)
582
583 policyJSON := []byte(`{
584 "default_policy": "deny",
585 "rules": {
586 "1": {
587 "description": "Read via follows OR explicit allow",
588 "read_follows_whitelist": ["` + curatorHex + `"],
589 "read_allow": ["` + explicitHex + `"]
590 }
591 }
592 }`)
593
594 policy, err := New(policyJSON)
595 if err != nil {
596 t.Fatalf("Failed to create policy: %v", err)
597 }
598
599 policy.UpdateRuleReadFollowsWhitelist(1, [][]byte{followedPubkey})
600
601 ev := createTestEvent(t, authorSigner, "test content", 1)
602
603 tests := []struct {
604 name string
605 pubkey []byte
606 expectAllow bool
607 }{
608 {
609 name: "followed user can read",
610 pubkey: followedPubkey,
611 expectAllow: true,
612 },
613 {
614 name: "explicit allow user can read",
615 pubkey: explicitPubkey,
616 expectAllow: true,
617 },
618 {
619 name: "curator can read (is whitelist pubkey)",
620 pubkey: curatorPubkey,
621 expectAllow: true,
622 },
623 {
624 name: "outsider denied",
625 pubkey: outsiderPubkey,
626 expectAllow: false,
627 },
628 }
629
630 for _, tt := range tests {
631 t.Run(tt.name, func(t *testing.T) {
632 allowed, err := policy.CheckPolicy("read", ev, tt.pubkey, "127.0.0.1")
633 if err != nil {
634 t.Fatalf("CheckPolicy error: %v", err)
635 }
636 if allowed != tt.expectAllow {
637 t.Errorf("CheckPolicy() = %v, expected %v", allowed, tt.expectAllow)
638 }
639 })
640 }
641 }
642
643 // TestGetAllFollowsWhitelistPubkeysDP tests the combined pubkey retrieval.
644 func TestGetAllFollowsWhitelistPubkeysDP(t *testing.T) {
645 read1 := "1111111111111111111111111111111111111111111111111111111111111111"
646 read2 := "2222222222222222222222222222222222222222222222222222222222222222"
647 write1 := "3333333333333333333333333333333333333333333333333333333333333333"
648 legacy := "4444444444444444444444444444444444444444444444444444444444444444"
649
650 policyJSON := []byte(`{
651 "default_policy": "allow",
652 "global": {
653 "read_follows_whitelist": ["` + read1 + `"],
654 "write_follows_whitelist": ["` + write1 + `"]
655 },
656 "rules": {
657 "1": {
658 "read_follows_whitelist": ["` + read2 + `"],
659 "follows_whitelist_admins": ["` + legacy + `"]
660 }
661 }
662 }`)
663
664 policy, err := New(policyJSON)
665 if err != nil {
666 t.Fatalf("Failed to create policy: %v", err)
667 }
668
669 allPubkeys := policy.GetAllFollowsWhitelistPubkeys()
670 if len(allPubkeys) != 4 {
671 t.Errorf("Expected 4 unique pubkeys, got %d", len(allPubkeys))
672 }
673
674 // Check each is present
675 pubkeySet := make(map[string]bool)
676 for _, pk := range allPubkeys {
677 pubkeySet[pk] = true
678 }
679
680 expected := []string{read1, read2, write1, legacy}
681 for _, exp := range expected {
682 if !pubkeySet[exp] {
683 t.Errorf("Expected pubkey %s not found", exp)
684 }
685 }
686 }
687
688 // TestWriteAllowIfTagged tests the write_allow_if_tagged field.
689 func TestWriteAllowIfTagged(t *testing.T) {
690 // Group A: unrestricted writers
691 groupASigner, groupAPubkey := generateTestKeypair(t)
692 groupAHex := hex.Enc(groupAPubkey)
693
694 // Group B: can only write if they p-tag a Group A member
695 groupBSigner, groupBPubkey := generateTestKeypair(t)
696
697 // Random user: no special access
698 randomSigner, randomPubkey := generateTestKeypair(t)
699
700 policyJSON := []byte(`{
701 "default_policy": "deny",
702 "kind": { "whitelist": [1] },
703 "rules": {
704 "1": {
705 "description": "Group A writes freely, others must tag Group A",
706 "write_allow": ["` + groupAHex + `"],
707 "write_allow_if_tagged": ["` + groupAHex + `"]
708 }
709 }
710 }`)
711
712 pol, err := New(policyJSON)
713 if err != nil {
714 t.Fatalf("Failed to create policy: %v", err)
715 }
716
717 t.Run("group_A_writes_freely", func(t *testing.T) {
718 ev := createTestEvent(t, groupASigner, "hello", 1)
719 allowed, err := pol.CheckPolicy("write", ev, groupAPubkey, "127.0.0.1")
720 if err != nil {
721 t.Fatalf("CheckPolicy error: %v", err)
722 }
723 if !allowed {
724 t.Error("Group A pubkey should be allowed to write freely")
725 }
726 })
727
728 t.Run("group_B_with_p_tag_allowed", func(t *testing.T) {
729 ev := createTestEvent(t, groupBSigner, "replying to group A", 1)
730 addPTag(ev, groupAPubkey)
731 allowed, err := pol.CheckPolicy("write", ev, groupBPubkey, "127.0.0.1")
732 if err != nil {
733 t.Fatalf("CheckPolicy error: %v", err)
734 }
735 if !allowed {
736 t.Error("Group B pubkey with p-tag to Group A should be allowed")
737 }
738 })
739
740 t.Run("group_B_without_p_tag_denied", func(t *testing.T) {
741 ev := createTestEvent(t, groupBSigner, "no tag", 1)
742 allowed, err := pol.CheckPolicy("write", ev, groupBPubkey, "127.0.0.1")
743 if err != nil {
744 t.Fatalf("CheckPolicy error: %v", err)
745 }
746 if allowed {
747 t.Error("Group B pubkey without p-tag should be denied")
748 }
749 })
750
751 t.Run("random_user_with_p_tag_allowed", func(t *testing.T) {
752 ev := createTestEvent(t, randomSigner, "mentioning group A", 1)
753 addPTag(ev, groupAPubkey)
754 allowed, err := pol.CheckPolicy("write", ev, randomPubkey, "127.0.0.1")
755 if err != nil {
756 t.Fatalf("CheckPolicy error: %v", err)
757 }
758 if !allowed {
759 t.Error("Random user with p-tag to Group A should be allowed")
760 }
761 })
762
763 t.Run("random_user_without_p_tag_denied", func(t *testing.T) {
764 ev := createTestEvent(t, randomSigner, "no tag", 1)
765 allowed, err := pol.CheckPolicy("write", ev, randomPubkey, "127.0.0.1")
766 if err != nil {
767 t.Fatalf("CheckPolicy error: %v", err)
768 }
769 if allowed {
770 t.Error("Random user without p-tag should be denied")
771 }
772 })
773 }
774
775 // TestWriteAllowIfTaggedStandalone tests write_allow_if_tagged without write_allow.
776 func TestWriteAllowIfTaggedStandalone(t *testing.T) {
777 _, gatePubkey := generateTestKeypair(t)
778 gateHex := hex.Enc(gatePubkey)
779
780 writerSigner, writerPubkey := generateTestKeypair(t)
781
782 policyJSON := []byte(`{
783 "default_policy": "deny",
784 "kind": { "whitelist": [1] },
785 "rules": {
786 "1": {
787 "description": "Anyone can write if they tag the gate pubkey",
788 "write_allow_if_tagged": ["` + gateHex + `"]
789 }
790 }
791 }`)
792
793 pol, err := New(policyJSON)
794 if err != nil {
795 t.Fatalf("Failed to create policy: %v", err)
796 }
797
798 t.Run("with_tag_allowed", func(t *testing.T) {
799 ev := createTestEvent(t, writerSigner, "tagged", 1)
800 addPTag(ev, gatePubkey)
801 allowed, err := pol.CheckPolicy("write", ev, writerPubkey, "127.0.0.1")
802 if err != nil {
803 t.Fatalf("CheckPolicy error: %v", err)
804 }
805 if !allowed {
806 t.Error("Should be allowed when tagging gate pubkey")
807 }
808 })
809
810 t.Run("without_tag_denied", func(t *testing.T) {
811 ev := createTestEvent(t, writerSigner, "no tag", 1)
812 allowed, err := pol.CheckPolicy("write", ev, writerPubkey, "127.0.0.1")
813 if err != nil {
814 t.Fatalf("CheckPolicy error: %v", err)
815 }
816 if allowed {
817 t.Error("Should be denied without tagging gate pubkey")
818 }
819 })
820 }
821