forked from coracle/zooid
Update tests
This commit is contained in:
+42
-19
@@ -11,10 +11,9 @@ func TestConfig_IsOwner(t *testing.T) {
|
|||||||
otherPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
otherPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Self: struct {
|
Info: struct {
|
||||||
Name string `toml:"name"`
|
Name string `toml:"name"`
|
||||||
Icon string `toml:"icon"`
|
Icon string `toml:"icon"`
|
||||||
Schema string `toml:"schema"`
|
|
||||||
Secret string `toml:"secret"`
|
Secret string `toml:"secret"`
|
||||||
Pubkey string `toml:"pubkey"`
|
Pubkey string `toml:"pubkey"`
|
||||||
Description string `toml:"description"`
|
Description string `toml:"description"`
|
||||||
@@ -38,16 +37,7 @@ func TestConfig_IsSelf(t *testing.T) {
|
|||||||
otherPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
otherPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Self: struct {
|
secret: secret,
|
||||||
Name string `toml:"name"`
|
|
||||||
Icon string `toml:"icon"`
|
|
||||||
Schema string `toml:"schema"`
|
|
||||||
Secret string `toml:"secret"`
|
|
||||||
Pubkey string `toml:"pubkey"`
|
|
||||||
Description string `toml:"description"`
|
|
||||||
}{
|
|
||||||
Secret: secret.Hex(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.IsSelf(selfPubkey) {
|
if !config.IsSelf(selfPubkey) {
|
||||||
@@ -59,7 +49,7 @@ func TestConfig_IsSelf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_GetRolesForPubkey(t *testing.T) {
|
func TestConfig_GetAllRoles(t *testing.T) {
|
||||||
pubkey1 := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
pubkey1 := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
||||||
pubkey2 := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
pubkey2 := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
||||||
|
|
||||||
@@ -80,22 +70,33 @@ func TestConfig_GetRolesForPubkey(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
roles := config.GetRolesForPubkey(pubkey1)
|
roles := config.GetAllRoles(pubkey1)
|
||||||
if len(roles) != 2 {
|
if len(roles) != 2 {
|
||||||
t.Errorf("GetRolesForPubkey() returned %d roles, want 2", len(roles))
|
t.Errorf("GetAllRoles() returned %d roles, want 2", len(roles))
|
||||||
}
|
}
|
||||||
|
|
||||||
roles = config.GetRolesForPubkey(pubkey2)
|
roles = config.GetAllRoles(pubkey2)
|
||||||
if len(roles) != 2 {
|
if len(roles) != 2 {
|
||||||
t.Errorf("GetRolesForPubkey() returned %d roles, want 2", len(roles))
|
t.Errorf("GetAllRoles() returned %d roles, want 2", len(roles))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_CanManage(t *testing.T) {
|
func TestConfig_CanManage(t *testing.T) {
|
||||||
|
ownerPubkey := nostr.MustPubKeyFromHex("9999999999999999999999999999999999999999999999999999999999999999")
|
||||||
adminPubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
adminPubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
||||||
userPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
userPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
|
secret: nostr.Generate(),
|
||||||
|
Info: struct {
|
||||||
|
Name string `toml:"name"`
|
||||||
|
Icon string `toml:"icon"`
|
||||||
|
Secret string `toml:"secret"`
|
||||||
|
Pubkey string `toml:"pubkey"`
|
||||||
|
Description string `toml:"description"`
|
||||||
|
}{
|
||||||
|
Pubkey: ownerPubkey.Hex(),
|
||||||
|
},
|
||||||
Roles: map[string]Role{
|
Roles: map[string]Role{
|
||||||
"admin": {
|
"admin": {
|
||||||
Pubkeys: []string{adminPubkey.Hex()},
|
Pubkeys: []string{adminPubkey.Hex()},
|
||||||
@@ -118,10 +119,21 @@ func TestConfig_CanManage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_CanInvite(t *testing.T) {
|
func TestConfig_CanInvite(t *testing.T) {
|
||||||
|
ownerPubkey := nostr.MustPubKeyFromHex("9999999999999999999999999999999999999999999999999999999999999999")
|
||||||
inviterPubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
inviterPubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
||||||
userPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
userPubkey := nostr.MustPubKeyFromHex("abcdef1234567890123456789012345678901234567890123456789012345678")
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
|
secret: nostr.Generate(),
|
||||||
|
Info: struct {
|
||||||
|
Name string `toml:"name"`
|
||||||
|
Icon string `toml:"icon"`
|
||||||
|
Secret string `toml:"secret"`
|
||||||
|
Pubkey string `toml:"pubkey"`
|
||||||
|
Description string `toml:"description"`
|
||||||
|
}{
|
||||||
|
Pubkey: ownerPubkey.Hex(),
|
||||||
|
},
|
||||||
Roles: map[string]Role{
|
Roles: map[string]Role{
|
||||||
"inviter": {
|
"inviter": {
|
||||||
Pubkeys: []string{inviterPubkey.Hex()},
|
Pubkeys: []string{inviterPubkey.Hex()},
|
||||||
@@ -144,9 +156,20 @@ func TestConfig_CanInvite(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConfig_MemberRole(t *testing.T) {
|
func TestConfig_MemberRole(t *testing.T) {
|
||||||
|
ownerPubkey := nostr.MustPubKeyFromHex("9999999999999999999999999999999999999999999999999999999999999999")
|
||||||
anyPubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
anyPubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
|
secret: nostr.Generate(),
|
||||||
|
Info: struct {
|
||||||
|
Name string `toml:"name"`
|
||||||
|
Icon string `toml:"icon"`
|
||||||
|
Secret string `toml:"secret"`
|
||||||
|
Pubkey string `toml:"pubkey"`
|
||||||
|
Description string `toml:"description"`
|
||||||
|
}{
|
||||||
|
Pubkey: ownerPubkey.Hex(),
|
||||||
|
},
|
||||||
Roles: map[string]Role{
|
Roles: map[string]Role{
|
||||||
"member": {
|
"member": {
|
||||||
Pubkeys: []string{},
|
Pubkeys: []string{},
|
||||||
@@ -155,9 +178,9 @@ func TestConfig_MemberRole(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
roles := config.GetRolesForPubkey(anyPubkey)
|
roles := config.GetAllRoles(anyPubkey)
|
||||||
if len(roles) != 1 {
|
if len(roles) != 1 {
|
||||||
t.Errorf("GetRolesForPubkey() should return member role for any pubkey, got %d roles", len(roles))
|
t.Errorf("GetAllRoles() should return member role for any pubkey, got %d roles", len(roles))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.CanInvite(anyPubkey) {
|
if !config.CanInvite(anyPubkey) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ func createTestEventStore() *EventStore {
|
|||||||
schema := &Schema{Name: "test_" + RandomString(8)}
|
schema := &Schema{Name: "test_" + RandomString(8)}
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Host: "test.com",
|
Host: "test.com",
|
||||||
Secret: nostr.Generate(),
|
secret: nostr.Generate(),
|
||||||
}
|
}
|
||||||
return &EventStore{
|
return &EventStore{
|
||||||
Config: config,
|
Config: config,
|
||||||
@@ -534,7 +534,7 @@ func TestEventStore_GetOrCreateApplicationSpecificData(t *testing.T) {
|
|||||||
|
|
||||||
dTag := "test/data"
|
dTag := "test/data"
|
||||||
|
|
||||||
// Test creating new data when none exists
|
// Test creating new data when none exists (unsigned)
|
||||||
event1 := store.GetOrCreateApplicationSpecificData(dTag)
|
event1 := store.GetOrCreateApplicationSpecificData(dTag)
|
||||||
|
|
||||||
if event1.Kind != nostr.KindApplicationSpecificData {
|
if event1.Kind != nostr.KindApplicationSpecificData {
|
||||||
@@ -546,9 +546,8 @@ func TestEventStore_GetOrCreateApplicationSpecificData(t *testing.T) {
|
|||||||
t.Errorf("GetOrCreateApplicationSpecificData() d tag = %v, want %v", dTagFound, dTag)
|
t.Errorf("GetOrCreateApplicationSpecificData() d tag = %v, want %v", dTagFound, dTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
if event1.PubKey != store.Config.Secret.Public() {
|
// Sign and store the event
|
||||||
t.Error("GetOrCreateApplicationSpecificData() should be signed by config secret")
|
store.SignAndStoreEvent(&event1, false)
|
||||||
}
|
|
||||||
|
|
||||||
// Test retrieving existing data
|
// Test retrieving existing data
|
||||||
event2 := store.GetOrCreateApplicationSpecificData(dTag)
|
event2 := store.GetOrCreateApplicationSpecificData(dTag)
|
||||||
@@ -557,6 +556,10 @@ func TestEventStore_GetOrCreateApplicationSpecificData(t *testing.T) {
|
|||||||
t.Error("GetOrCreateApplicationSpecificData() should return same event when called again")
|
t.Error("GetOrCreateApplicationSpecificData() should return same event when called again")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event2.PubKey != store.Config.GetSelf() {
|
||||||
|
t.Error("Retrieved event should be signed by config secret")
|
||||||
|
}
|
||||||
|
|
||||||
// Test with different d tag creates new event
|
// Test with different d tag creates new event
|
||||||
event3 := store.GetOrCreateApplicationSpecificData("other/data")
|
event3 := store.GetOrCreateApplicationSpecificData("other/data")
|
||||||
|
|
||||||
|
|||||||
@@ -39,174 +39,3 @@ func TestGetGroupIDFromEvent(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeGroupMetadataFilter(t *testing.T) {
|
|
||||||
h := "group123"
|
|
||||||
filter := MakeGroupMetadataFilter(h)
|
|
||||||
|
|
||||||
if len(filter.Kinds) != 1 || filter.Kinds[0] != nostr.KindSimpleGroupMetadata {
|
|
||||||
t.Errorf("MakeGroupMetadataFilter() kinds = %v, want [%v]", filter.Kinds, nostr.KindSimpleGroupMetadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
if filter.Tags["a"][0] != h {
|
|
||||||
t.Errorf("MakeGroupMetadataFilter() tags a = %v, want %v", filter.Tags["a"], h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakeGroupEventFilters(t *testing.T) {
|
|
||||||
h := "group123"
|
|
||||||
filters := MakeGroupEventFilters(h)
|
|
||||||
|
|
||||||
if len(filters) != 2 {
|
|
||||||
t.Errorf("MakeGroupEventFilters() length = %v, want 2", len(filters))
|
|
||||||
}
|
|
||||||
|
|
||||||
if filters[0].Tags["a"][0] != h {
|
|
||||||
t.Errorf("MakeGroupEventFilters() first filter tag a = %v, want %v", filters[0].Tags["a"], h)
|
|
||||||
}
|
|
||||||
|
|
||||||
if filters[1].Tags["h"][0] != h {
|
|
||||||
t.Errorf("MakeGroupEventFilters() second filter tag h = %v, want %v", filters[1].Tags["h"], h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakeGroupMembershipCheckFilter(t *testing.T) {
|
|
||||||
h := "group123"
|
|
||||||
pubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
|
||||||
filter := MakeGroupMembershipCheckFilter(h, pubkey)
|
|
||||||
|
|
||||||
expectedKinds := []nostr.Kind{nostr.KindSimpleGroupPutUser, nostr.KindSimpleGroupRemoveUser}
|
|
||||||
if len(filter.Kinds) != 2 {
|
|
||||||
t.Errorf("MakeGroupMembershipCheckFilter() kinds length = %v, want 2", len(filter.Kinds))
|
|
||||||
}
|
|
||||||
for i, kind := range expectedKinds {
|
|
||||||
if filter.Kinds[i] != kind {
|
|
||||||
t.Errorf("MakeGroupMembershipCheckFilter() kinds[%d] = %v, want %v", i, filter.Kinds[i], kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if filter.Tags["p"][0] != pubkey.Hex() {
|
|
||||||
t.Errorf("MakeGroupMembershipCheckFilter() tag p = %v, want %v", filter.Tags["p"], pubkey.Hex())
|
|
||||||
}
|
|
||||||
|
|
||||||
if filter.Tags["h"][0] != h {
|
|
||||||
t.Errorf("MakeGroupMembershipCheckFilter() tag h = %v, want %v", filter.Tags["h"], h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCheckGroupMembership(t *testing.T) {
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
events []nostr.Event
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "put user event",
|
|
||||||
events: []nostr.Event{
|
|
||||||
{Kind: nostr.KindSimpleGroupPutUser},
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "remove user event",
|
|
||||||
events: []nostr.Event{
|
|
||||||
{Kind: nostr.KindSimpleGroupRemoveUser},
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no events",
|
|
||||||
events: []nostr.Event{},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
seq := func(yield func(nostr.Event) bool) {
|
|
||||||
for _, event := range tt.events {
|
|
||||||
if !yield(event) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := CheckGroupMembership(seq)
|
|
||||||
if result != tt.want {
|
|
||||||
t.Errorf("CheckGroupMembership() = %v, want %v", result, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakePutUserEvent(t *testing.T) {
|
|
||||||
h := "group123"
|
|
||||||
pubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
|
||||||
|
|
||||||
event := MakePutUserEvent(h, pubkey)
|
|
||||||
|
|
||||||
if event.Kind != nostr.KindSimpleGroupPutUser {
|
|
||||||
t.Errorf("MakePutUserEvent() kind = %v, want %v", event.Kind, nostr.KindSimpleGroupPutUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
if event.CreatedAt == 0 {
|
|
||||||
t.Error("MakePutUserEvent() should set CreatedAt")
|
|
||||||
}
|
|
||||||
|
|
||||||
pTag := event.Tags.Find("p")
|
|
||||||
if pTag == nil || pTag[1] != pubkey.Hex() {
|
|
||||||
t.Errorf("MakePutUserEvent() p tag = %v, want %v", pTag, pubkey.Hex())
|
|
||||||
}
|
|
||||||
|
|
||||||
hTag := event.Tags.Find("h")
|
|
||||||
if hTag == nil || hTag[1] != h {
|
|
||||||
t.Errorf("MakePutUserEvent() h tag = %v, want %v", hTag, h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakeRemoveUserEvent(t *testing.T) {
|
|
||||||
h := "group123"
|
|
||||||
pubkey := nostr.MustPubKeyFromHex("1234567890123456789012345678901234567890123456789012345678901234")
|
|
||||||
|
|
||||||
event := MakeRemoveUserEvent(h, pubkey)
|
|
||||||
|
|
||||||
if event.Kind != nostr.KindSimpleGroupRemoveUser {
|
|
||||||
t.Errorf("MakeRemoveUserEvent() kind = %v, want %v", event.Kind, nostr.KindSimpleGroupRemoveUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
if event.CreatedAt == 0 {
|
|
||||||
t.Error("MakeRemoveUserEvent() should set CreatedAt")
|
|
||||||
}
|
|
||||||
|
|
||||||
pTag := event.Tags.Find("p")
|
|
||||||
if pTag == nil || pTag[1] != pubkey.Hex() {
|
|
||||||
t.Errorf("MakeRemoveUserEvent() p tag = %v, want %v", pTag, pubkey.Hex())
|
|
||||||
}
|
|
||||||
|
|
||||||
hTag := event.Tags.Find("h")
|
|
||||||
if hTag == nil || hTag[1] != h {
|
|
||||||
t.Errorf("MakeRemoveUserEvent() h tag = %v, want %v", hTag, h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakeMetadataEvent(t *testing.T) {
|
|
||||||
originalEvent := nostr.Event{
|
|
||||||
Kind: nostr.KindSimpleGroupCreateGroup,
|
|
||||||
CreatedAt: nostr.Timestamp(1234567890),
|
|
||||||
Tags: nostr.Tags{{"name", "Test Group"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
metadataEvent := MakeMetadataEvent(originalEvent)
|
|
||||||
|
|
||||||
if metadataEvent.Kind != nostr.KindSimpleGroupMetadata {
|
|
||||||
t.Errorf("MakeMetadataEvent() kind = %v, want %v", metadataEvent.Kind, nostr.KindSimpleGroupMetadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
if metadataEvent.CreatedAt != originalEvent.CreatedAt {
|
|
||||||
t.Errorf("MakeMetadataEvent() CreatedAt = %v, want %v", metadataEvent.CreatedAt, originalEvent.CreatedAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(metadataEvent.Tags) != len(originalEvent.Tags) {
|
|
||||||
t.Errorf("MakeMetadataEvent() tags length = %v, want %v", len(metadataEvent.Tags), len(originalEvent.Tags))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+18
-292
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
|
"fiatjaf.com/nostr/khatru"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createTestInstance() *Instance {
|
func createTestInstance() *Instance {
|
||||||
@@ -12,19 +13,16 @@ func createTestInstance() *Instance {
|
|||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Host: "test.com",
|
Host: "test.com",
|
||||||
Secret: ownerSecret,
|
secret: ownerSecret,
|
||||||
Self: struct {
|
Info: struct {
|
||||||
Name string `toml:"name"`
|
Name string `toml:"name"`
|
||||||
Icon string `toml:"icon"`
|
Icon string `toml:"icon"`
|
||||||
Schema string `toml:"schema"`
|
|
||||||
Secret string `toml:"secret"`
|
Secret string `toml:"secret"`
|
||||||
Pubkey string `toml:"pubkey"`
|
Pubkey string `toml:"pubkey"`
|
||||||
Description string `toml:"description"`
|
Description string `toml:"description"`
|
||||||
}{
|
}{
|
||||||
Name: "Test Relay",
|
Name: "Test Relay",
|
||||||
Secret: ownerSecret.Hex(),
|
|
||||||
Pubkey: ownerPubkey.Hex(),
|
Pubkey: ownerPubkey.Hex(),
|
||||||
Schema: "test_relay",
|
|
||||||
},
|
},
|
||||||
Roles: map[string]Role{
|
Roles: map[string]Role{
|
||||||
"admin": {
|
"admin": {
|
||||||
@@ -36,18 +34,25 @@ func createTestInstance() *Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
schema := &Schema{Name: "test_" + RandomString(8)}
|
schema := &Schema{Name: "test_" + RandomString(8)}
|
||||||
|
|
||||||
|
relay := &khatru.Relay{}
|
||||||
|
|
||||||
events := &EventStore{
|
events := &EventStore{
|
||||||
|
Relay: relay,
|
||||||
Config: config,
|
Config: config,
|
||||||
Schema: schema,
|
Schema: schema,
|
||||||
}
|
}
|
||||||
|
|
||||||
instance := &Instance{
|
management := &ManagementStore{
|
||||||
Config: config,
|
Config: config,
|
||||||
Events: events,
|
Events: events,
|
||||||
Management: &ManagementStore{
|
}
|
||||||
Config: config,
|
|
||||||
Events: events,
|
instance := &Instance{
|
||||||
},
|
Relay: relay,
|
||||||
|
Config: config,
|
||||||
|
Events: events,
|
||||||
|
Management: management,
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.Events.Init()
|
instance.Events.Init()
|
||||||
@@ -55,169 +60,14 @@ func createTestInstance() *Instance {
|
|||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstance_IsAdmin(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
ownerPubkey := instance.Config.Secret.Public()
|
|
||||||
otherPubkey := nostr.Generate().Public()
|
|
||||||
|
|
||||||
// Test owner is admin
|
|
||||||
if !instance.Config.IsAdmin(ownerPubkey) {
|
|
||||||
t.Error("IsAdmin() should return true for owner")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test non-owner is not admin
|
|
||||||
if instance.Config.IsAdmin(otherPubkey) {
|
|
||||||
t.Error("IsAdmin() should return false for non-owner")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test user with manage permission is admin
|
|
||||||
managerPubkey := nostr.Generate().Public()
|
|
||||||
instance.Config.Roles["manager"] = Role{
|
|
||||||
Pubkeys: []string{managerPubkey.Hex()},
|
|
||||||
CanManage: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
if !instance.Config.IsAdmin(managerPubkey) {
|
|
||||||
t.Error("IsAdmin() should return true for user with manage permissions")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstance_HasAccess(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
ownerPubkey := instance.Config.Secret.Public()
|
|
||||||
userSecret := nostr.Generate()
|
|
||||||
userPubkey := userSecret.Public()
|
|
||||||
|
|
||||||
// Test owner has access
|
|
||||||
if !instance.HasAccess(ownerPubkey) {
|
|
||||||
t.Error("HasAccess() should return true for owner")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test user without join event has no access
|
|
||||||
if instance.HasAccess(userPubkey) {
|
|
||||||
t.Error("HasAccess() should return false for user without join event")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a join event for the user (must be signed by the user)
|
|
||||||
joinEvent := nostr.Event{
|
|
||||||
Kind: RELAY_JOIN,
|
|
||||||
CreatedAt: nostr.Now(),
|
|
||||||
PubKey: userPubkey,
|
|
||||||
Tags: nostr.Tags{{"claim", "test"}},
|
|
||||||
}
|
|
||||||
joinEvent.Sign(userSecret)
|
|
||||||
|
|
||||||
instance.Events.SaveEvent(joinEvent)
|
|
||||||
|
|
||||||
// Test user with join event has access
|
|
||||||
if !instance.HasAccess(userPubkey) {
|
|
||||||
t.Error("HasAccess() should return true for user with join event")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstance_IsGroupMember(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
groupID := "test-group-123"
|
|
||||||
userPubkey := nostr.Generate().Public()
|
|
||||||
|
|
||||||
// Test user is not initially a member
|
|
||||||
if instance.IsGroupMember(groupID, userPubkey) {
|
|
||||||
t.Error("IsGroupMember() should return false for non-member")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add user to group
|
|
||||||
putUserEvent := MakePutUserEvent(groupID, userPubkey)
|
|
||||||
putUserEvent.Sign(instance.Config.Secret)
|
|
||||||
instance.Events.SaveEvent(putUserEvent)
|
|
||||||
|
|
||||||
// Test user is now a member
|
|
||||||
if !instance.IsGroupMember(groupID, userPubkey) {
|
|
||||||
t.Error("IsGroupMember() should return true after put user event")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove user from group (with a later timestamp to ensure proper ordering)
|
|
||||||
removeUserEvent := MakeRemoveUserEvent(groupID, userPubkey)
|
|
||||||
removeUserEvent.CreatedAt = nostr.Now() + 1 // Make it newer
|
|
||||||
removeUserEvent.Sign(instance.Config.Secret)
|
|
||||||
instance.Events.SaveEvent(removeUserEvent)
|
|
||||||
|
|
||||||
// Test user is no longer a member
|
|
||||||
if instance.IsGroupMember(groupID, userPubkey) {
|
|
||||||
t.Error("IsGroupMember() should return false after remove user event")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstance_HasGroupAccess(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
groupID := "test-group-456"
|
|
||||||
userPubkey := nostr.Generate().Public()
|
|
||||||
|
|
||||||
// Create open group metadata
|
|
||||||
openGroupMeta := nostr.Event{
|
|
||||||
Kind: nostr.KindSimpleGroupMetadata,
|
|
||||||
CreatedAt: nostr.Now(),
|
|
||||||
Tags: nostr.Tags{
|
|
||||||
{"a", groupID},
|
|
||||||
{"name", "Open Group"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
openGroupMeta.Sign(instance.Config.Secret)
|
|
||||||
instance.Events.SaveEvent(openGroupMeta)
|
|
||||||
|
|
||||||
// Test access to open group
|
|
||||||
if !instance.HasGroupAccess(groupID, userPubkey) {
|
|
||||||
t.Error("HasGroupAccess() should return true for open group")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create closed group metadata
|
|
||||||
closedGroupID := "closed-group-789"
|
|
||||||
closedGroupMeta := nostr.Event{
|
|
||||||
Kind: nostr.KindSimpleGroupMetadata,
|
|
||||||
CreatedAt: nostr.Now(),
|
|
||||||
Tags: nostr.Tags{
|
|
||||||
{"a", closedGroupID},
|
|
||||||
{"name", "Closed Group"},
|
|
||||||
{"closed", ""},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
closedGroupMeta.Sign(instance.Config.Secret)
|
|
||||||
instance.Events.SaveEvent(closedGroupMeta)
|
|
||||||
|
|
||||||
// Test no access to closed group for non-member
|
|
||||||
if instance.HasGroupAccess(closedGroupID, userPubkey) {
|
|
||||||
t.Error("HasGroupAccess() should return false for closed group non-member")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add user as member to closed group
|
|
||||||
putUserEvent := MakePutUserEvent(closedGroupID, userPubkey)
|
|
||||||
putUserEvent.Sign(instance.Config.Secret)
|
|
||||||
instance.Events.SaveEvent(putUserEvent)
|
|
||||||
|
|
||||||
// Test access to closed group for member
|
|
||||||
if !instance.HasGroupAccess(closedGroupID, userPubkey) {
|
|
||||||
t.Error("HasGroupAccess() should return true for closed group member")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstance_AllowRecipientEvent(t *testing.T) {
|
func TestInstance_AllowRecipientEvent(t *testing.T) {
|
||||||
instance := createTestInstance()
|
instance := createTestInstance()
|
||||||
|
|
||||||
userSecret := nostr.Generate()
|
userSecret := nostr.Generate()
|
||||||
userPubkey := userSecret.Public()
|
userPubkey := userSecret.Public()
|
||||||
|
|
||||||
// Add user access
|
// Add user as member
|
||||||
joinEvent := nostr.Event{
|
instance.Management.AddMember(userPubkey)
|
||||||
Kind: RELAY_JOIN,
|
|
||||||
CreatedAt: nostr.Now(),
|
|
||||||
PubKey: userPubkey,
|
|
||||||
Tags: nostr.Tags{{"claim", "test"}},
|
|
||||||
}
|
|
||||||
joinEvent.Sign(userSecret)
|
|
||||||
instance.Events.SaveEvent(joinEvent)
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -289,7 +139,7 @@ func TestInstance_GenerateInviteEvent(t *testing.T) {
|
|||||||
t.Errorf("GenerateInviteEvent() kind = %v, want %v", inviteEvent.Kind, RELAY_INVITE)
|
t.Errorf("GenerateInviteEvent() kind = %v, want %v", inviteEvent.Kind, RELAY_INVITE)
|
||||||
}
|
}
|
||||||
|
|
||||||
if inviteEvent.PubKey != instance.Config.Secret.Public() {
|
if inviteEvent.PubKey != instance.Config.GetSelf() {
|
||||||
t.Error("GenerateInviteEvent() should be signed by instance")
|
t.Error("GenerateInviteEvent() should be signed by instance")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,106 +153,6 @@ func TestInstance_GenerateInviteEvent(t *testing.T) {
|
|||||||
if pTag == nil || pTag[1] != userPubkey.Hex() {
|
if pTag == nil || pTag[1] != userPubkey.Hex() {
|
||||||
t.Error("GenerateInviteEvent() should have correct p tag")
|
t.Error("GenerateInviteEvent() should have correct p tag")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The GenerateInviteEvent function actually looks for existing events
|
|
||||||
// by the target pubkey as author, but creates events signed by instance.
|
|
||||||
// This seems to be a bug in the implementation, but we test the current behavior.
|
|
||||||
// Each call will generate a new event since the query won't find a match.
|
|
||||||
inviteEvent2 := instance.GenerateInviteEvent(userPubkey)
|
|
||||||
if inviteEvent.ID == inviteEvent2.ID {
|
|
||||||
t.Error("GenerateInviteEvent() generates new events each time due to query mismatch")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstance_OnJoinEvent(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
userPubkey := nostr.Generate().Public()
|
|
||||||
|
|
||||||
// Generate an invite first
|
|
||||||
inviteEvent := instance.GenerateInviteEvent(userPubkey)
|
|
||||||
claimTag := inviteEvent.Tags.Find("claim")
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
joinEvent nostr.Event
|
|
||||||
wantReject bool
|
|
||||||
wantMsg string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "valid join event",
|
|
||||||
joinEvent: nostr.Event{
|
|
||||||
Kind: RELAY_JOIN,
|
|
||||||
Tags: nostr.Tags{{"claim", claimTag[1]}},
|
|
||||||
},
|
|
||||||
wantReject: false,
|
|
||||||
wantMsg: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "join event without claim",
|
|
||||||
joinEvent: nostr.Event{
|
|
||||||
Kind: RELAY_JOIN,
|
|
||||||
Tags: nostr.Tags{},
|
|
||||||
},
|
|
||||||
wantReject: true,
|
|
||||||
wantMsg: "invalid: no claim tag",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "join event with invalid claim",
|
|
||||||
joinEvent: nostr.Event{
|
|
||||||
Kind: RELAY_JOIN,
|
|
||||||
Tags: nostr.Tags{{"claim", "invalid-claim"}},
|
|
||||||
},
|
|
||||||
wantReject: true,
|
|
||||||
wantMsg: "invalid: failed to validate invite code",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
reject, msg := instance.OnJoinEvent(tt.joinEvent)
|
|
||||||
if reject != tt.wantReject {
|
|
||||||
t.Errorf("OnJoinEvent() reject = %v, want %v", reject, tt.wantReject)
|
|
||||||
}
|
|
||||||
if msg != tt.wantMsg {
|
|
||||||
t.Errorf("OnJoinEvent() msg = %v, want %v", msg, tt.wantMsg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInstance_GetGroupMetadataEvent(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
groupID := "test-group-metadata"
|
|
||||||
|
|
||||||
// Test with no metadata event
|
|
||||||
metaEvent := instance.GetGroupMetadataEvent(groupID)
|
|
||||||
if !IsEmptyEvent(metaEvent) {
|
|
||||||
t.Error("GetGroupMetadataEvent() should return empty event when no metadata exists")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create metadata event
|
|
||||||
originalMeta := nostr.Event{
|
|
||||||
Kind: nostr.KindSimpleGroupMetadata,
|
|
||||||
CreatedAt: nostr.Now(),
|
|
||||||
Tags: nostr.Tags{
|
|
||||||
{"a", groupID},
|
|
||||||
{"name", "Test Group"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
originalMeta.Sign(instance.Config.Secret)
|
|
||||||
instance.Events.SaveEvent(originalMeta)
|
|
||||||
|
|
||||||
// Test with metadata event
|
|
||||||
metaEvent = instance.GetGroupMetadataEvent(groupID)
|
|
||||||
if IsEmptyEvent(metaEvent) {
|
|
||||||
t.Error("GetGroupMetadataEvent() should return metadata event")
|
|
||||||
}
|
|
||||||
|
|
||||||
if metaEvent.ID != originalMeta.ID {
|
|
||||||
t.Error("GetGroupMetadataEvent() should return correct metadata event")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstance_IsInternalEvent(t *testing.T) {
|
func TestInstance_IsInternalEvent(t *testing.T) {
|
||||||
@@ -464,27 +214,3 @@ func TestInstance_IsInternalEvent(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInstance_HasAccess_WithBannedUser(t *testing.T) {
|
|
||||||
instance := createTestInstance()
|
|
||||||
|
|
||||||
userSecret := nostr.Generate()
|
|
||||||
userPubkey := userSecret.Public()
|
|
||||||
|
|
||||||
// Add user to banned list
|
|
||||||
instance.Management.BanPubkey(userPubkey, "test ban")
|
|
||||||
|
|
||||||
// Test banned user has no access even with join event
|
|
||||||
joinEvent := nostr.Event{
|
|
||||||
Kind: RELAY_JOIN,
|
|
||||||
CreatedAt: nostr.Now(),
|
|
||||||
PubKey: userPubkey,
|
|
||||||
Tags: nostr.Tags{{"claim", "test"}},
|
|
||||||
}
|
|
||||||
joinEvent.Sign(userSecret)
|
|
||||||
instance.Events.SaveEvent(joinEvent)
|
|
||||||
|
|
||||||
if instance.HasAccess(userPubkey) {
|
|
||||||
t.Error("HasAccess() should return false for banned user even with join event")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-4
@@ -28,17 +28,17 @@ func Dispatch(hostname string) (*Instance, bool) {
|
|||||||
func Start() {
|
func Start() {
|
||||||
dataDir := Env("DATA")
|
dataDir := Env("DATA")
|
||||||
if err := os.MkdirAll(dataDir, 0755); err != nil {
|
if err := os.MkdirAll(dataDir, 0755); err != nil {
|
||||||
log.Fatal("Failed to create data directory: %v", err)
|
log.Fatalf("Failed to create data directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaDir := Env("MEDIA")
|
mediaDir := Env("MEDIA")
|
||||||
if err := os.MkdirAll(mediaDir, 0755); err != nil {
|
if err := os.MkdirAll(mediaDir, 0755); err != nil {
|
||||||
log.Fatal("Failed to create media directory: %v", err)
|
log.Fatalf("Failed to create media directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
configDir := Env("CONFIG")
|
configDir := Env("CONFIG")
|
||||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||||
log.Fatal("Failed to create config directory: %v", err)
|
log.Fatalf("Failed to create config directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
instancesOnce.Do(func() {
|
instancesOnce.Do(func() {
|
||||||
@@ -48,7 +48,7 @@ func Start() {
|
|||||||
|
|
||||||
entries, err := os.ReadDir(configDir)
|
entries, err := os.ReadDir(configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to scan config directory: %v", err)
|
log.Fatalf("Failed to scan config directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ func (m *ManagementStore) BanEvent(id nostr.ID, reason string) error {
|
|||||||
func (m *ManagementStore) AllowEvent(id nostr.ID, reason string) error {
|
func (m *ManagementStore) AllowEvent(id nostr.ID, reason string) error {
|
||||||
event := m.Events.GetOrCreateApplicationSpecificData(BANNED_EVENTS)
|
event := m.Events.GetOrCreateApplicationSpecificData(BANNED_EVENTS)
|
||||||
event.Tags = Filter(event.Tags, func(t nostr.Tag) bool {
|
event.Tags = Filter(event.Tags, func(t nostr.Tag) bool {
|
||||||
return t[1] == id.Hex()
|
return t[1] != id.Hex()
|
||||||
})
|
})
|
||||||
|
|
||||||
return m.Events.SignAndStoreEvent(&event, false)
|
return m.Events.SignAndStoreEvent(&event, false)
|
||||||
|
|||||||
@@ -4,15 +4,18 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
|
"fiatjaf.com/nostr/khatru"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createTestManagementStore() *ManagementStore {
|
func createTestManagementStore() *ManagementStore {
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Host: "test.com",
|
Host: "test.com",
|
||||||
Secret: nostr.Generate(),
|
secret: nostr.Generate(),
|
||||||
}
|
}
|
||||||
schema := &Schema{Name: "test_" + RandomString(8)}
|
schema := &Schema{Name: "test_" + RandomString(8)}
|
||||||
|
relay := &khatru.Relay{}
|
||||||
events := &EventStore{
|
events := &EventStore{
|
||||||
|
Relay: relay,
|
||||||
Config: config,
|
Config: config,
|
||||||
Schema: schema,
|
Schema: schema,
|
||||||
}
|
}
|
||||||
@@ -39,24 +42,11 @@ func TestManagementStore_BanPubkey(t *testing.T) {
|
|||||||
t.Error("PubkeyIsBanned() should return true after banning")
|
t.Error("PubkeyIsBanned() should return true after banning")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test banned pubkey list
|
|
||||||
bannedPubkeys := mgmt.GetBannedPubkeys()
|
|
||||||
found := false
|
|
||||||
for _, banned := range bannedPubkeys {
|
|
||||||
if banned == pubkey {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
t.Error("GetBannedPubkeys() should include banned pubkey")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test banned pubkey items
|
// Test banned pubkey items
|
||||||
bannedItems := mgmt.GetBannedPubkeyItems()
|
bannedItems := mgmt.GetBannedPubkeyItems()
|
||||||
itemFound := false
|
itemFound := false
|
||||||
for _, item := range bannedItems {
|
for _, item := range bannedItems {
|
||||||
if item.Pubkey == pubkey && item.Reason == reason {
|
if item.PubKey == pubkey && item.Reason == reason {
|
||||||
itemFound = true
|
itemFound = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -78,7 +68,7 @@ func TestManagementStore_AllowPubkey(t *testing.T) {
|
|||||||
t.Error("Setup: pubkey should be banned")
|
t.Error("Setup: pubkey should be banned")
|
||||||
}
|
}
|
||||||
|
|
||||||
mgmt.AllowPubkey(pubkey, "unbanned")
|
mgmt.AllowPubkey(pubkey)
|
||||||
|
|
||||||
if mgmt.PubkeyIsBanned(pubkey) {
|
if mgmt.PubkeyIsBanned(pubkey) {
|
||||||
t.Error("PubkeyIsBanned() should return false after allowing")
|
t.Error("PubkeyIsBanned() should return false after allowing")
|
||||||
@@ -98,24 +88,11 @@ func TestManagementStore_BanEvent(t *testing.T) {
|
|||||||
t.Error("EventIsBanned() should return true after banning")
|
t.Error("EventIsBanned() should return true after banning")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test banned event list
|
|
||||||
bannedEvents := mgmt.GetBannedEvents()
|
|
||||||
found := false
|
|
||||||
for _, banned := range bannedEvents {
|
|
||||||
if banned == eventID {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
t.Error("GetBannedEvents() should include banned event")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test banned event items
|
// Test banned event items
|
||||||
bannedItems := mgmt.GetBannedEventItems()
|
bannedItems := mgmt.GetBannedEventItems()
|
||||||
itemFound := false
|
itemFound := false
|
||||||
for _, item := range bannedItems {
|
for _, item := range bannedItems {
|
||||||
if item.ID == eventID && item.Reason == reason {
|
if item.ID == eventID.Hex() && item.Reason == reason {
|
||||||
itemFound = true
|
itemFound = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user