/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/identify3/adapter.go
604 строки
20 KB
zoom-ua
gofumpt (#28710)
17 дек 2025, 17:16
Не верифицирован
17 дек 2025, 17:16
cda510b
Код
Авторство
О чём код?
package identify3 import ( "encoding/hex" "fmt" "strings" "sync" "github.com/keybase/client/go/externals" "github.com/keybase/client/go/libkb" keybase1 "github.com/keybase/client/go/protocol/keybase1" ) // UIAdapter converts between the Identify2 UI that Identify2 engine expects, and the // Identify3UI interface that the frontend implements. It's maintains the // state machine that was previously implemented in JS. type UIAdapter struct { sync.Mutex session *libkb.Identify3Session ui keybase1.Identify3UiInterface username string iFollowThem bool sentResult bool // An upcall is when the service initiates the ID interaction. // An downcall is when the frontend initiates the ID. // Probably as directed by KBFS or the CLI. // "Tell Nojima we're about to hit him." isUpcall bool priorityMap map[string]int // map from proof key to display priority } var _ libkb.IdentifyUI = (*UIAdapter)(nil) func NewUIAdapter(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface) (*UIAdapter, error) { ret := &UIAdapter{ ui: ui, } ret.initPriorityMap(mctx) return ret, nil } func NewUIAdapterMakeSession(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface, guiid keybase1.Identify3GUIID) (ret *UIAdapter, err error) { sess := libkb.NewIdentify3SessionWithID(mctx, guiid) err = mctx.G().Identify3State.Put(sess) if err != nil { return nil, err } ret, err = NewUIAdapterWithSession(mctx, ui, sess) if err != nil { return nil, err } return ret, nil } func NewUIAdapterMakeSessionForUpcall(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface) (ret *UIAdapter, err error) { guiid, err := libkb.NewIdentify3GUIID() if err != nil { return nil, err } ret, err = NewUIAdapterMakeSession(mctx, ui, guiid) if err != nil { return nil, err } ret.isUpcall = true return ret, nil } func NewUIAdapterWithSession(mctx libkb.MetaContext, ui keybase1.Identify3UiInterface, sess *libkb.Identify3Session) (*UIAdapter, error) { ret, err := NewUIAdapter(mctx, ui) if err != nil { return nil, err } ret.session = sess return ret, nil } func (i *UIAdapter) Start(mctx libkb.MetaContext, user string, reason keybase1.IdentifyReason, force bool) error { i.Lock() i.username = user i.Unlock() if !i.isUpcall { return nil } arg := keybase1.Identify3ShowTrackerArg{ GuiID: i.session.ID(), Assertion: keybase1.Identify3Assertion(user), Reason: reason, ForceDisplay: true, } err := i.ui.Identify3ShowTracker(mctx.Ctx(), arg) if err != nil { mctx.Debug("Failed to call Identify3ShowTracker: %s", err) } return err } func (i *UIAdapter) initPriorityMap(mctx libkb.MetaContext) { i.priorityMap = make(map[string]int) var haveDisplayConfigs bool for _, displayConfig := range mctx.G().GetProofServices().ListDisplayConfigs(mctx) { haveDisplayConfigs = true i.priorityMap[displayConfig.Key] = displayConfig.Priority var altKey string switch displayConfig.Key { case "zcash.t", "zcash.z", "zcash.s": altKey = "zcash" case "bitcoin": altKey = "btc" case "http", "https", "dns": altKey = "web" } if len(altKey) > 0 { if _, ok := i.priorityMap[altKey]; !ok { i.priorityMap[altKey] = displayConfig.Priority } } } if !haveDisplayConfigs { i.priorityMap["twitter"] = 1 i.priorityMap["https"] = 100 i.priorityMap["http"] = 101 i.priorityMap["dns"] = 102 i.priorityMap["pgp"] = 103 i.priorityMap["bitcoin"] = 104 i.priorityMap["zcash.s"] = 105 i.priorityMap["zcash.z"] = 106 i.priorityMap["zcash.t"] = 107 i.priorityMap["stellar"] = 108 i.priorityMap["github"] = 2 i.priorityMap["reddit"] = 3 i.priorityMap["hackernews"] = 4 i.priorityMap["facebook"] = 5 } } func (i *UIAdapter) priority(key string) int { if i.priorityMap == nil { return 0 // should be impossible but don't crash. } p, ok := i.priorityMap[key] if !ok { // Put it at the bottom of the list. return 9999999 } return p } func (i *UIAdapter) getColorForValid(following bool) keybase1.Identify3RowColor { if following { return keybase1.Identify3RowColor_GREEN } return keybase1.Identify3RowColor_BLUE } // return true if we need an upgrade func (i *UIAdapter) setRowStatus(mctx libkb.MetaContext, arg *keybase1.Identify3Row, lcr keybase1.LinkCheckResult) bool { needUpgrade := false mctx.Debug("ID3: setRowStatus(lcr: %+v, cached: %+v, diff: %+v, remoteDiff: %+v, hint: %+v)", lcr, lcr.Cached, lcr.Diff, lcr.RemoteDiff, lcr.Hint) switch { // The proof worked, and either we tracked it as working, or we didn't track it at all. case (lcr.ProofResult.State == keybase1.ProofState_OK && (lcr.RemoteDiff == nil || lcr.RemoteDiff.Type == keybase1.TrackDiffType_NONE)): arg.Color = i.getColorForValid(lcr.RemoteDiff != nil) arg.State = keybase1.Identify3RowState_VALID // The proof worked, and it's new to us. case lcr.ProofResult.State == keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_NEW: arg.Color = keybase1.Identify3RowColor_BLUE arg.State = keybase1.Identify3RowState_VALID arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "new"}) needUpgrade = true // The proof worked, and it's upgraded. case lcr.ProofResult.State == keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_UPGRADED: arg.Color = keybase1.Identify3RowColor_BLUE arg.State = keybase1.Identify3RowState_VALID arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "upgraded"}) needUpgrade = true // The proof worked, we tracked failed, and now it's working case lcr.ProofResult.State == keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_REMOTE_WORKING: arg.Color = keybase1.Identify3RowColor_BLUE arg.State = keybase1.Identify3RowState_VALID arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "new"}) needUpgrade = true // The proof failed, but we didn't track it case lcr.ProofResult.State != keybase1.ProofState_OK && lcr.RemoteDiff == nil: arg.Color = keybase1.Identify3RowColor_ORANGE arg.State = keybase1.Identify3RowState_WARNING arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "unreachable"}) // The proof failed, but we did "ignore" it, so it's OK case lcr.ProofResult.State != keybase1.ProofState_OK && (lcr.RemoteDiff == nil || lcr.RemoteDiff.Type == keybase1.TrackDiffType_NONE): arg.Color = keybase1.Identify3RowColor_GREEN arg.State = keybase1.Identify3RowState_WARNING arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "ignored"}) // The proof failed, but we did "ignore" it via "SNOONZE", so it's OK, for now. case lcr.ProofResult.State != keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type == keybase1.TrackDiffType_NONE_VIA_TEMPORARY: arg.Color = keybase1.Identify3RowColor_YELLOW arg.State = keybase1.Identify3RowState_WARNING arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "ignored"}, keybase1.Identify3RowMeta{Color: arg.Color, Label: "temporary"}, ) // The proof failed, we did track it, and it didn't match our track case lcr.ProofResult.State != keybase1.ProofState_OK && lcr.RemoteDiff != nil && lcr.RemoteDiff.Type != keybase1.TrackDiffType_NONE: arg.Color = keybase1.Identify3RowColor_RED arg.State = keybase1.Identify3RowState_ERROR arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "unreachable"}) default: mctx.Warning("unhandled ID3 setRowStatus") } return needUpgrade } func (i *UIAdapter) rowPartial(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr *keybase1.LinkCheckResult) (row keybase1.Identify3Row) { row = keybase1.Identify3Row{ Key: proof.Key, Value: proof.Value, SigID: proof.SigID, Ctime: proof.MTime, // It's what we've got. Priority: i.priority(proof.Key), } var humanURLOrSigchainURL string if lcr != nil && lcr.Hint != nil { humanURLOrSigchainURL = lcr.Hint.HumanUrl } if len(humanURLOrSigchainURL) == 0 { humanURLOrSigchainURL = i.makeSigchainViewURL(mctx, proof.SigID) } row.ProofURL = humanURLOrSigchainURL switch proof.ProofType { case keybase1.ProofType_TWITTER: row.SiteURL = fmt.Sprintf("https://twitter.com/%v", proof.Value) case keybase1.ProofType_GITHUB: row.SiteURL = fmt.Sprintf("https://github.com/%v", proof.Value) case keybase1.ProofType_REDDIT: row.SiteURL = fmt.Sprintf("https://reddit.com/user/%v", proof.Value) case keybase1.ProofType_HACKERNEWS: // hackernews profile urls must have the username in its original casing. username := proof.Value if libkb.Cicmp(proof.Value, proof.DisplayMarkup) { username = proof.DisplayMarkup } row.SiteURL = fmt.Sprintf("https://news.ycombinator.com/user?id=%v", username) case keybase1.ProofType_FACEBOOK: row.SiteURL = fmt.Sprintf("https://facebook.com/%v", proof.Value) case keybase1.ProofType_GENERIC_SOCIAL: row.SiteURL = humanURLOrSigchainURL serviceType := mctx.G().GetProofServices().GetServiceType(mctx.Ctx(), proof.Key) if serviceType != nil { if serviceType, ok := serviceType.(*externals.GenericSocialProofServiceType); ok { profileURL, err := serviceType.ProfileURL(proof.Value) if err == nil { row.SiteURL = profileURL } } } row.ProofURL = i.makeSigchainViewURL(mctx, proof.SigID) case keybase1.ProofType_GENERIC_WEB_SITE: protocol := "https" if proof.Key != "https" { protocol = "http" } row.SiteURL = fmt.Sprintf("%v://%v", protocol, proof.Value) case keybase1.ProofType_DNS: row.SiteURL = fmt.Sprintf("http://%v", proof.Value) row.ProofURL = i.makeSigchainViewURL(mctx, proof.SigID) default: row.SiteURL = humanURLOrSigchainURL } iconKey := libkb.ProofIconKey(mctx, proof.ProofType, proof.Key) row.SiteIcon = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeSmall, 16) row.SiteIconDarkmode = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeSmallDarkmode, 16) row.SiteIconFull = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeFull, 64) row.SiteIconFullDarkmode = libkb.MakeProofIcons(mctx, iconKey, libkb.ProofIconTypeFullDarkmode, 64) switch proof.ProofType { case keybase1.ProofType_NONE, keybase1.ProofType_PGP: // These types are not eligible for web-of-trust selection. default: wotProof, err := libkb.NewWotProof(proof.ProofType, proof.Key, proof.Value) if err != nil { mctx.Debug("Error creating web-of-trust proof summary: %v", err) } else { row.WotProof = &wotProof } } return row } func (i *UIAdapter) finishRemoteCheck(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr keybase1.LinkCheckResult) error { if lcr.BreaksTracking { i.session.SetTrackBroken() } arg := i.rowPartial(mctx, proof, &lcr) needUpgrade := i.setRowStatus(mctx, &arg, lcr) if needUpgrade { i.session.SetNeedUpgrade() } i.updateRow(mctx, arg) return nil } func (i *UIAdapter) FinishWebProofCheck(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr keybase1.LinkCheckResult) error { return i.finishRemoteCheck(mctx, proof, lcr) } func (i *UIAdapter) FinishSocialProofCheck(mctx libkb.MetaContext, proof keybase1.RemoteProof, lcr keybase1.LinkCheckResult) error { return i.finishRemoteCheck(mctx, proof, lcr) } func (i *UIAdapter) Confirm(libkb.MetaContext, *keybase1.IdentifyOutcome) (keybase1.ConfirmResult, error) { return keybase1.ConfirmResult{}, nil } func (i *UIAdapter) DisplayCryptocurrency(mctx libkb.MetaContext, cc keybase1.Cryptocurrency) error { i.plumbCryptocurrency(mctx, cc) return nil } func (i *UIAdapter) DisplayStellarAccount(mctx libkb.MetaContext, s keybase1.StellarAccount) error { i.plumbStellarAccount(mctx, s) return nil } func (i *UIAdapter) DisplayKey(mctx libkb.MetaContext, key keybase1.IdentifyKey) error { if key.BreaksTracking { i.session.SetTrackBroken() } i.checkEldest(mctx, key) i.displayKey(mctx, key) return nil } func (i *UIAdapter) displayKey(mctx libkb.MetaContext, key keybase1.IdentifyKey) { if key.PGPFingerprint == nil { return } arg := keybase1.Identify3Row{ Key: "pgp", Value: hex.EncodeToString(key.PGPFingerprint), SigID: key.SigID, Ctime: 0, Priority: i.priority("pgp"), SiteURL: i.makeKeybaseProfileURL(mctx), // key.SigID is blank if the PGP key was there pre-sigchain ProofURL: i.makeSigchainViewURL(mctx, key.SigID), SiteIcon: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeSmall, 16), SiteIconDarkmode: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeSmallDarkmode, 16), SiteIconFull: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeFull, 64), SiteIconFullDarkmode: libkb.MakeProofIcons(mctx, "pgp", libkb.ProofIconTypeFullDarkmode, 64), Kid: &key.KID, // PICNIC-1092 consider adding `WotProof` to support pgp in web-of-trust. } switch { case key.TrackDiff == nil || key.TrackDiff.Type == keybase1.TrackDiffType_NONE: arg.State = keybase1.Identify3RowState_VALID arg.Color = i.getColorForValid(key.TrackDiff != nil) case key.TrackDiff != nil && (key.TrackDiff.Type == keybase1.TrackDiffType_REVOKED || key.TrackDiff.Type == keybase1.TrackDiffType_NEW_ELDEST): arg.State = keybase1.Identify3RowState_REVOKED arg.Color = keybase1.Identify3RowColor_RED case key.TrackDiff != nil && key.TrackDiff.Type == keybase1.TrackDiffType_NEW: arg.State = keybase1.Identify3RowState_VALID arg.Color = keybase1.Identify3RowColor_BLUE arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "new"}) default: mctx.Warning("unhandled ID3 setRowStatus in displayKey: %+v", key) } i.updateRow(mctx, arg) } func (i *UIAdapter) checkEldest(mctx libkb.MetaContext, key keybase1.IdentifyKey) { if key.TrackDiff == nil || key.TrackDiff.Type != keybase1.TrackDiffType_NEW_ELDEST { return } err := i.ui.Identify3UserReset(mctx.Ctx(), i.session.ID()) if err != nil { mctx.Debug("Error sending user reset message: %s", err) } } func (i *UIAdapter) ReportLastTrack(mctx libkb.MetaContext, track *keybase1.TrackSummary) error { if track != nil { i.Lock() i.iFollowThem = true i.Unlock() } return nil } func (i *UIAdapter) plumbUncheckedProofs(mctx libkb.MetaContext, proofs []keybase1.IdentifyRow) { err := i.ui.Identify3Summary(mctx.Ctx(), keybase1.Identify3Summary{ GuiID: i.session.ID(), NumProofsToCheck: len(proofs), }) if err != nil { mctx.Debug("Identify3Summary call failed: %s", err.Error()) } for _, proof := range proofs { i.plumbUncheckedProof(mctx, proof) } } func (i *UIAdapter) plumbUncheckedProof(mctx libkb.MetaContext, row keybase1.IdentifyRow) { arg := i.rowPartial(mctx, row.Proof, nil) arg.State = keybase1.Identify3RowState_CHECKING arg.Color = keybase1.Identify3RowColor_GRAY i.updateRow(mctx, arg) } func (i *UIAdapter) updateRow(mctx libkb.MetaContext, arg keybase1.Identify3Row) { arg.GuiID = i.session.ID() err := i.ui.Identify3UpdateRow(mctx.Ctx(), arg) mctx.Debug("update row %+v", arg) if err != nil { mctx.Debug("Failed to send update row (%+v): %s", arg, err) } } func (i *UIAdapter) shouldSkipSendResult() bool { i.Lock() defer i.Unlock() if i.sentResult { return true } i.sentResult = true return false } func (i *UIAdapter) sendResult(mctx libkb.MetaContext, typ keybase1.Identify3ResultType) error { if i.shouldSkipSendResult() { mctx.Debug("Skipping send result, already done") return nil } arg := keybase1.Identify3ResultArg{ GuiID: i.session.ID(), Result: typ, } err := i.ui.Identify3Result(mctx.Ctx(), arg) if err != nil { mctx.Debug("Failed to send result (%+v): %s", arg, err) } return err } func (i *UIAdapter) makeKeybaseProfileURL(mctx libkb.MetaContext) string { url := libkb.SiteURILookup[mctx.G().Env.GetRunMode()] var parts []string if url == "" { return url } parts = append(parts, url, i.username) return strings.Join(parts, "/") } func (i *UIAdapter) makeSigchainViewURL(mctx libkb.MetaContext, s keybase1.SigID) string { url := libkb.SiteURILookup[mctx.G().Env.GetRunMode()] var parts []string if url == "" { return url } parts = append(parts, url, i.username) page := "sigchain" if !s.IsNil() { page = page + "#" + s.String() } parts = append(parts, page) return strings.Join(parts, "/") } func (i *UIAdapter) plumbCryptocurrency(mctx libkb.MetaContext, crypto keybase1.Cryptocurrency) { key := crypto.Type switch crypto.Family { case string(libkb.CryptocurrencyFamilyBitcoin): key = "btc" case string(libkb.CryptocurrencyFamilyZCash): key = "zcash" default: mctx.Debug("unrecgonized crypto family: %v, %v", crypto.Type, crypto.Family) } i.updateRow(mctx, keybase1.Identify3Row{ Key: key, Value: crypto.Address, Priority: i.priority(key), State: keybase1.Identify3RowState_VALID, Color: i.getColorForValid(i.iFollowThem), SigID: crypto.SigID, Ctime: 0, SiteURL: i.makeSigchainViewURL(mctx, crypto.SigID), SiteIcon: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeSmall, 16), SiteIconDarkmode: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeSmallDarkmode, 16), SiteIconFull: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeFull, 64), SiteIconFullDarkmode: libkb.MakeProofIcons(mctx, key, libkb.ProofIconTypeFullDarkmode, 64), ProofURL: i.makeSigchainViewURL(mctx, crypto.SigID), }) } func (i *UIAdapter) plumbStellarAccount(mctx libkb.MetaContext, str keybase1.StellarAccount) { color := i.getColorForValid(i.iFollowThem) if str.Hidden { color = keybase1.Identify3RowColor_GRAY } i.updateRow(mctx, keybase1.Identify3Row{ Key: "stellar", Value: str.FederationAddress, Priority: i.priority("stellar"), State: keybase1.Identify3RowState_VALID, Color: color, SigID: str.SigID, Ctime: 0, SiteURL: i.makeSigchainViewURL(mctx, str.SigID), SiteIcon: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeSmall, 16), SiteIconDarkmode: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeSmallDarkmode, 16), SiteIconFull: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeFull, 64), SiteIconFullDarkmode: libkb.MakeProofIcons(mctx, "stellar", libkb.ProofIconTypeFullDarkmode, 64), ProofURL: i.makeSigchainViewURL(mctx, str.SigID), }) } func (i *UIAdapter) plumbRevoked(mctx libkb.MetaContext, row keybase1.RevokedProof) { arg := i.rowPartial(mctx, row.Proof, nil) arg.State = keybase1.Identify3RowState_REVOKED arg.Color = keybase1.Identify3RowColor_RED arg.Metas = append(arg.Metas, keybase1.Identify3RowMeta{Color: arg.Color, Label: "revoked"}, ) i.updateRow(mctx, arg) } func (i *UIAdapter) plumbRevokeds(mctx libkb.MetaContext, rows []keybase1.RevokedProof) { for _, row := range rows { i.plumbRevoked(mctx, row) } } func (i *UIAdapter) LaunchNetworkChecks(mctx libkb.MetaContext, id *keybase1.Identity, user *keybase1.User) error { if id.BreaksTracking { i.session.SetTrackBroken() } i.plumbUncheckedProofs(mctx, id.Proofs) i.plumbRevokeds(mctx, id.RevokedDetails) return nil } func (i *UIAdapter) DisplayTrackStatement(libkb.MetaContext, string) error { return nil } func (i *UIAdapter) DisplayUserCard(mctx libkb.MetaContext, card keybase1.UserCard) error { arg := keybase1.Identify3UpdateUserCardArg{ GuiID: i.session.ID(), Card: card, } err := i.ui.Identify3UpdateUserCard(mctx.Ctx(), arg) if err != nil { mctx.Debug("Failed to send update card: %s", err) } return nil } func (i *UIAdapter) ReportTrackToken(mctx libkb.MetaContext, token keybase1.TrackToken) error { outcome, err := mctx.G().TrackCache().Get(token) if err != nil { return err } i.session.SetOutcome(outcome) return nil } func (i *UIAdapter) Cancel(mctx libkb.MetaContext) error { _ = i.sendResult(mctx, keybase1.Identify3ResultType_CANCELED) return nil } func (i *UIAdapter) Finish(mctx libkb.MetaContext) error { _ = i.sendResult(mctx, i.session.ResultType()) return nil } func (i *UIAdapter) DisplayTLFCreateWithInvite(libkb.MetaContext, keybase1.DisplayTLFCreateWithInviteArg) error { return nil } func (i *UIAdapter) Dismiss(libkb.MetaContext, string, keybase1.DismissReason) error { return nil }