forked from tangled.org/core
this repo has no description

appview: improve spindle verification process

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 2a45e84f 45882b6b

verified
Changed files
+74 -15
appview
db
pages
templates
repo
spindles
repo
spindles
spindle
+7 -2
appview/db/spindle.go
··· 51 for rows.Next() { 52 var spindle Spindle 53 var createdAt string 54 - var verified sql.NullTime 55 56 if err := rows.Scan( 57 &spindle.Id, ··· 69 } 70 71 if verified.Valid { 72 - spindle.Verified = &verified.Time 73 } 74 75 spindles = append(spindles, spindle)
··· 51 for rows.Next() { 52 var spindle Spindle 53 var createdAt string 54 + var verified sql.NullString 55 56 if err := rows.Scan( 57 &spindle.Id, ··· 69 } 70 71 if verified.Valid { 72 + t, err := time.Parse(time.RFC3339, verified.String) 73 + if err != nil { 74 + now := time.Now() 75 + spindle.Verified = &now 76 + } 77 + spindle.Verified = &t 78 } 79 80 spindles = append(spindles, spindle)
+2 -2
appview/pages/templates/repo/new.html
··· 60 </fieldset> 61 62 <div class="space-y-2"> 63 - <button type="submit" class="btn flex gap-2 items-center"> 64 create repo 65 <span id="spinner" class="group"> 66 - {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 67 </span> 68 </button> 69 <div id="repo" class="error"></div>
··· 60 </fieldset> 61 62 <div class="space-y-2"> 63 + <button type="submit" class="btn flex items-center"> 64 create repo 65 <span id="spinner" class="group"> 66 + {{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 67 </span> 68 </button> 69 <div id="repo" class="error"></div>
+3 -3
appview/pages/templates/repo/settings.html
··· 83 84 {{ if .RepoInfo.Roles.IsOwner }} 85 <form 86 - hx-put="/{{ $.RepoInfo.FullName }}/settings/spindle" 87 class="mt-6 group" 88 > 89 <label for="spindle">spindle</label> ··· 100 <option 101 value="{{ . }}" 102 class="py-1" 103 - {{ if .eq . $.Repo.Spindle }} 104 selected 105 {{ end }} 106 > ··· 127 <button class="btn my-2 flex items-center" type="text"> 128 <span>delete</span> 129 <span id="delete-repo-spinner" class="group"> 130 - {{ i "loader-circle" "pl-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 131 </span> 132 </button> 133 <span>
··· 83 84 {{ if .RepoInfo.Roles.IsOwner }} 85 <form 86 + hx-post="/{{ $.RepoInfo.FullName }}/settings/spindle" 87 class="mt-6 group" 88 > 89 <label for="spindle">spindle</label> ··· 100 <option 101 value="{{ . }}" 102 class="py-1" 103 + {{ if eq . $.CurrentSpindle }} 104 selected 105 {{ end }} 106 > ··· 127 <button class="btn my-2 flex items-center" type="text"> 128 <span>delete</span> 129 <span id="delete-repo-spinner" class="group"> 130 + {{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 131 </span> 132 </button> 133 <span>
+2 -2
appview/pages/templates/spindles/fragments/spindleListing.html
··· 24 <button 25 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 26 title="Delete spindle" 27 - hx-delete="/spindles/{{ urlquery .Instance }}" 28 hx-swap="outerHTML" 29 hx-target="#spindle-{{.Id}}" 30 hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?" ··· 40 <button 41 class="btn gap-2 group" 42 title="Retry spindle verification" 43 - hx-post="/spindles/{{ urlquery .Instance }}/retry" 44 hx-swap="none" 45 hx-target="#spindle-{{.Id}}" 46 >
··· 24 <button 25 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 26 title="Delete spindle" 27 + hx-delete="/spindles/{{ .Instance }}" 28 hx-swap="outerHTML" 29 hx-target="#spindle-{{.Id}}" 30 hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?" ··· 40 <button 41 class="btn gap-2 group" 42 title="Retry spindle verification" 43 + hx-post="/spindles/{{ .Instance }}/retry" 44 hx-swap="none" 45 hx-target="#spindle-{{.Id}}" 46 >
+1
appview/repo/repo.go
··· 1108 return 1109 } 1110 1111 spindles, err := rp.enforcer.GetSpindlesForUser(user.Did) 1112 if err != nil { 1113 log.Println("failed to fetch spindles", err)
··· 1108 return 1109 } 1110 1111 + // all spindles that this user is a member of 1112 spindles, err := rp.enforcer.GetSpindlesForUser(user.Did) 1113 if err != nil { 1114 log.Println("failed to fetch spindles", err)
+46
appview/spindles/spindles.go
··· 54 ) 55 if err != nil { 56 s.Logger.Error("failed to fetch spindles", "err", err) 57 } 58 59 s.Pages.Spindles(w, pages.SpindlesParams{ ··· 150 return 151 } 152 153 // ok 154 s.Pages.HxRefresh(w) 155 return ··· 255 db.FilterEq("owner", user.Did), 256 db.FilterEq("instance", instance), 257 ) 258 259 verifiedSpindle := db.Spindle{ 260 Id: int(rowId),
··· 54 ) 55 if err != nil { 56 s.Logger.Error("failed to fetch spindles", "err", err) 57 + w.WriteHeader(http.StatusInternalServerError) 58 + return 59 } 60 61 s.Pages.Spindles(w, pages.SpindlesParams{ ··· 152 return 153 } 154 155 + tx, err = s.Db.Begin() 156 + if err != nil { 157 + l.Error("failed to commit verification info", "err", err) 158 + s.Pages.HxRefresh(w) 159 + return 160 + } 161 + defer func() { 162 + tx.Rollback() 163 + s.Enforcer.E.LoadPolicy() 164 + }() 165 + 166 + // mark this spindle as verified in the db 167 + _, err = db.VerifySpindle( 168 + tx, 169 + db.FilterEq("owner", user.Did), 170 + db.FilterEq("instance", instance), 171 + ) 172 + 173 + err = s.Enforcer.AddSpindleOwner(instance, user.Did) 174 + if err != nil { 175 + l.Error("failed to update ACL", "err", err) 176 + s.Pages.HxRefresh(w) 177 + return 178 + } 179 + 180 + err = tx.Commit() 181 + if err != nil { 182 + l.Error("failed to commit verification info", "err", err) 183 + s.Pages.HxRefresh(w) 184 + return 185 + } 186 + 187 + err = s.Enforcer.E.SavePolicy() 188 + if err != nil { 189 + l.Error("failed to update ACL", "err", err) 190 + s.Pages.HxRefresh(w) 191 + return 192 + } 193 + 194 // ok 195 s.Pages.HxRefresh(w) 196 return ··· 296 db.FilterEq("owner", user.Did), 297 db.FilterEq("instance", instance), 298 ) 299 + if err != nil { 300 + l.Error("verification failed", "err", err) 301 + fail() 302 + return 303 + } 304 305 verifiedSpindle := db.Spindle{ 306 Id: int(rowId),
+6 -5
spindle/ingester.go
··· 59 if s.cfg.Server.Dev { 60 domain = s.cfg.Server.ListenAddr 61 } 62 - recordInstance := *record.Instance 63 64 if recordInstance != domain { 65 l.Error("domain mismatch", "domain", recordInstance, "expected", domain) 66 - return fmt.Errorf("domain mismatch: %s != %s", *record.Instance, domain) 67 } 68 69 ok, err := s.e.E.Enforce(did, rbacDomain, rbacDomain, "server:invite") ··· 95 96 l := s.l.With("component", "ingester", "record", tangled.RepoNSID) 97 98 switch e.Commit.Operation { 99 case models.CommitOperationCreate, models.CommitOperationUpdate: 100 raw := e.Commit.Record ··· 106 } 107 108 domain := s.cfg.Server.Hostname 109 - if s.cfg.Server.Dev { 110 - domain = s.cfg.Server.ListenAddr 111 - } 112 113 // no spindle configured for this repo 114 if record.Spindle == nil { 115 return nil 116 } 117 118 // this repo did not want this spindle 119 if *record.Spindle != domain { 120 return nil 121 } 122
··· 59 if s.cfg.Server.Dev { 60 domain = s.cfg.Server.ListenAddr 61 } 62 + recordInstance := record.Instance 63 64 if recordInstance != domain { 65 l.Error("domain mismatch", "domain", recordInstance, "expected", domain) 66 + return fmt.Errorf("domain mismatch: %s != %s", record.Instance, domain) 67 } 68 69 ok, err := s.e.E.Enforce(did, rbacDomain, rbacDomain, "server:invite") ··· 95 96 l := s.l.With("component", "ingester", "record", tangled.RepoNSID) 97 98 + l.Info("ingesting repo record") 99 + 100 switch e.Commit.Operation { 101 case models.CommitOperationCreate, models.CommitOperationUpdate: 102 raw := e.Commit.Record ··· 108 } 109 110 domain := s.cfg.Server.Hostname 111 112 // no spindle configured for this repo 113 if record.Spindle == nil { 114 + l.Info("no spindle configured", "did", record.Owner, "name", record.Name) 115 return nil 116 } 117 118 // this repo did not want this spindle 119 if *record.Spindle != domain { 120 + l.Info("different spindle configured", "did", record.Owner, "name", record.Name, "spindle", *record.Spindle, "domain", domain) 121 return nil 122 } 123
+7 -1
spindle/server.go
··· 66 67 jq := queue.NewQueue(100, 2) 68 69 - collections := []string{tangled.SpindleMemberNSID} 70 jc, err := jetstream.NewJetstreamClient(cfg.Server.JetstreamEndpoint, "spindle", collections, nil, logger, d, false, false) 71 if err != nil { 72 return fmt.Errorf("failed to setup jetstream client: %w", err) ··· 140 mux := chi.NewRouter() 141 142 mux.HandleFunc("/events", s.Events) 143 mux.HandleFunc("/logs/{knot}/{rkey}/{name}", s.Logs) 144 return mux 145 }
··· 66 67 jq := queue.NewQueue(100, 2) 68 69 + collections := []string{ 70 + tangled.SpindleMemberNSID, 71 + tangled.RepoNSID, 72 + } 73 jc, err := jetstream.NewJetstreamClient(cfg.Server.JetstreamEndpoint, "spindle", collections, nil, logger, d, false, false) 74 if err != nil { 75 return fmt.Errorf("failed to setup jetstream client: %w", err) ··· 143 mux := chi.NewRouter() 144 145 mux.HandleFunc("/events", s.Events) 146 + mux.HandleFunc("/owner", func(w http.ResponseWriter, r *http.Request) { 147 + w.Write([]byte(s.cfg.Server.Owner)) 148 + }) 149 mux.HandleFunc("/logs/{knot}/{rkey}/{name}", s.Logs) 150 return mux 151 }