/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/service/team_handler.go
347 строк
12 KB
zoom-ua
remove golang.org/x/net/context in favor of context (#28708)
17 дек 2025, 18:24
Не верифицирован
17 дек 2025, 18:24
67b0ffe
Код
Авторство
О чём код?
// Copyright 2017 Keybase, Inc. All rights reserved. Use of // this source code is governed by the included BSD license. // Handlers for team-related gregor messages package service import ( "context" "encoding/json" "fmt" "strings" "sync" "github.com/keybase/client/go/badges" "github.com/keybase/client/go/gregor" "github.com/keybase/client/go/libkb" "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/client/go/teams" ) const teamHandlerName = "teamHandler" type teamHandler struct { libkb.Contextified badger *badges.Badger // Some work that comes from team gregor messages is done in // background goroutine: rotateTeam and reset user badge // dismissing, for now. Use a mutex to limit this to only one // job at time. teamHandlerBackgroundJob sync.Mutex } var _ libkb.GregorInBandMessageHandler = (*teamHandler)(nil) func newTeamHandler(g *libkb.GlobalContext, badger *badges.Badger) *teamHandler { return &teamHandler{ Contextified: libkb.NewContextified(g), badger: badger, } } func (r *teamHandler) Create(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) { switch category { case "team.clkr": return true, r.rotateTeam(ctx, cli, item) case "team.sbs": return true, r.sharingBeforeSignup(ctx, cli, item) case "team.openreq": return true, r.openTeamAccessRequest(ctx, cli, item) case "team.opensweep": return true, r.openTeamSweepResetUsersRequest(ctx, cli, item) case "team.change": return true, r.changeTeam(ctx, cli, category, item, keybase1.TeamChangeSet{}) case "team.force_repoll": return true, r.gotForceRepoll(ctx, cli, item) case "team.rename": return true, r.changeTeam(ctx, cli, category, item, keybase1.TeamChangeSet{Renamed: true}) case "team.delete": return true, r.deleteTeam(ctx, cli, item) case "team.exit": return true, r.exitTeam(ctx, cli, item) case "team.seitan": return true, r.seitanCompletion(ctx, cli, item) case "team.member_out_from_reset": return true, r.memberOutFromReset(ctx, cli, item) case "team.abandoned": return true, r.abandonTeam(ctx, cli, item) case "team.newly_added_to_team": return true, r.newlyAddedToTeam(ctx, cli, item) case "team.user_team_version": return true, r.userTeamVersion(ctx, cli, item) case "team.member_showcase_change": return true, r.memberShowcaseChange(ctx, cli, item) default: if strings.HasPrefix(category, "team.") { return false, fmt.Errorf("unknown teamHandler category: %q", category) } return false, nil } } func (r *teamHandler) rotateTeam(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: team.clkr received") var msg keybase1.TeamCLKRMsg if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.clkr item: %s", err) return err } r.G().Log.CDebugf(ctx, "team.clkr unmarshaled: %+v", msg) for _, uv := range msg.ResetUsersUntrusted { // We don't use UIDMapper in HandleRotateRequest, but since // server just told us that these users have reset, we might // as well use that knowledge to refresh cache. // Use ClearUIDAtEldestSeqno instead of InformOfEldestSeqno // because usually uv.UserEldestSeqno (the "new EldestSeqno") // will be 0, because user has just reset and hasn't // reprovisioned yet err := r.G().UIDMapper.ClearUIDAtEldestSeqno(ctx, r.G(), uv.Uid, uv.MemberEldestSeqno) if err != nil { return err } } go func() { r.teamHandlerBackgroundJob.Lock() defer r.teamHandlerBackgroundJob.Unlock() if err := teams.HandleRotateRequest(ctx, r.G(), msg); err != nil { r.G().Log.CDebugf(ctx, "HandleRotateRequest failed with error: %s", err) return } r.G().Log.CDebugf(ctx, "dismissing team.clkr item since rotate succeeded") err := r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) if err != nil { r.G().Log.CDebugf(ctx, "error dismissing team.clkr item: %+v", err) } }() return nil } func (r *teamHandler) memberOutFromReset(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { nm := "team.member_out_from_reset" r.G().Log.CDebugf(ctx, "teamHandler: %s received", nm) var msg keybase1.TeamMemberOutFromReset if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling %s item: %s", nm, err) return err } r.G().Log.CDebugf(ctx, "%s unmarshaled: %+v", nm, msg) if err := r.G().UIDMapper.ClearUIDAtEldestSeqno(ctx, r.G(), msg.ResetUser.Uid, msg.ResetUser.EldestSeqno); err != nil { return err } // Favorites is misused to let people know when there are reset team // members. This busts the relevant cache. r.G().NotifyRouter.HandleFavoritesChanged(r.G().GetMyUID()) r.G().Log.CDebugf(ctx, "%s: cleared UIDMap cache for %s%%%d", nm, msg.ResetUser.Uid, msg.ResetUser.EldestSeqno) return nil } type abandonMsg struct { TeamID keybase1.TeamID `json:"team_id"` } func (r *teamHandler) abandonTeam(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { nm := "team.abandoned" r.G().Log.CDebugf(ctx, "teamHandler.abandonTeam: %s received", nm) var msg abandonMsg if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling %s item: %s", nm, err) return err } r.G().Log.CDebugf(ctx, "teamHandler.abandonTeam: %s unmarshaled: %+v", nm, msg) r.G().NotifyRouter.HandleTeamAbandoned(ctx, msg.TeamID) r.G().Log.CDebugf(ctx, "teamHandler.abandonTeam: locally dismissing %s", nm) if err := r.G().GregorState.LocalDismissItem(ctx, item.Metadata().MsgID()); err != nil { r.G().Log.CDebugf(ctx, "teamHandler.abandonTeam: failed to locally dismiss msg %v", item.Metadata().MsgID()) } return nil } func (r *teamHandler) gotForceRepoll(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: gotForceRepoll received") return teams.HandleForceRepollNotification(ctx, r.G(), item.DTime()) } func (r *teamHandler) changeTeam(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item, changes keybase1.TeamChangeSet, ) error { var rows []keybase1.TeamChangeRow r.G().Log.CDebugf(ctx, "teamHandler: changeTeam received") if err := json.Unmarshal(item.Body().Bytes(), &rows); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling %s item: %s", category, err) return err } r.G().Log.CDebugf(ctx, "%s unmarshaled: %+v", category, rows) if err := teams.HandleChangeNotification(ctx, r.G(), rows, changes); err != nil { return err } // Locally dismiss this now that we have processed it so we can // avoid replaying it over and over. if err := r.G().GregorState.LocalDismissItem(ctx, item.Metadata().MsgID()); err != nil { r.G().Log.CDebugf(ctx, "failed to local dismiss team change: %s", err) } return nil } func (r *teamHandler) deleteTeam(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { var rows []keybase1.TeamChangeRow if err := json.Unmarshal(item.Body().Bytes(), &rows); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.(change|rename) item: %s", err) return err } r.G().Log.CDebugf(ctx, "teamHandler: team.delete unmarshaled: %+v", rows) return teams.HandleDeleteNotification(ctx, r.G(), rows) } func (r *teamHandler) exitTeam(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { var rows []keybase1.TeamExitRow if err := json.Unmarshal(item.Body().Bytes(), &rows); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.exit item: %s", err) return err } r.G().Log.CDebugf(ctx, "teamHandler: team.exit unmarshaled: %+v", rows) if err := teams.HandleExitNotification(ctx, r.G(), rows); err != nil { return err } r.G().Log.Debug("dismissing team.exit: %v", item.Metadata().MsgID().String()) return r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) } func (r *teamHandler) userTeamVersion(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) (err error) { mctx := libkb.NewMetaContext(ctx, r.G()) nm := "team.user_team_version" defer mctx.Trace("teamHandler#userTeamVersion", &err)() var obj keybase1.UserTeamVersionUpdate err = json.Unmarshal(item.Body().Bytes(), &obj) if err != nil { mctx.Debug("Error unmarshaling %s item: %s", nm, err) return err } return r.G().GetTeamRoleMapManager().Update(mctx, obj.Version) } func (r *teamHandler) newlyAddedToTeam(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { nm := "team.newly_added_to_team" r.G().Log.CDebugf(ctx, "teamHandler.newlyAddedToTeam: %s received", nm) var rows []keybase1.TeamNewlyAddedRow if err := json.Unmarshal(item.Body().Bytes(), &rows); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling %s item: %s", nm, err) return err } r.G().Log.CDebugf(ctx, "teamHandler.newlyAddedToTeam: %s unmarshaled: %+v", nm, rows) if err := teams.HandleNewlyAddedToTeamNotification(ctx, r.G(), rows); err != nil { return err } // Note there used to be a local dismissal here, but the newly_added_to_team needs // to stay in the gregor state for badging to work. return nil } func (r *teamHandler) sharingBeforeSignup(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: team.sbs received") var msg keybase1.TeamSBSMsg if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.sbs item: %s", err) return err } r.G().Log.CDebugf(ctx, "team.sbs unmarshaled: %+v", msg) if err := teams.HandleSBSRequest(ctx, r.G(), msg); err != nil { return err } r.G().Log.Debug("dismissing team.sbs item since it succeeded") return r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) } func (r *teamHandler) openTeamAccessRequest(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: team.openreq received") var msg keybase1.TeamOpenReqMsg if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.openreq item: %s", err) return err } r.G().Log.CDebugf(ctx, "team.openreq unmarshaled: %+v", msg) if err := teams.HandleOpenTeamAccessRequest(ctx, r.G(), msg); err != nil { return err } r.G().Log.CDebugf(ctx, "dismissing team.openreq item since it succeeded") return r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) } func (r *teamHandler) openTeamSweepResetUsersRequest(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: team.opensweep received") var msg keybase1.TeamOpenSweepMsg if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.opensweep item: %s", err) return err } r.G().Log.CDebugf(ctx, "team.opensweep unmarshaled: %+v", msg) if err := teams.HandleOpenTeamSweepRequest(ctx, r.G(), msg); err != nil { return err } r.G().Log.CDebugf(ctx, "dismissing team.opensweep item since it succeeded") return r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) } func (r *teamHandler) memberShowcaseChange(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: team.member_showchase_change received") if err := teams.HandleTeamMemberShowcaseChange(ctx, r.G()); err != nil { return err } r.G().Log.CDebugf(ctx, "dismissing team.member_showcase_change item since it succeeded") return r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) } func (r *teamHandler) seitanCompletion(ctx context.Context, cli gregor1.IncomingInterface, item gregor.Item) error { r.G().Log.CDebugf(ctx, "teamHandler: team.seitan received") var msg keybase1.TeamSeitanMsg if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { r.G().Log.CDebugf(ctx, "error unmarshaling team.seitan item: %s", err) return err } r.G().Log.CDebugf(ctx, "team.seitan unmarshaled: %+v", msg) if err := teams.HandleTeamSeitan(ctx, r.G(), msg); err != nil { return err } r.G().Log.CDebugf(ctx, "dismissing team.seitan item since it succeeded") return r.G().GregorState.DismissItem(ctx, cli, item.Metadata().MsgID()) } func (r *teamHandler) Dismiss(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) { return false, nil } func (r *teamHandler) IsAlive() bool { return true } func (r *teamHandler) Name() string { return teamHandlerName }