forked from tangled.org/core
this repo has no description
at test-ci 2.5 kB view raw
1package spindleverify 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "net/http" 9 "strings" 10 "time" 11 12 "tangled.sh/tangled.sh/core/appview/db" 13 "tangled.sh/tangled.sh/core/rbac" 14) 15 16var ( 17 FetchError = errors.New("failed to fetch owner") 18) 19 20// TODO: move this to "spindleclient" or similar 21func fetchOwner(ctx context.Context, domain string, dev bool) (string, error) { 22 scheme := "https" 23 if dev { 24 scheme = "http" 25 } 26 27 url := fmt.Sprintf("%s://%s/owner", scheme, domain) 28 req, err := http.NewRequest("GET", url, nil) 29 if err != nil { 30 return "", err 31 } 32 33 client := &http.Client{ 34 Timeout: 1 * time.Second, 35 } 36 37 resp, err := client.Do(req.WithContext(ctx)) 38 if err != nil || resp.StatusCode != 200 { 39 return "", fmt.Errorf("failed to fetch /owner") 40 } 41 42 body, err := io.ReadAll(io.LimitReader(resp.Body, 1024)) // read atmost 1kb of data 43 if err != nil { 44 return "", fmt.Errorf("failed to read /owner response: %w", err) 45 } 46 47 did := strings.TrimSpace(string(body)) 48 if did == "" { 49 return "", fmt.Errorf("empty DID in /owner response") 50 } 51 52 return did, nil 53} 54 55type OwnerMismatch struct { 56 expected string 57 observed string 58} 59 60func (e *OwnerMismatch) Error() string { 61 return fmt.Sprintf("owner mismatch: %q != %q", e.expected, e.observed) 62} 63 64func RunVerification(ctx context.Context, instance, expectedOwner string, dev bool) error { 65 // begin verification 66 observedOwner, err := fetchOwner(ctx, instance, dev) 67 if err != nil { 68 return fmt.Errorf("%w: %w", FetchError, err) 69 } 70 71 if observedOwner != expectedOwner { 72 return &OwnerMismatch{ 73 expected: expectedOwner, 74 observed: observedOwner, 75 } 76 } 77 78 return nil 79} 80 81// mark this spindle as verified in the DB and add this user as its owner 82func MarkVerified(d *db.DB, e *rbac.Enforcer, instance, owner string) (int64, error) { 83 tx, err := d.Begin() 84 if err != nil { 85 return 0, fmt.Errorf("failed to create txn: %w", err) 86 } 87 defer func() { 88 tx.Rollback() 89 e.E.LoadPolicy() 90 }() 91 92 // mark this spindle as verified in the db 93 rowId, err := db.VerifySpindle( 94 tx, 95 db.FilterEq("owner", owner), 96 db.FilterEq("instance", instance), 97 ) 98 if err != nil { 99 return 0, fmt.Errorf("failed to write to DB: %w", err) 100 } 101 102 err = e.AddSpindleOwner(instance, owner) 103 if err != nil { 104 return 0, fmt.Errorf("failed to update ACL: %w", err) 105 } 106 107 err = tx.Commit() 108 if err != nil { 109 return 0, fmt.Errorf("failed to commit txn: %w", err) 110 } 111 112 err = e.E.SavePolicy() 113 if err != nil { 114 return 0, fmt.Errorf("failed to update ACL: %w", err) 115 } 116 117 return rowId, nil 118}