/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/teams/errors.go
649 строк
17 KB
zoom-ua
modernize error handling with errors.As/Is (#29350)
25 июн 2026, 17:41
Не верифицирован
25 июн 2026, 17:41
e09e254
Код
Авторство
О чём код?
package teams import ( "context" "errors" "fmt" "github.com/keybase/client/go/libkb" "github.com/keybase/client/go/protocol/keybase1" ) func NewStubbedError(l *ChainLinkUnpacked) StubbedError { return StubbedError{l: l, note: nil} } func NewStubbedErrorWithNote(l *ChainLinkUnpacked, note string) StubbedError { return StubbedError{l: l, note: ¬e} } type StubbedError struct { l *ChainLinkUnpacked note *string } func (e StubbedError) Error() string { if e.note == nil { return fmt.Sprintf("stubbed link when not expected (seqno %d)", int(e.l.outerLink.Seqno)) } return fmt.Sprintf("%s (stubbed link when not expected; at seqno %d)", *e.note, int(e.l.outerLink.Seqno)) } type InvalidLink struct { l *ChainLinkUnpacked note string } func (e InvalidLink) Error() string { return fmt.Sprintf("invalid link (seqno %d): %s", e.l.Seqno(), e.note) } func NewInvalidLink(l *ChainLinkUnpacked, format string, args ...any) InvalidLink { return InvalidLink{l, fmt.Sprintf(format, args...)} } type AppendLinkError struct { prevSeqno keybase1.Seqno l *ChainLinkUnpacked inner error } func (e AppendLinkError) Error() string { return fmt.Sprintf("appending %v->%v: %v", e.prevSeqno, e.l.Seqno(), e.inner) } func (e AppendLinkError) Unwrap() error { return e.inner } func NewAppendLinkError(l *ChainLinkUnpacked, prevSeqno keybase1.Seqno, inner error) AppendLinkError { return AppendLinkError{prevSeqno, l, inner} } type InflateError struct { l *ChainLinkUnpacked note *string } func (e InflateError) Error() string { if e.note == nil { return fmt.Sprintf("error inflating previously-stubbed link (seqno %d)", int(e.l.outerLink.Seqno)) } return fmt.Sprintf("error inflating previously-stubbed link (seqno %d) (%s)", int(e.l.outerLink.Seqno), *e.note) } func NewInflateError(l *ChainLinkUnpacked) InflateError { return InflateError{l: l, note: nil} } func NewInflateErrorWithNote(l *ChainLinkUnpacked, note string) InflateError { return InflateError{l: l, note: ¬e} } type UnexpectedSeqnoError struct { expected keybase1.Seqno actual keybase1.Seqno } func (e UnexpectedSeqnoError) Error() string { return fmt.Sprintf("expected seqno:%v but got %v", e.expected, e.actual) } func NewUnexpectedSeqnoError(expected, actual keybase1.Seqno) UnexpectedSeqnoError { return UnexpectedSeqnoError{expected, actual} } type AdminPermissionError struct { TeamID keybase1.TeamID UserVersion keybase1.UserVersion Desc string } func (e AdminPermissionError) Error() string { return fmt.Sprintf("For team %s, user %s: %s", e.TeamID, e.UserVersion.PercentForm(), e.Desc) } func NewAdminPermissionError(t keybase1.TeamID, uv keybase1.UserVersion, d string) AdminPermissionError { return AdminPermissionError{t, uv, d} } type AdminNotFoundError struct { Admin SCTeamAdmin } func (e AdminNotFoundError) Error() string { return fmt.Sprintf("Admin permission specified in %+v wasn't found", e.Admin) } func NewAdminNotFoundError(a SCTeamAdmin) AdminNotFoundError { return AdminNotFoundError{a} } type ProofError struct { p proof msg string } func NewProofError(p proof, s string) ProofError { return ProofError{p, s} } func (p ProofError) Error() string { return fmt.Sprintf("proof error for proof '%s': %s", p.p.reason, p.msg) } type PermissionError struct { TeamID keybase1.TeamID UserVersion keybase1.UserVersion Desc string } func NewPermissionError(t keybase1.TeamID, uv keybase1.UserVersion, d string) PermissionError { return PermissionError{t, uv, d} } func (e PermissionError) Error() string { return fmt.Sprintf("For team %s, user %s: %s", e.TeamID, e.UserVersion.PercentForm(), e.Desc) } type PrevError struct { Msg string } func NewPrevError(format string, args ...any) error { return PrevError{fmt.Sprintf(format, args...)} } func (e PrevError) Error() string { return e.Msg } type InviteError struct { id keybase1.TeamInviteID err error } func NewInviteError(id keybase1.TeamInviteID, err error) InviteError { return InviteError{id: id, err: err} } func (i InviteError) Error() string { return fmt.Sprintf("Invite error: Invite ID %s: %s", i.id, i.err) } func (i InviteError) Unwrap() error { return i.err } type InvitelinkBadRoleError struct { role keybase1.TeamRole } func NewInvitelinkBadRoleError(role keybase1.TeamRole) InvitelinkBadRoleError { return InvitelinkBadRoleError{role: role} } func (i InvitelinkBadRoleError) Error() string { return fmt.Sprintf("Cannot create invitelink to add invitees as %s", i.role) } type ResolveError struct { name keybase1.TeamName id keybase1.TeamID } func (e ResolveError) Error() string { return fmt.Sprintf("mismatched team name and id: %v <-/-> %v", e.name.String(), e.id.String()) } func NewResolveError(name keybase1.TeamName, id keybase1.TeamID) ResolveError { return ResolveError{name, id} } type TeamDoesNotExistError struct { descriptor string public bool // Whether this is about the public version of the team } func (e TeamDoesNotExistError) Error() string { if e.public { return fmt.Sprintf("Team %q (public) does not exist", e.descriptor) } return fmt.Sprintf("Team %q does not exist", e.descriptor) } func NewTeamDoesNotExistError(public bool, format string, args ...any) error { return TeamDoesNotExistError{ descriptor: fmt.Sprintf(format, args...), public: public, } } type ImplicitTeamOperationError struct { msg string } func (e ImplicitTeamOperationError) Error() string { return fmt.Sprintf("Implicit team operation not allowed: %v", e.msg) } type ExplicitTeamOperationError struct { msg string } func (e ExplicitTeamOperationError) Error() string { return fmt.Sprintf("Operation only allowed on implicit teams: %s", e.msg) } func NewImplicitTeamOperationError(format string, args ...any) error { return &ImplicitTeamOperationError{msg: fmt.Sprintf(format, args...)} } func NewExplicitTeamOperationError(m string) error { return &ExplicitTeamOperationError{msg: m} } func IsTeamReadError(err error) bool { var aerr libkb.AppStatusError return errors.As(err, &aerr) && keybase1.StatusCode(aerr.Code) == keybase1.StatusCode_SCTeamReadError } func FixupTeamGetError(ctx context.Context, g *libkb.GlobalContext, e error, teamDescriptor string, publicTeam bool) error { return fixupTeamGetError(ctx, g, e, teamDescriptor, publicTeam) } func fixupTeamGetError(ctx context.Context, g *libkb.GlobalContext, e error, teamDescriptor string, publicTeam bool) error { if e == nil { return nil } switch e := e.(type) { case libkb.AppStatusError: switch keybase1.StatusCode(e.Code) { case keybase1.StatusCode_SCTeamReadError: g.Log.CDebugf(ctx, "replacing error: %v", e) e.Desc = fmt.Sprintf("You are not a member of team %q; try `keybase team request-access %s` for access", teamDescriptor, teamDescriptor) return e case keybase1.StatusCode_SCTeamNotFound: g.Log.CDebugf(ctx, "replacing error: %v", e) return NewTeamDoesNotExistError(publicTeam, "%s", teamDescriptor) } case TeamDoesNotExistError: // Replace the not found error so that it has a name instead of team ID. // If subteams are involved the name might not correspond to the ID // but it's better to have this understandable error message that's accurate // most of the time than one with an ID that's always accurate. g.Log.CDebugf(ctx, "replacing error: %v", e) return NewTeamDoesNotExistError(publicTeam, "%s", teamDescriptor) } return e } func NewKeyMaskNotFoundErrorForApplication(a keybase1.TeamApplication) libkb.KeyMaskNotFoundError { return libkb.KeyMaskNotFoundError{App: a} } func NewKeyMaskNotFoundErrorForApplicationAndGeneration(a keybase1.TeamApplication, g keybase1.PerTeamKeyGeneration) libkb.KeyMaskNotFoundError { return libkb.KeyMaskNotFoundError{App: a, Gen: g} } type AdminPermissionRequiredError struct{} func NewAdminPermissionRequiredError() error { return &AdminPermissionRequiredError{} } func (e *AdminPermissionRequiredError) Error() string { return "Only admins can perform this operation." } type ImplicitAdminCannotLeaveError struct{} func NewImplicitAdminCannotLeaveError() error { return &ImplicitAdminCannotLeaveError{} } func (e ImplicitAdminCannotLeaveError) Error() string { return "You cannot leave this team. You are an implicit admin (admin of a parent team) but not an explicit member." } type NotExplicitMemberOfSubteamError struct{} func NewNotExplicitMemberOfSubteamError() error { return NotExplicitMemberOfSubteamError{} } func (e NotExplicitMemberOfSubteamError) Error() string { return "You are not an explicit member of this subteam, so you can't access chats or files; try adding yourself (if you're an admin of the parent team)" } func (e NotExplicitMemberOfSubteamError) HumanError() error { return e } type TeamTombstonedError struct{} func NewTeamTombstonedError() error { return &TeamTombstonedError{} } func (e TeamTombstonedError) Error() string { return "team has been tombstoned" } type TeamDeletedError struct{} func NewTeamDeletedError() error { return &TeamDeletedError{} } func (e TeamDeletedError) Error() string { return "team has been deleted" } type SubteamOwnersError struct{} func NewSubteamOwnersError() error { return &SubteamOwnersError{} } func (e SubteamOwnersError) Error() string { return "Subteams cannot have owners. Try admin instead." } // The sigchain link is problematically new. type GreenLinkError struct{ seqno keybase1.Seqno } func NewGreenLinkError(seqno keybase1.Seqno) error { return GreenLinkError{seqno: seqno} } func (e GreenLinkError) Error() string { // Report the probable cause for this error. return fmt.Sprintf("team sigchain is being rapidly updated (seqno: %v)", e.seqno) } type UnsupportedLinkTypeError struct { outerType libkb.SigchainV2Type innerType string } func NewUnsupportedLinkTypeError(outerType libkb.SigchainV2Type, innerType string) error { return UnsupportedLinkTypeError{ outerType: outerType, innerType: innerType, } } func (e UnsupportedLinkTypeError) Error() string { return fmt.Sprintf("unsupported team link type: %v (%v)", e.outerType, e.innerType) } type PrecheckAppendError struct { Inner error } func NewPrecheckAppendError(inner error) error { return PrecheckAppendError{Inner: inner} } func (e PrecheckAppendError) Error() string { return fmt.Sprintf("Precheck append error: %v", e.Inner) } func (e PrecheckAppendError) Unwrap() error { return e.Inner } type PrecheckStructuralError struct { Inner error Msg string } func NewPrecheckStructuralError(message string, inner error) error { return PrecheckStructuralError{Inner: inner, Msg: message} } func (e PrecheckStructuralError) Error() string { if e.Inner != nil { return fmt.Sprintf("Precheck structural error: %s: %v", e.Msg, e.Inner) } return e.Msg } func (e PrecheckStructuralError) Unwrap() error { return e.Inner } type AttemptedInviteSocialOwnerError struct{ Msg string } func NewAttemptedInviteSocialOwnerError(assertion string) error { them := assertion if assertion == "" { them = "That user" } return AttemptedInviteSocialOwnerError{Msg: fmt.Sprintf("%v doesn't have a Keybase account yet, so you can't add them"+ " as an owner; you can add them as reader or writer.", them)} } func (e AttemptedInviteSocialOwnerError) Error() string { return e.Msg } type UserHasNotResetError struct{ Msg string } func NewUserHasNotResetError(format string, args ...any) error { return UserHasNotResetError{Msg: fmt.Sprintf(format, args...)} } func (e UserHasNotResetError) Error() string { return e.Msg } type AddMembersError struct { Assertion libkb.AssertionExpression Err error } func NewAddMembersError(a libkb.AssertionExpression, e error) AddMembersError { return AddMembersError{a, e} } func (a AddMembersError) Error() string { if a.Assertion == nil { return fmt.Sprintf("Error adding members: %v", a.Err) } urls := a.Assertion.CollectUrls(nil) if len(urls) == 1 && urls[0].IsEmail() { return fmt.Sprintf("Error adding email %q: %v", urls[0].GetValue(), a.Err) } return fmt.Sprintf("Error adding %q: %v", a.Assertion.String(), a.Err) } func (a AddMembersError) Unwrap() error { return a.Err } type BadNameError struct { Msg string } func (b BadNameError) Error() string { return fmt.Sprintf("bad name error: %s", b.Msg) } func NewBadNameError(s string) BadNameError { return BadNameError{Msg: s} } type FastLoadError struct { Msg string } func (f FastLoadError) Error() string { return fmt.Sprintf("fast load error: %s", f.Msg) } func NewFastLoadError(format string, args ...any) error { return FastLoadError{Msg: fmt.Sprintf(format, args...)} } type BadPublicError struct { id keybase1.TeamID isPublic bool } func NewBadPublicError(id keybase1.TeamID, isPublic bool) error { return BadPublicError{id, isPublic} } func (e BadPublicError) Error() string { return fmt.Sprintf("Public bit for team %s is wrong (%v)", e.id, e.isPublic) } type AuditError struct { Msg string } func NewAuditError(format string, args ...any) error { return AuditError{Msg: fmt.Sprintf(format, args...)} } func (e AuditError) Error() string { return fmt.Sprintf("Audit error: %s", e.Msg) } type KBFSKeyGenerationError struct { Required, Exists int } func NewKBFSKeyGenerationError(required, exists int) KBFSKeyGenerationError { return KBFSKeyGenerationError{ Required: required, Exists: exists, } } func (e KBFSKeyGenerationError) Error() string { return fmt.Sprintf("KBFS key generation too low: %v < %v", e.Exists, e.Required) } type FTLMissingSeedError struct { gen keybase1.PerTeamKeyGeneration } func NewFTLMissingSeedError(g keybase1.PerTeamKeyGeneration) error { return FTLMissingSeedError{gen: g} } func (e FTLMissingSeedError) Error() string { return fmt.Sprintf("FTL Missing seed at generation: %d", e.gen) } type MixedServerTrustAssertionError struct{} func NewMixedServerTrustAssertionError() error { return MixedServerTrustAssertionError{} } func (e MixedServerTrustAssertionError) Error() string { return "cannot add team members via server trust (email or SMS) and also with checkable assertions" } type CompoundInviteError struct { Assertion string } func NewCompoundInviteError(s string) error { return CompoundInviteError{s} } func (e CompoundInviteError) Error() string { return fmt.Sprintf("cannot pair an invitation with a compound assertion (%s)", e.Assertion) } type StaleBoxError interface { IsStaleBoxError() } type BoxRaceError struct { inner error } func (e BoxRaceError) Error() string { return e.inner.Error() } func (e BoxRaceError) Unwrap() error { return e.inner } func (e BoxRaceError) IsStaleBoxError() {} func isStaleBoxError(err error) bool { if err == nil { return false } var sbe StaleBoxError return errors.As(err, &sbe) } type NeedHiddenChainRotationError struct{} func (e NeedHiddenChainRotationError) Error() string { return "need hidden chain rotation" } type MissingReaderKeyMaskError struct { gen keybase1.PerTeamKeyGeneration app keybase1.TeamApplication } func NewMissingReaderKeyMaskError(gen keybase1.PerTeamKeyGeneration, app keybase1.TeamApplication) error { return MissingReaderKeyMaskError{gen, app} } func (e MissingReaderKeyMaskError) Error() string { return fmt.Sprintf("missing reader key mask for gen:%v app:%v", e.gen, e.app) } type MapAncestorsError struct { err error // failedLoadingAtAncestorIdx indicates the team the MapTeamAncestors load failed at. // So if it failed loading the initial team passed in, failedLoadingAtAncestorIdx=0. // Each successive parent team adds one to the index. So if the team tree were // A.B.C.D.E and MapTeamAncestors was called on D, and the function failed at B, // failed=2. failedLoadingAtAncestorIdx int } func NewMapAncestorsError(err error, failedLoadingAtAncestorIdx int) error { return &MapAncestorsError{err, failedLoadingAtAncestorIdx} } func (e *MapAncestorsError) Error() string { return fmt.Sprintf("failed to load ancestor %d during load: %s", e.failedLoadingAtAncestorIdx, e.err) } func (e *MapAncestorsError) Unwrap() error { return e.err } // MemberNotFoundInChainError is an error that is returned when a member is not in a team, and this // fact is verified in the sigchain (i.e., not servertrust). type MemberNotFoundInChainError struct { err error } func NewMemberNotFoundInChainError(err error) error { return &MemberNotFoundInChainError{err} } func (e *MemberNotFoundInChainError) Error() string { return fmt.Sprintf("could not find team member in team: %s", e.err) } func (e *MemberNotFoundInChainError) Unwrap() error { return e.err } type InviteLinkAcceptanceError struct { Cause error } func (e InviteLinkAcceptanceError) Error() string { return fmt.Sprintf("InviteLinkAcceptanceError: %s", e.Cause) } func (e InviteLinkAcceptanceError) Unwrap() error { return e.Cause } func NewInviteLinkAcceptanceError(format string, args ...any) InviteLinkAcceptanceError { return InviteLinkAcceptanceError{fmt.Errorf(format, args...)} }