github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/service/device.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package service 5 6 import ( 7 "encoding/json" 8 "errors" 9 10 "github.com/keybase/client/go/engine" 11 "github.com/keybase/client/go/gregor" 12 "github.com/keybase/client/go/libkb" 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 "github.com/keybase/go-framed-msgpack-rpc/rpc" 15 "golang.org/x/net/context" 16 ) 17 18 // DeviceHandler is the RPC handler for the device interface. 19 type DeviceHandler struct { 20 *BaseHandler 21 libkb.Contextified 22 gregor *gregorHandler 23 } 24 25 // NewDeviceHandler creates a DeviceHandler for the xp transport. 26 func NewDeviceHandler(xp rpc.Transporter, g *libkb.GlobalContext, gregor *gregorHandler) *DeviceHandler { 27 return &DeviceHandler{ 28 BaseHandler: NewBaseHandler(g, xp), 29 Contextified: libkb.NewContextified(g), 30 gregor: gregor, 31 } 32 } 33 34 // DeviceList returns a list of all the devices for a user. 35 func (h *DeviceHandler) DeviceList(ctx context.Context, sessionID int) ([]keybase1.Device, error) { 36 uis := libkb.UIs{ 37 LogUI: h.getLogUI(sessionID), 38 SessionID: sessionID, 39 } 40 eng := engine.NewDevList(h.G()) 41 m := libkb.NewMetaContext(ctx, h.G()).WithUIs(uis) 42 if err := engine.RunEngine2(m, eng); err != nil { 43 return nil, err 44 } 45 return eng.List(), nil 46 } 47 48 // DeviceHistoryList returns a list of all the devices for a user, 49 // with detailed history and provisioner, revoker information. 50 func (h *DeviceHandler) DeviceHistoryList(nctx context.Context, sessionID int) ([]keybase1.DeviceDetail, error) { 51 uis := libkb.UIs{ 52 LogUI: h.getLogUI(sessionID), 53 SessionID: sessionID, 54 } 55 eng := engine.NewDeviceHistorySelf(h.G()) 56 m := libkb.NewMetaContext(nctx, h.G()).WithUIs(uis) 57 if err := engine.RunEngine2(m, eng); err != nil { 58 return nil, err 59 } 60 return eng.Devices(), nil 61 } 62 63 // DeviceAdd starts the kex2 device provisioning on the 64 // provisioner (device X/C1) 65 func (h *DeviceHandler) DeviceAdd(c context.Context, sessionID int) error { 66 uis := libkb.UIs{ 67 ProvisionUI: h.getProvisionUI(sessionID), 68 SecretUI: h.getSecretUI(sessionID, h.G()), 69 SessionID: sessionID, 70 } 71 m := libkb.NewMetaContext(c, h.G()).WithUIs(uis) 72 eng := engine.NewDeviceAdd(h.G()) 73 return engine.RunEngine2(m, eng) 74 } 75 76 // CheckDeviceNameFormat verifies that the device name has a valid 77 // format. 78 func (h *DeviceHandler) CheckDeviceNameFormat(_ context.Context, arg keybase1.CheckDeviceNameFormatArg) (bool, error) { 79 ok := libkb.CheckDeviceName.F(arg.Name) 80 if ok { 81 return ok, nil 82 } 83 return false, errors.New(libkb.CheckDeviceName.Hint) 84 } 85 86 type _deviceChange struct { 87 DeviceID string `json:"device_id"` 88 } 89 90 func LoopAndDismissForDeviceChangeNotifications(mctx libkb.MetaContext, dismisser libkb.GregorState, 91 gregorState gregor.State, exceptedDeviceID string) (err error) { 92 93 items, err := gregorState.Items() 94 if err != nil { 95 return err 96 } 97 var body _deviceChange 98 for _, item := range items { 99 category := item.Category().String() 100 if !(category == "device.revoked" || category == "device.new") { 101 continue 102 } 103 err := json.Unmarshal(item.Body().Bytes(), &body) 104 if err != nil { 105 return err 106 } 107 itemID := item.Metadata().MsgID() 108 if body.DeviceID != exceptedDeviceID { 109 mctx.Debug("dismissing device notification %s for %s", category, body.DeviceID) 110 err := dismisser.DismissItem(mctx.Ctx(), nil, itemID) 111 if err != nil { 112 return err 113 } 114 } 115 } 116 return nil 117 } 118 119 func (h *DeviceHandler) DismissDeviceChangeNotifications(c context.Context) (err error) { 120 mctx := libkb.NewMetaContext(c, h.G()) 121 defer mctx.Trace("DismissDeviceChangeNotifications", &err)() 122 123 gcli, err := h.gregor.getGregorCli() 124 if err != nil { 125 return err 126 } 127 state, err := gcli.StateMachineState(c, nil, true) 128 if err != nil { 129 return err 130 } 131 activeDeviceID := h.G().ActiveDevice.DeviceID().String() 132 dismisser := h.G().GregorState 133 err = LoopAndDismissForDeviceChangeNotifications(mctx, dismisser, state, activeDeviceID) 134 return err 135 } 136 137 func (h *DeviceHandler) CheckDeviceNameForUser(ctx context.Context, arg keybase1.CheckDeviceNameForUserArg) error { 138 mctx := libkb.NewMetaContext(ctx, h.G()) 139 _, err := mctx.G().API.Get(mctx, libkb.APIArg{ 140 Endpoint: "device/check_name", 141 SessionType: libkb.APISessionTypeNONE, 142 Args: libkb.HTTPArgs{ 143 "username": libkb.S{Val: arg.Username}, 144 "devicename": libkb.S{Val: arg.Devicename}, 145 }, 146 }) 147 148 if err == nil { 149 return err 150 } 151 152 if apiErr, ok := err.(*libkb.APIError); ok { 153 switch apiErr.Code { 154 case libkb.SCDeviceNameInUse: 155 return libkb.DeviceNameInUseError{} 156 case libkb.SCInputError: 157 return libkb.DeviceBadNameError{} 158 } 159 } 160 161 return err 162 }