+160
-3
appview/ingester.go
+160
-3
appview/ingester.go
···
14
14
"tangled.sh/tangled.sh/core/api/tangled"
15
15
"tangled.sh/tangled.sh/core/appview/config"
16
16
"tangled.sh/tangled.sh/core/appview/db"
17
-
"tangled.sh/tangled.sh/core/appview/spindleverify"
17
+
"tangled.sh/tangled.sh/core/appview/serververify"
18
18
"tangled.sh/tangled.sh/core/idresolver"
19
19
"tangled.sh/tangled.sh/core/rbac"
20
20
)
···
64
64
err = i.ingestSpindleMember(e)
65
65
case tangled.SpindleNSID:
66
66
err = i.ingestSpindle(e)
67
+
case tangled.KnotMemberNSID:
68
+
err = i.ingestKnotMember(e)
69
+
case tangled.KnotNSID:
70
+
err = i.ingestKnot(e)
67
71
case tangled.StringNSID:
68
72
err = i.ingestString(e)
69
73
}
···
475
479
return err
476
480
}
477
481
478
-
err = spindleverify.RunVerification(context.Background(), instance, did, i.Config.Core.Dev)
482
+
err = serververify.RunVerification(context.Background(), instance, did, i.Config.Core.Dev)
479
483
if err != nil {
480
484
l.Error("failed to add spindle to db", "err", err, "instance", instance)
481
485
return err
482
486
}
483
487
484
-
_, err = spindleverify.MarkVerified(ddb, i.Enforcer, instance, did)
488
+
_, err = serververify.MarkSpindleVerified(ddb, i.Enforcer, instance, did)
485
489
if err != nil {
486
490
return fmt.Errorf("failed to mark verified: %w", err)
487
491
}
···
609
613
610
614
return nil
611
615
}
616
+
617
+
func (i *Ingester) ingestKnotMember(e *models.Event) error {
618
+
did := e.Did
619
+
var err error
620
+
621
+
l := i.Logger.With("handler", "ingestKnotMember")
622
+
l = l.With("nsid", e.Commit.Collection)
623
+
624
+
switch e.Commit.Operation {
625
+
case models.CommitOperationCreate:
626
+
raw := json.RawMessage(e.Commit.Record)
627
+
record := tangled.KnotMember{}
628
+
err = json.Unmarshal(raw, &record)
629
+
if err != nil {
630
+
l.Error("invalid record", "err", err)
631
+
return err
632
+
}
633
+
634
+
// only knot owner can invite to knots
635
+
ok, err := i.Enforcer.IsKnotInviteAllowed(did, record.Domain)
636
+
if err != nil || !ok {
637
+
return fmt.Errorf("failed to enforce permissions: %w", err)
638
+
}
639
+
640
+
memberId, err := i.IdResolver.ResolveIdent(context.Background(), record.Subject)
641
+
if err != nil {
642
+
return err
643
+
}
644
+
645
+
if memberId.Handle.IsInvalidHandle() {
646
+
return err
647
+
}
648
+
649
+
err = i.Enforcer.AddKnotMember(record.Domain, memberId.DID.String())
650
+
if err != nil {
651
+
return fmt.Errorf("failed to update ACLs: %w", err)
652
+
}
653
+
654
+
l.Info("added knot member")
655
+
case models.CommitOperationDelete:
656
+
// we don't store knot members in a table (like we do for spindle)
657
+
// and we can't remove this just yet. possibly fixed if we switch
658
+
// to either:
659
+
// 1. a knot_members table like with spindle and store the rkey
660
+
// 2. use the knot host as the rkey
661
+
//
662
+
// TODO: implement member deletion
663
+
l.Info("skipping knot member delete", "did", did, "rkey", e.Commit.RKey)
664
+
}
665
+
666
+
return nil
667
+
}
668
+
669
+
func (i *Ingester) ingestKnot(e *models.Event) error {
670
+
did := e.Did
671
+
var err error
672
+
673
+
l := i.Logger.With("handler", "ingestKnot")
674
+
l = l.With("nsid", e.Commit.Collection)
675
+
676
+
switch e.Commit.Operation {
677
+
case models.CommitOperationCreate:
678
+
raw := json.RawMessage(e.Commit.Record)
679
+
record := tangled.Knot{}
680
+
err = json.Unmarshal(raw, &record)
681
+
if err != nil {
682
+
l.Error("invalid record", "err", err)
683
+
return err
684
+
}
685
+
686
+
domain := e.Commit.RKey
687
+
688
+
ddb, ok := i.Db.Execer.(*db.DB)
689
+
if !ok {
690
+
return fmt.Errorf("failed to index profile record, invalid db cast")
691
+
}
692
+
693
+
err := db.AddKnot(ddb, domain, did)
694
+
if err != nil {
695
+
l.Error("failed to add knot to db", "err", err, "domain", domain)
696
+
return err
697
+
}
698
+
699
+
err = serververify.RunVerification(context.Background(), domain, did, i.Config.Core.Dev)
700
+
if err != nil {
701
+
l.Error("failed to verify knot", "err", err, "domain", domain)
702
+
return err
703
+
}
704
+
705
+
err = serververify.MarkKnotVerified(ddb, i.Enforcer, domain, did)
706
+
if err != nil {
707
+
return fmt.Errorf("failed to mark verified: %w", err)
708
+
}
709
+
710
+
return nil
711
+
712
+
case models.CommitOperationDelete:
713
+
domain := e.Commit.RKey
714
+
715
+
ddb, ok := i.Db.Execer.(*db.DB)
716
+
if !ok {
717
+
return fmt.Errorf("failed to index profile record, invalid db cast")
718
+
}
719
+
720
+
// get record from db first
721
+
registration, err := db.RegistrationByDomain(ddb, domain)
722
+
if err != nil {
723
+
return fmt.Errorf("failed to get registration: %w", err)
724
+
}
725
+
726
+
// only allow deletion by the owner
727
+
if registration.ByDid != did {
728
+
return fmt.Errorf("unauthorized deletion attempt")
729
+
}
730
+
731
+
tx, err := ddb.Begin()
732
+
if err != nil {
733
+
return err
734
+
}
735
+
defer func() {
736
+
tx.Rollback()
737
+
i.Enforcer.E.LoadPolicy()
738
+
}()
739
+
740
+
err = db.DeleteKnot(
741
+
tx,
742
+
db.FilterEq("did", did),
743
+
db.FilterEq("domain", domain),
744
+
)
745
+
if err != nil {
746
+
return err
747
+
}
748
+
749
+
if registration.Registered != nil {
750
+
err = i.Enforcer.RemoveKnot(domain)
751
+
if err != nil {
752
+
return err
753
+
}
754
+
}
755
+
756
+
err = tx.Commit()
757
+
if err != nil {
758
+
return err
759
+
}
760
+
761
+
err = i.Enforcer.E.SavePolicy()
762
+
if err != nil {
763
+
return err
764
+
}
765
+
}
766
+
767
+
return nil
768
+
}
+5
rbac/rbac.go
+5
rbac/rbac.go
···
100
100
return err
101
101
}
102
102
103
+
func (e *Enforcer) RemoveKnot(knot string) error {
104
+
_, err := e.E.DeleteDomains(knot)
105
+
return err
106
+
}
107
+
103
108
func (e *Enforcer) GetKnotsForUser(did string) ([]string, error) {
104
109
keepFunc := isNotSpindle
105
110
stripFunc := unSpindle