Monorepo for Tangled tangled.org
5

Configure Feed

Select the types of activity you want to include in your feed.

1package spindle 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "log/slog" 8 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 "tangled.org/core/spindle/db" 11 "tangled.org/core/spindle/secrets" 12) 13 14func copyRepoSecrets(ctx context.Context, mgr secrets.Manager, src, dst secrets.RepoIdentifier) (int, error) { 15 cur, err := mgr.GetSecretsUnlocked(ctx, src) 16 if err != nil { 17 return 0, fmt.Errorf("get %s: %w", src, err) 18 } 19 var step func(remaining []secrets.UnlockedSecret, copied int) (int, error) 20 step = func(remaining []secrets.UnlockedSecret, copied int) (int, error) { 21 if len(remaining) == 0 { 22 return copied, nil 23 } 24 s := remaining[0] 25 addErr := mgr.AddSecret(ctx, secrets.UnlockedSecret{ 26 Repo: dst, 27 Key: s.Key, 28 Value: s.Value, 29 CreatedAt: s.CreatedAt, 30 CreatedBy: s.CreatedBy, 31 }) 32 switch { 33 case addErr == nil: 34 return step(remaining[1:], copied+1) 35 case errors.Is(addErr, secrets.ErrKeyAlreadyPresent): 36 return step(remaining[1:], copied) 37 default: 38 return copied, fmt.Errorf("add %s/%s: %w", dst, s.Key, addErr) 39 } 40 } 41 return step(cur, 0) 42} 43 44func legacyKeyCandidates(owner syntax.DID, name string, rkey syntax.RecordKey) []string { 45 o := owner.String() 46 r := rkey.String() 47 switch { 48 case name == "" && r == "": 49 return nil 50 case name == "": 51 return []string{o + "/" + r} 52 case r == "" || name == r: 53 return []string{o + "/" + name} 54 default: 55 return []string{o + "/" + name, o + "/" + r} 56 } 57} 58 59func migrateLegacyRepoSecrets(ctx context.Context, d *db.DB, vault secrets.Manager, logger *slog.Logger, owner syntax.DID, name string, rkey syntax.RecordKey, repoDid syntax.DID) { 60 candidates := legacyKeyCandidates(owner, name, rkey) 61 if len(candidates) == 0 { 62 return 63 } 64 flag := "legacy-secret-copy:" + repoDid.String() + ":" + rkey.String() 65 var exists bool 66 if err := d.QueryRowContext(ctx, `select exists (select 1 from migrations where name = ?)`, flag).Scan(&exists); err != nil { 67 logger.Warn("legacy secret copy: check migration flag", "err", err) 68 return 69 } 70 if exists { 71 return 72 } 73 74 newID := secrets.RepoIdentifier(repoDid.String()) 75 var step func(remaining []string, copied int) (int, error) 76 step = func(remaining []string, copied int) (int, error) { 77 if len(remaining) == 0 { 78 return copied, nil 79 } 80 oldID := secrets.RepoIdentifier(remaining[0]) 81 n, err := copyRepoSecrets(ctx, vault, oldID, newID) 82 if err != nil { 83 return copied, fmt.Errorf("copy %s -> %s: %w", oldID, newID, err) 84 } 85 return step(remaining[1:], copied+n) 86 } 87 total, err := step(candidates, 0) 88 if err != nil { 89 logger.Warn("legacy secret copy failed", "err", err) 90 return 91 } 92 93 if _, err := d.ExecContext(ctx, `insert or ignore into migrations (name) values (?)`, flag); err != nil { 94 logger.Warn("legacy secret copy: mark flag failed", "err", err) 95 return 96 } 97 logger.Info("legacy secret migrate done", "owner", owner, "name", name, "rkey", rkey, "repoDid", repoDid, "candidates", candidates, "copied", total) 98}