github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/service/user_handler.go (about) 1 // Copyright 2016 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 "fmt" 9 "strings" 10 11 "golang.org/x/net/context" 12 13 "github.com/keybase/client/go/gregor" 14 "github.com/keybase/client/go/libkb" 15 gregor1 "github.com/keybase/client/go/protocol/gregor1" 16 keybase1 "github.com/keybase/client/go/protocol/keybase1" 17 ) 18 19 const userHandlerName = "userHandler" 20 21 type userHandler struct { 22 libkb.Contextified 23 userBlockedHandlers []UserBlockedHandler 24 } 25 26 type UserBlockedHandler interface { 27 UserBlocked(m libkb.MetaContext, badUIDs map[keybase1.UID]bool) error 28 } 29 30 func newUserHandler(g *libkb.GlobalContext) *userHandler { 31 return &userHandler{ 32 Contextified: libkb.NewContextified(g), 33 } 34 } 35 36 func (r *userHandler) PushUserBlockedHandler(h UserBlockedHandler) { 37 r.userBlockedHandlers = append(r.userBlockedHandlers, h) 38 } 39 40 func (r *userHandler) Create(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) { 41 m := libkb.NewMetaContext(ctx, r.G()) 42 switch category { 43 case "user.key_change": 44 return true, r.keyChange(m) 45 case "user.identity_change": 46 return true, r.identityChange(m) 47 case "user.password_change": 48 return true, r.passwordChange(m, cli, category, item) 49 case "user.passphrase_state": 50 return true, r.passphraseStateUpdate(m, cli, category, item) 51 case "user.blocked": 52 return true, r.userBlocked(m, cli, category, item) 53 default: 54 if strings.HasPrefix(category, "user.") { 55 return false, fmt.Errorf("unknown userHandler category: %q", category) 56 } 57 return false, nil 58 } 59 } 60 61 func (r *userHandler) keyChange(m libkb.MetaContext) error { 62 m.G().KeyfamilyChanged(m.Ctx(), m.G().Env.GetUID()) 63 64 // check if this device was just revoked and if so, log out 65 return m.LogoutAndDeprovisionIfRevoked() 66 } 67 68 func (r *userHandler) identityChange(m libkb.MetaContext) error { 69 m.G().UserChanged(m.Ctx(), m.G().Env.GetUID()) 70 return nil 71 } 72 73 func (r *userHandler) passwordChange(m libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) error { 74 m.Debug("userHandler: %s received", category) 75 return r.G().GregorState.DismissItem(m.Ctx(), cli, item.Metadata().MsgID()) 76 } 77 78 func (r *userHandler) passphraseStateUpdate(m libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) error { 79 m.Debug("userHandler: %s received", category) 80 var msg keybase1.UserPassphraseStateMsg 81 if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { 82 m.Warning("error unmarshaling user.passphrase_update item: %s", err) 83 return err 84 } 85 libkb.MaybeSavePassphraseState(m, msg.PassphraseState) 86 r.G().NotifyRouter.HandlePasswordChanged(m.Ctx(), msg.PassphraseState) 87 // Don't dismiss the item, so other devices know about it 88 return nil 89 } 90 91 func (r *userHandler) userBlocked(m libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) error { 92 m.Debug("userHandler: %s received", category) 93 var msg keybase1.UserBlockedBody 94 if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { 95 m.Warning("error unmarshaling user.blocked item: %s", err) 96 return err 97 } 98 m.Debug("Got user.blocked item: %+v", msg) 99 badUIDs := make(map[keybase1.UID]bool) 100 101 for _, r := range msg.Blocks { 102 if (r.Chat != nil && *r.Chat) || (r.Follow != nil && *r.Follow) { 103 badUIDs[r.Uid] = true 104 } 105 106 // regardless of status, clear user card cache for any uid 107 // that changed 108 if err := m.G().CardCache().Delete(r.Uid); err != nil { 109 m.Debug("CardCache.Delete(%s) error: %s", r.Uid, err) 110 } 111 } 112 113 // Ignore the error if we fail to block properly 114 _ = libkb.NewServertrustTrackerSyncer(m.G(), msg.Uid, libkb.FollowDirectionFollowing).Block(m, badUIDs) 115 116 m.Debug("Got user.blocked blocked UIDs %+v", badUIDs) 117 for _, h := range r.userBlockedHandlers { 118 tmp := h.UserBlocked(m, badUIDs) 119 if tmp != nil { 120 m.Warning("Error handling UserBlocked message: %s", tmp) 121 } 122 } 123 124 r.G().NotifyRouter.HandleUserBlocked(m.Ctx(), msg) 125 126 r.G().GetStellar().Refresh(m, "user.blocked message") 127 128 // dismiss this locally so it is only processed once per device 129 if err := r.G().GregorState.LocalDismissItem(m.Ctx(), item.Metadata().MsgID()); err != nil { 130 m.Warning("error in LocalDismissItem: %s", err) 131 } 132 133 return nil 134 } 135 136 func (r *userHandler) Dismiss(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) { 137 return false, nil 138 } 139 140 func (r *userHandler) IsAlive() bool { 141 return true 142 } 143 144 func (r *userHandler) Name() string { 145 return userHandlerName 146 }