You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
5.0 KiB
211 lines
5.0 KiB
package dgraph |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"time" |
|
|
|
"next.orly.dev/pkg/database" |
|
"next.orly.dev/pkg/encoders/hex" |
|
) |
|
|
|
// NIP-43 Invite-based ACL methods |
|
// Simplified implementation using marker-based storage |
|
|
|
// AddNIP43Member adds a member using an invite code |
|
func (d *D) AddNIP43Member(pubkey []byte, inviteCode string) error { |
|
key := "nip43_" + hex.Enc(pubkey) |
|
|
|
member := database.NIP43Membership{ |
|
InviteCode: inviteCode, |
|
AddedAt: time.Now(), |
|
} |
|
copy(member.Pubkey[:], pubkey) |
|
|
|
data, err := json.Marshal(member) |
|
if err != nil { |
|
return fmt.Errorf("failed to marshal membership: %w", err) |
|
} |
|
|
|
// Also add to members list |
|
if err := d.addToMembersList(pubkey); err != nil { |
|
return err |
|
} |
|
|
|
return d.SetMarker(key, data) |
|
} |
|
|
|
// RemoveNIP43Member removes a member |
|
func (d *D) RemoveNIP43Member(pubkey []byte) error { |
|
key := "nip43_" + hex.Enc(pubkey) |
|
|
|
// Remove from members list |
|
if err := d.removeFromMembersList(pubkey); err != nil { |
|
return err |
|
} |
|
|
|
return d.DeleteMarker(key) |
|
} |
|
|
|
// IsNIP43Member checks if a pubkey is a member |
|
func (d *D) IsNIP43Member(pubkey []byte) (isMember bool, err error) { |
|
_, err = d.GetNIP43Membership(pubkey) |
|
return err == nil, nil |
|
} |
|
|
|
// GetNIP43Membership retrieves membership information |
|
func (d *D) GetNIP43Membership(pubkey []byte) (*database.NIP43Membership, error) { |
|
key := "nip43_" + hex.Enc(pubkey) |
|
|
|
data, err := d.GetMarker(key) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
var member database.NIP43Membership |
|
if err := json.Unmarshal(data, &member); err != nil { |
|
return nil, fmt.Errorf("failed to unmarshal membership: %w", err) |
|
} |
|
|
|
return &member, nil |
|
} |
|
|
|
// GetAllNIP43Members retrieves all member pubkeys |
|
func (d *D) GetAllNIP43Members() ([][]byte, error) { |
|
data, err := d.GetMarker("nip43_members_list") |
|
if err != nil { |
|
return nil, nil // No members = empty list |
|
} |
|
|
|
var members []string |
|
if err := json.Unmarshal(data, &members); err != nil { |
|
return nil, fmt.Errorf("failed to unmarshal members list: %w", err) |
|
} |
|
|
|
result := make([][]byte, 0, len(members)) |
|
for _, hexPubkey := range members { |
|
pubkey, err := hex.Dec(hexPubkey) |
|
if err != nil { |
|
continue |
|
} |
|
result = append(result, pubkey) |
|
} |
|
|
|
return result, nil |
|
} |
|
|
|
// StoreInviteCode stores an invite code with expiration |
|
func (d *D) StoreInviteCode(code string, expiresAt time.Time) error { |
|
key := "invite_" + code |
|
|
|
inviteData := map[string]interface{}{ |
|
"code": code, |
|
"expiresAt": expiresAt, |
|
} |
|
|
|
data, err := json.Marshal(inviteData) |
|
if err != nil { |
|
return fmt.Errorf("failed to marshal invite: %w", err) |
|
} |
|
|
|
return d.SetMarker(key, data) |
|
} |
|
|
|
// ValidateInviteCode checks if an invite code is valid |
|
func (d *D) ValidateInviteCode(code string) (valid bool, err error) { |
|
key := "invite_" + code |
|
|
|
data, err := d.GetMarker(key) |
|
if err != nil { |
|
return false, nil // Code doesn't exist |
|
} |
|
|
|
var inviteData map[string]interface{} |
|
if err := json.Unmarshal(data, &inviteData); err != nil { |
|
return false, fmt.Errorf("failed to unmarshal invite: %w", err) |
|
} |
|
|
|
// Check expiration |
|
if expiresStr, ok := inviteData["expiresAt"].(string); ok { |
|
expiresAt, err := time.Parse(time.RFC3339, expiresStr) |
|
if err == nil && time.Now().After(expiresAt) { |
|
return false, nil // Expired |
|
} |
|
} |
|
|
|
return true, nil |
|
} |
|
|
|
// DeleteInviteCode removes an invite code |
|
func (d *D) DeleteInviteCode(code string) error { |
|
key := "invite_" + code |
|
return d.DeleteMarker(key) |
|
} |
|
|
|
// PublishNIP43MembershipEvent publishes a membership event |
|
func (d *D) PublishNIP43MembershipEvent(kind int, pubkey []byte) error { |
|
// This would require publishing an actual Nostr event |
|
// For now, just log it |
|
d.Logger.Infof("would publish NIP-43 event kind %d for %s", kind, hex.Enc(pubkey)) |
|
return nil |
|
} |
|
|
|
// Helper functions |
|
|
|
func (d *D) addToMembersList(pubkey []byte) error { |
|
data, err := d.GetMarker("nip43_members_list") |
|
|
|
var members []string |
|
if err == nil { |
|
if err := json.Unmarshal(data, &members); err != nil { |
|
return fmt.Errorf("failed to unmarshal members list: %w", err) |
|
} |
|
} |
|
|
|
hexPubkey := hex.Enc(pubkey) |
|
|
|
// Check if already in list |
|
for _, member := range members { |
|
if member == hexPubkey { |
|
return nil // Already in list |
|
} |
|
} |
|
|
|
members = append(members, hexPubkey) |
|
|
|
data, err = json.Marshal(members) |
|
if err != nil { |
|
return fmt.Errorf("failed to marshal members list: %w", err) |
|
} |
|
|
|
return d.SetMarker("nip43_members_list", data) |
|
} |
|
|
|
func (d *D) removeFromMembersList(pubkey []byte) error { |
|
data, err := d.GetMarker("nip43_members_list") |
|
if err != nil { |
|
return nil // List doesn't exist |
|
} |
|
|
|
var members []string |
|
if err := json.Unmarshal(data, &members); err != nil { |
|
return fmt.Errorf("failed to unmarshal members list: %w", err) |
|
} |
|
|
|
hexPubkey := hex.Enc(pubkey) |
|
|
|
// Remove from list |
|
newMembers := make([]string, 0, len(members)) |
|
for _, member := range members { |
|
if member != hexPubkey { |
|
newMembers = append(newMembers, member) |
|
} |
|
} |
|
|
|
data, err = json.Marshal(newMembers) |
|
if err != nil { |
|
return fmt.Errorf("failed to marshal members list: %w", err) |
|
} |
|
|
|
return d.SetMarker("nip43_members_list", data) |
|
}
|
|
|