1// Copyright 2017 Keybase, Inc. All rights reserved. Use of 2// this source code is governed by the included BSD license. 3 4package engine 5 6import ( 7 "time" 8 9 "github.com/keybase/client/go/libkb" 10 "github.com/keybase/client/go/protocol/keybase1" 11) 12 13// Bootstrap is an engine. 14type Bootstrap struct { 15 libkb.Contextified 16 status keybase1.BootstrapStatus 17} 18 19// NewBootstrap creates a Bootstrap engine. 20func NewBootstrap(g *libkb.GlobalContext) *Bootstrap { 21 return &Bootstrap{ 22 Contextified: libkb.NewContextified(g), 23 } 24} 25 26// Name is the unique engine name. 27func (e *Bootstrap) Name() string { 28 return "Bootstrap" 29} 30 31// GetPrereqs returns the engine prereqs. 32func (e *Bootstrap) Prereqs() Prereqs { 33 return Prereqs{} 34} 35 36// RequiredUIs returns the required UIs. 37func (e *Bootstrap) RequiredUIs() []libkb.UIKind { 38 return []libkb.UIKind{} 39} 40 41// SubConsumers returns the other UI consumers for this engine. 42func (e *Bootstrap) SubConsumers() []libkb.UIConsumer { 43 return nil 44} 45 46func (e *Bootstrap) lookupFullname(m libkb.MetaContext, uv keybase1.UserVersion) { 47 pkgs, err := m.G().UIDMapper.MapUIDsToUsernamePackagesOffline(m.Ctx(), m.G(), []keybase1.UID{uv.Uid}, time.Duration(0)) 48 if err != nil { 49 m.Warning("UID -> Username failed lookup: %s", err) 50 return 51 } 52 pkg := pkgs[0] 53 if pkg.NormalizedUsername.IsNil() || pkg.FullName == nil { 54 m.Debug("Empty username for UID=%s", uv.Uid) 55 return 56 } 57 if !uv.EldestSeqno.Eq(pkg.FullName.EldestSeqno) { 58 m.Debug("Wrong eldest for username package; got %d but wanted %d", pkg.FullName.EldestSeqno, uv.EldestSeqno) 59 return 60 } 61 e.status.Fullname = pkg.FullName.FullName 62} 63 64// Run starts the engine. 65func (e *Bootstrap) Run(m libkb.MetaContext) error { 66 e.status.Registered = e.signedUp(m) 67 68 // if any Login engine worked previously, then ActiveDevice will 69 // be valid: 70 validActiveDevice := m.G().ActiveDevice.Valid() 71 72 // the only way for ActiveDevice to be valid is to be logged in 73 // (and provisioned) 74 e.status.LoggedIn = validActiveDevice 75 if !e.status.LoggedIn { 76 m.Debug("Bootstrap: not logged in") 77 return nil 78 } 79 m.Debug("Bootstrap: logged in (valid active device)") 80 81 var uv keybase1.UserVersion 82 uv, e.status.DeviceID, e.status.DeviceName, _, _ = e.G().ActiveDevice.AllFields() 83 e.status.Uid = uv.Uid 84 e.status.Username = e.G().ActiveDevice.Username(m).String() 85 m.Debug("Bootstrap status: uid=%s, username=%s, deviceID=%s, deviceName=%s", e.status.Uid, e.status.Username, e.status.DeviceID, e.status.DeviceName) 86 87 if chatHelper := e.G().ChatHelper; chatHelper != nil { 88 e.status.UserReacjis = chatHelper.UserReacjis(m.Ctx(), e.status.Uid.ToBytes()) 89 } 90 91 e.lookupFullname(m, uv) 92 93 return nil 94} 95 96// signedUp is true if there's a uid in config.json. 97func (e *Bootstrap) signedUp(m libkb.MetaContext) bool { 98 cr := m.G().Env.GetConfig() 99 if cr == nil { 100 return false 101 } 102 if uid := cr.GetUID(); uid.Exists() { 103 return true 104 } 105 return false 106} 107 108func (e *Bootstrap) Status() keybase1.BootstrapStatus { 109 return e.status 110} 111