github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/identify3/adapter.go (about) 1 package identify3 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "strings" 7 "sync" 8 9 "github.com/keybase/client/go/externals" 10 "github.com/keybase/client/go/libkb" 11 keybase1 "github.com/keybase/client/go/protocol/keybase1" 12 ) 13 14 // UIAdapter converts between the Identify2 UI that Identify2 engine expects, and the 15 // Identify3UI interface that the frontend implements. It's maintains the 16 // state machine that was previously implemented in JS. 17 type UIAdapter struct { 18 sync.Mutex 19 session *libkb.Identify3Session 20 ui keybase1.Identify3UiInterface 21 username string 22 iFollowThem bool 23 sentResult bool 24 // An upcall is when the service initiates the ID interaction. 25 // An downcall is when the frontend initiates the ID. 26 // Probably as directed by KBFS or the CLI. 27 // "Tell Nojima we're about to hit him." 28 isUpcall bool 29 priorityMap map[string]int // map from proof key to display priority 30 } 31 32 var _ libkb.IdentifyUI = (*UIAdapter)(nil) 33 34 func NewUIAdapter(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface) (*UIAdapter, error) { 35 ret := &UIAdapter{ 36 ui: ui, 37 } 38 ret.initPriorityMap(mctx) 39 return ret, nil 40 } 41 42 func NewUIAdapterMakeSession(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface, guiid keybase1.Identify3GUIID) (ret *UIAdapter, err error) { 43 sess := libkb.NewIdentify3SessionWithID(mctx, guiid) 44 err = mctx.G().Identify3State.Put(sess) 45 if err != nil { 46 return nil, err 47 } 48 49 ret, err = NewUIAdapterWithSession(mctx, ui, sess) 50 if err != nil { 51 return nil, err 52 } 53 return ret, nil 54 } 55 56 func NewUIAdapterMakeSessionForUpcall(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface) (ret *UIAdapter, err error) { 57 guiid, err := libkb.NewIdentify3GUIID() 58 if err != nil { 59 return nil, err 60 } 61 ret, err = NewUIAdapterMakeSession(mctx, ui, guiid) 62 if err != nil { 63 return nil, err 64 } 65 ret.isUpcall = true 66 return ret, nil 67 } 68 69 func NewUIAdapterWithSession(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface, sess *libkb.Identify3Session) (*UIAdapter, error) { 70 ret, err := NewUIAdapter(mctx, ui) 71 if err != nil { 72 return nil, err 73 } 74 ret.session = sess 75 return ret, nil 76 } 77 78 func (i *UIAdapter) Start(mctx libkb.MetaContext, user string, reason keybase1.IdentifyReason, force bool) error { 79 i.Lock() 80 i.username = user 81 i.Unlock() 82 83 if !i.isUpcall { 84 return nil 85 } 86 arg := keybase1.Identify3ShowTrackerArg{ 87 GuiID: i.session.ID(), 88 Assertion: keybase1.Identify3Assertion(user), 89 Reason: reason, 90 ForceDisplay: true, 91 } 92 93 err := i.ui.Identify3ShowTracker(mctx.Ctx(), arg) 94 if err != nil { 95 mctx.Debug("Failed to call Identify3ShowTracker: %s", err) 96 } 97 return err 98 } 99 100 func (i *UIAdapter) initPriorityMap(mctx libkb.MetaContext) { 101 i.priorityMap = make(map[string]int) 102 var haveDisplayConfigs bool 103 for _, displayConfig := range mctx.G().GetProofServices().ListDisplayConfigs(mctx) { 104 haveDisplayConfigs = true 105 i.priorityMap[displayConfig.Key] = displayConfig.Priority 106 var altKey string 107 switch displayConfig.Key { 108 case "zcash.t", "zcash.z", "zcash.s": 109 altKey = "zcash" 110 case "bitcoin": 111 altKey = "btc" 112 case "http", "https", "dns": 113 altKey = "web" 114 } 115 if len(altKey) > 0 { 116 if _, ok := i.priorityMap[altKey]; !ok { 117 i.priorityMap[altKey] = displayConfig.Priority 118 } 119 } 120 } 121 if !haveDisplayConfigs { 122 i.priorityMap["twitter"] = 1 123 i.priorityMap["https"] = 100 124 i.priorityMap["http"] = 101 125 i.priorityMap["dns"] = 102 126 i.priorityMap["pgp"] = 103 127 i.priorityMap["bitcoin"] = 104 128 i.priorityMap["zcash.s"] = 105 129 i.priorityMap["zcash.z"] = 106 130 i.priorityMap["zcash.t"] = 107 131 i.priorityMap["stellar"] = 108 132 i.priorityMap["github"] = 2 133 i.priorityMap["reddit"] = 3 134 i.priorityMap["hackernews"] = 4 135 i.priorityMap["facebook"] = 5 136 } 137 } 138 139 func (i *UIAdapter) priority(key string) int { 140 if i.priorityMap == nil { 141 return 0 // should be impossible but don't crash. 142 } 143 p, ok := i.priorityMap[key] 144 if !ok { 145 // Put it at the bottom of the list. 146 return 9999999 147 } 148 return p 149 } 150 151 func (i *UIAdapter) getColorForValid(following bool) keybase1.Identify3RowColor { 152 if following { 153 return keybase1.Identify3RowColor_GREEN 154 } 155 return keybase1.Identify3RowColor_BLUE 156 } 157 158 // return true if we need an upgrade 159 func (i *UIAdapter) setRowStatus(mctx libkb.MetaContext, arg *keybase1.Identify3Row, lcr keybase1.LinkCheckResult) bool { 160 161 needUpgrade := false 162 mctx.Debug("ID3: setRowStatus(lcr: %+v, cached: %+v, diff: %+v, remoteDiff: %+v, hint: %+v)", 163 lcr, lcr.Cached, lcr.Diff, lcr.RemoteDiff, lcr.Hint) 164 165 switch { 166 // The proof worked, and either we tracked it as working, or we didn't track it at all. 167 case (lcr.ProofResult.State == keybase1.ProofState_OK && (lcr.RemoteDiff == nil || lcr.RemoteDiff.Type == keybase1.TrackDiffType_NONE)): 168 arg.Color = i.getColorForValid(lcr.RemoteDiff != nil) 169 arg.State = keybase1.Identify3RowState_VALID 170 171 // The proof worked, and it's new to us. 172 case lcr.ProofResult.State == keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_NEW: 173 arg.Color = keybase1.Identify3RowColor_BLUE 174 arg.State = keybase1.Identify3RowState_VALID 175 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "new"}) 176 needUpgrade = true 177 178 // The proof worked, and it's upgraded. 179 case lcr.ProofResult.State == keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_UPGRADED: 180 arg.Color = keybase1.Identify3RowColor_BLUE 181 arg.State = keybase1.Identify3RowState_VALID 182 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "upgraded"}) 183 needUpgrade = true 184 185 // The proof worked, we tracked failed, and now it's working 186 case lcr.ProofResult.State == keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_REMOTE_WORKING: 187 arg.Color = keybase1.Identify3RowColor_BLUE 188 arg.State = keybase1.Identify3RowState_VALID 189 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "new"}) 190 needUpgrade = true 191 192 // The proof failed, but we didn't track it 193 case lcr.ProofResult.State != keybase1.ProofState_OK && lcr.RemoteDiff == nil: 194 arg.Color = keybase1.Identify3RowColor_ORANGE 195 arg.State = keybase1.Identify3RowState_WARNING 196 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "unreachable"}) 197 198 // The proof failed, but we did "ignore" it, so it's OK 199 case lcr.ProofResult.State != keybase1.ProofState_OK && (lcr.RemoteDiff == nil || lcr.RemoteDiff.Type == keybase1.TrackDiffType_NONE): 200 arg.Color = keybase1.Identify3RowColor_GREEN 201 arg.State = keybase1.Identify3RowState_WARNING 202 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "ignored"}) 203 204 // The proof failed, but we did "ignore" it via "SNOONZE", so it's OK, for now. 205 case lcr.ProofResult.State != keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_NONE_VIA_TEMPORARY: 206 arg.Color = keybase1.Identify3RowColor_YELLOW 207 arg.State = keybase1.Identify3RowState_WARNING 208 arg.Metas = append(arg.Metas, 209 keybase1.Identify3RowMeta{Color: arg.Color, Label: "ignored"}, 210 keybase1.Identify3RowMeta{Color: arg.Color, Label: "temporary"}, 211 ) 212 213 // The proof failed, we did track it, and it didn't match our track 214 case lcr.ProofResult.State != keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type != keybase1.TrackDiffType_NONE: 215 arg.Color = keybase1.Identify3RowColor_RED 216 arg.State = keybase1.Identify3RowState_ERROR 217 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "unreachable"}) 218 219 default: 220 mctx.Warning("unhandled ID3 setRowStatus") 221 222 } 223 return needUpgrade 224 } 225 226 func (i *UIAdapter) rowPartial(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr *keybase1.LinkCheckResult) (row keybase1.Identify3Row) { 227 row = keybase1.Identify3Row{ 228 Key: proof.Key, 229 Value: proof.Value, 230 SigID: proof.SigID, 231 Ctime: proof.MTime, // It's what we've got. 232 Priority: i.priority(proof.Key), 233 } 234 235 var humanURLOrSigchainURL string 236 if lcr != nil && lcr.Hint != nil { 237 humanURLOrSigchainURL = lcr.Hint.HumanUrl 238 } 239 if len(humanURLOrSigchainURL) == 0 { 240 humanURLOrSigchainURL = i.makeSigchainViewURL(mctx, proof.SigID) 241 } 242 243 row.ProofURL = humanURLOrSigchainURL 244 switch proof.ProofType { 245 case keybase1.ProofType_TWITTER: 246 row.SiteURL = fmt.Sprintf("https://twitter.com/%v", proof.Value) 247 case keybase1.ProofType_GITHUB: 248 row.SiteURL = fmt.Sprintf("https://github.com/%v", proof.Value) 249 case keybase1.ProofType_REDDIT: 250 row.SiteURL = fmt.Sprintf("https://reddit.com/user/%v", proof.Value) 251 case keybase1.ProofType_HACKERNEWS: 252 // hackernews profile urls must have the username in its original casing. 253 username := proof.Value 254 if libkb.Cicmp(proof.Value, proof.DisplayMarkup) { 255 username = proof.DisplayMarkup 256 } 257 row.SiteURL = fmt.Sprintf("https://news.ycombinator.com/user?id=%v", username) 258 case keybase1.ProofType_FACEBOOK: 259 row.SiteURL = fmt.Sprintf("https://facebook.com/%v", proof.Value) 260 case keybase1.ProofType_GENERIC_SOCIAL: 261 row.SiteURL = humanURLOrSigchainURL 262 serviceType := mctx.G().GetProofServices().GetServiceType(mctx.Ctx(), proof.Key) 263 if serviceType != nil { 264 if serviceType, ok := serviceType.(*externals.GenericSocialProofServiceType); ok { 265 profileURL, err := serviceType.ProfileURL(proof.Value) 266 if err == nil { 267 row.SiteURL = profileURL 268 } 269 } 270 } 271 row.ProofURL = i.makeSigchainViewURL(mctx, proof.SigID) 272 case keybase1.ProofType_GENERIC_WEB_SITE: 273 protocol := "https" 274 if proof.Key != "https" { 275 protocol = "http" 276 } 277 row.SiteURL = fmt.Sprintf("%v://%v", protocol, proof.Value) 278 case keybase1.ProofType_DNS: 279 row.SiteURL = fmt.Sprintf("http://%v", proof.Value) 280 row.ProofURL = i.makeSigchainViewURL(mctx, proof.SigID) 281 default: 282 row.SiteURL = humanURLOrSigchainURL 283 } 284 iconKey := libkb.ProofIconKey(mctx, proof.ProofType, proof.Key) 285 row.SiteIcon = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeSmall, 16) 286 row.SiteIconDarkmode = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeSmallDarkmode, 16) 287 row.SiteIconFull = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeFull, 64) 288 row.SiteIconFullDarkmode = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeFullDarkmode, 64) 289 switch proof.ProofType { 290 case keybase1.ProofType_NONE, keybase1.ProofType_PGP: 291 // These types are not eligible for web-of-trust selection. 292 default: 293 wotProof, err := libkb.NewWotProof(proof.ProofType, proof.Key, proof.Value) 294 if err != nil { 295 mctx.Debug("Error creating web-of-trust proof summary: %v", err) 296 } else { 297 row.WotProof = &wotProof 298 } 299 } 300 return row 301 } 302 303 func (i *UIAdapter) finishRemoteCheck(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr keybase1.LinkCheckResult) error { 304 if lcr.BreaksTracking { 305 i.session.SetTrackBroken() 306 } 307 308 arg := i.rowPartial(mctx, proof, &lcr) 309 needUpgrade := i.setRowStatus(mctx, &arg, lcr) 310 if needUpgrade { 311 i.session.SetNeedUpgrade() 312 } 313 314 i.updateRow(mctx, arg) 315 return nil 316 } 317 318 func (i *UIAdapter) FinishWebProofCheck(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr keybase1.LinkCheckResult) error { 319 return i.finishRemoteCheck(mctx, proof, lcr) 320 } 321 322 func (i *UIAdapter) FinishSocialProofCheck(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr keybase1.LinkCheckResult) error { 323 return i.finishRemoteCheck(mctx, proof, lcr) 324 } 325 326 func (i *UIAdapter) Confirm(libkb.MetaContext, *keybase1.IdentifyOutcome) (keybase1.ConfirmResult, error) { 327 return keybase1.ConfirmResult{}, nil 328 } 329 330 func (i *UIAdapter) DisplayCryptocurrency(mctx libkb.MetaContext, cc keybase1.Cryptocurrency) error { 331 i.plumbCryptocurrency(mctx, cc) 332 return nil 333 } 334 335 func (i *UIAdapter) DisplayStellarAccount(mctx libkb.MetaContext, s keybase1.StellarAccount) error { 336 i.plumbStellarAccount(mctx, s) 337 return nil 338 } 339 340 func (i *UIAdapter) DisplayKey(mctx libkb.MetaContext, key keybase1.IdentifyKey) error { 341 if key.BreaksTracking { 342 i.session.SetTrackBroken() 343 } 344 i.checkEldest(mctx, key) 345 i.displayKey(mctx, key) 346 return nil 347 } 348 349 func (i *UIAdapter) displayKey(mctx libkb.MetaContext, key keybase1.IdentifyKey) { 350 if key.PGPFingerprint == nil { 351 return 352 } 353 354 arg := keybase1.Identify3Row{ 355 Key: "pgp", 356 Value: hex.EncodeToString(key.PGPFingerprint), 357 SigID: key.SigID, 358 Ctime: 0, 359 Priority: i.priority("pgp"), 360 SiteURL: i.makeKeybaseProfileURL(mctx), 361 // key.SigID is blank if the PGP key was there pre-sigchain 362 ProofURL: i.makeSigchainViewURL(mctx, key.SigID), 363 SiteIcon: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeSmall, 16), 364 SiteIconDarkmode: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeSmallDarkmode, 16), 365 SiteIconFull: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeFull, 64), 366 SiteIconFullDarkmode: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeFullDarkmode, 64), 367 Kid: &key.KID, 368 // PICNIC-1092 consider adding `WotProof` to support pgp in web-of-trust. 369 } 370 371 switch { 372 case key.TrackDiff == nil || key.TrackDiff.Type == keybase1.TrackDiffType_NONE: 373 arg.State = keybase1.Identify3RowState_VALID 374 arg.Color = i.getColorForValid(key.TrackDiff != nil) 375 case key.TrackDiff != nil && (key.TrackDiff.Type == keybase1.TrackDiffType_REVOKED || key.TrackDiff.Type == keybase1.TrackDiffType_NEW_ELDEST): 376 arg.State = keybase1.Identify3RowState_REVOKED 377 arg.Color = keybase1.Identify3RowColor_RED 378 case key.TrackDiff != nil && key.TrackDiff.Type == keybase1.TrackDiffType_NEW: 379 arg.State = keybase1.Identify3RowState_VALID 380 arg.Color = keybase1.Identify3RowColor_BLUE 381 arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "new"}) 382 default: 383 mctx.Warning("unhandled ID3 setRowStatus in displayKey: %+v", key) 384 } 385 386 i.updateRow(mctx, arg) 387 } 388 389 func (i *UIAdapter) checkEldest(mctx libkb.MetaContext, key keybase1.IdentifyKey) { 390 if key.TrackDiff == nil || key.TrackDiff.Type != keybase1.TrackDiffType_NEW_ELDEST { 391 return 392 } 393 err := i.ui.Identify3UserReset(mctx.Ctx(), i.session.ID()) 394 if err != nil { 395 mctx.Debug("Error sending user reset message: %s", err) 396 } 397 } 398 399 func (i *UIAdapter) ReportLastTrack(mctx libkb.MetaContext, track *keybase1.TrackSummary) error { 400 if track != nil { 401 i.Lock() 402 i.iFollowThem = true 403 i.Unlock() 404 } 405 return nil 406 } 407 408 func (i *UIAdapter) plumbUncheckedProofs(mctx libkb.MetaContext, proofs []keybase1.IdentifyRow) { 409 err := i.ui.Identify3Summary(mctx.Ctx(), keybase1.Identify3Summary{ 410 GuiID: i.session.ID(), 411 NumProofsToCheck: len(proofs), 412 }) 413 if err != nil { 414 mctx.Debug("Identify3Summary call failed: %s", err.Error()) 415 } 416 for _, proof := range proofs { 417 i.plumbUncheckedProof(mctx, proof) 418 } 419 } 420 421 func (i *UIAdapter) plumbUncheckedProof(mctx libkb.MetaContext, row keybase1.IdentifyRow) { 422 arg := i.rowPartial(mctx, row.Proof, nil) 423 arg.State = keybase1.Identify3RowState_CHECKING 424 arg.Color = keybase1.Identify3RowColor_GRAY 425 i.updateRow(mctx, arg) 426 } 427 428 func (i *UIAdapter) updateRow(mctx libkb.MetaContext, arg keybase1.Identify3Row) { 429 arg.GuiID = i.session.ID() 430 err := i.ui.Identify3UpdateRow(mctx.Ctx(), arg) 431 mctx.Debug("update row %+v", arg) 432 if err != nil { 433 mctx.Debug("Failed to send update row (%+v): %s", arg, err) 434 } 435 } 436 437 func (i *UIAdapter) shouldSkipSendResult() bool { 438 i.Lock() 439 defer i.Unlock() 440 if i.sentResult { 441 return true 442 } 443 i.sentResult = true 444 return false 445 } 446 447 func (i *UIAdapter) sendResult(mctx libkb.MetaContext, typ keybase1.Identify3ResultType) error { 448 if i.shouldSkipSendResult() { 449 mctx.Debug("Skipping send result, already done") 450 return nil 451 } 452 arg := keybase1.Identify3ResultArg{ 453 GuiID: i.session.ID(), 454 Result: typ, 455 } 456 457 err := i.ui.Identify3Result(mctx.Ctx(), arg) 458 if err != nil { 459 mctx.Debug("Failed to send result (%+v): %s", arg, err) 460 } 461 return err 462 } 463 464 func (i *UIAdapter) makeKeybaseProfileURL(mctx libkb.MetaContext) string { 465 url := libkb.SiteURILookup[mctx.G().Env.GetRunMode()] 466 var parts []string 467 if url == "" { 468 return url 469 } 470 parts = append(parts, url, i.username) 471 return strings.Join(parts, "/") 472 } 473 474 func (i *UIAdapter) makeSigchainViewURL(mctx libkb.MetaContext, s keybase1.SigID) string { 475 url := libkb.SiteURILookup[mctx.G().Env.GetRunMode()] 476 var parts []string 477 if url == "" { 478 return url 479 } 480 parts = append(parts, url, i.username) 481 page := "sigchain" 482 if !s.IsNil() { 483 page = page + "#" + s.String() 484 } 485 parts = append(parts, page) 486 return strings.Join(parts, "/") 487 } 488 489 func (i *UIAdapter) plumbCryptocurrency(mctx libkb.MetaContext, crypto keybase1.Cryptocurrency) { 490 key := crypto.Type 491 switch crypto.Family { 492 case string(libkb.CryptocurrencyFamilyBitcoin): 493 key = "btc" 494 case string(libkb.CryptocurrencyFamilyZCash): 495 key = "zcash" 496 default: 497 mctx.Debug("unrecgonized crypto family: %v, %v", crypto.Type, crypto.Family) 498 } 499 i.updateRow(mctx, keybase1.Identify3Row{ 500 Key: key, 501 Value: crypto.Address, 502 Priority: i.priority(key), 503 State: keybase1.Identify3RowState_VALID, 504 Color: i.getColorForValid(i.iFollowThem), 505 SigID: crypto.SigID, 506 Ctime: 0, 507 SiteURL: i.makeSigchainViewURL(mctx, crypto.SigID), 508 SiteIcon: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeSmall, 16), 509 SiteIconDarkmode: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeSmallDarkmode, 16), 510 SiteIconFull: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeFull, 64), 511 SiteIconFullDarkmode: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeFullDarkmode, 64), 512 ProofURL: i.makeSigchainViewURL(mctx, crypto.SigID), 513 }) 514 } 515 516 func (i *UIAdapter) plumbStellarAccount(mctx libkb.MetaContext, str keybase1.StellarAccount) { 517 color := i.getColorForValid(i.iFollowThem) 518 if str.Hidden { 519 color = keybase1.Identify3RowColor_GRAY 520 } 521 i.updateRow(mctx, keybase1.Identify3Row{ 522 Key: "stellar", 523 Value: str.FederationAddress, 524 Priority: i.priority("stellar"), 525 State: keybase1.Identify3RowState_VALID, 526 Color: color, 527 SigID: str.SigID, 528 Ctime: 0, 529 SiteURL: i.makeSigchainViewURL(mctx, str.SigID), 530 SiteIcon: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeSmall, 16), 531 SiteIconDarkmode: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeSmallDarkmode, 16), 532 SiteIconFull: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeFull, 64), 533 SiteIconFullDarkmode: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeFullDarkmode, 64), 534 ProofURL: i.makeSigchainViewURL(mctx, str.SigID), 535 }) 536 } 537 538 func (i *UIAdapter) plumbRevoked(mctx libkb.MetaContext, row keybase1.RevokedProof) { 539 arg := i.rowPartial(mctx, row.Proof, nil) 540 arg.State = keybase1.Identify3RowState_REVOKED 541 arg.Color = keybase1.Identify3RowColor_RED 542 arg.Metas = append(arg.Metas, 543 keybase1.Identify3RowMeta{Color: arg.Color, Label: "revoked"}, 544 ) 545 i.updateRow(mctx, arg) 546 } 547 548 func (i *UIAdapter) plumbRevokeds(mctx libkb.MetaContext, rows []keybase1.RevokedProof) { 549 for _, row := range rows { 550 i.plumbRevoked(mctx, row) 551 } 552 } 553 554 func (i *UIAdapter) LaunchNetworkChecks(mctx libkb.MetaContext, id *keybase1.Identity, user *keybase1.User) error { 555 556 if id.BreaksTracking { 557 i.session.SetTrackBroken() 558 } 559 i.plumbUncheckedProofs(mctx, id.Proofs) 560 i.plumbRevokeds(mctx, id.RevokedDetails) 561 562 return nil 563 } 564 565 func (i *UIAdapter) DisplayTrackStatement(libkb.MetaContext, string) error { 566 return nil 567 } 568 569 func (i *UIAdapter) DisplayUserCard(mctx libkb.MetaContext, card keybase1.UserCard) error { 570 arg := keybase1.Identify3UpdateUserCardArg{ 571 GuiID: i.session.ID(), 572 Card: card, 573 } 574 err := i.ui.Identify3UpdateUserCard(mctx.Ctx(), arg) 575 if err != nil { 576 mctx.Debug("Failed to send update card: %s", err) 577 } 578 return nil 579 } 580 581 func (i *UIAdapter) ReportTrackToken(mctx libkb.MetaContext, token keybase1.TrackToken) error { 582 outcome, err := mctx.G().TrackCache().Get(token) 583 if err != nil { 584 return err 585 } 586 i.session.SetOutcome(outcome) 587 return nil 588 } 589 590 func (i *UIAdapter) Cancel(mctx libkb.MetaContext) error { 591 _ = i.sendResult(mctx, keybase1.Identify3ResultType_CANCELED) 592 return nil 593 } 594 595 func (i *UIAdapter) Finish(mctx libkb.MetaContext) error { 596 _ = i.sendResult(mctx, i.session.ResultType()) 597 return nil 598 } 599 func (i *UIAdapter) DisplayTLFCreateWithInvite(libkb.MetaContext, keybase1.DisplayTLFCreateWithInviteArg) error { 600 return nil 601 } 602 func (i *UIAdapter) Dismiss(libkb.MetaContext, string, keybase1.DismissReason) error { 603 return nil 604 }