1package teams 2 3import ( 4 "fmt" 5 6 "golang.org/x/net/context" 7 8 "github.com/keybase/client/go/libkb" 9 "github.com/keybase/client/go/protocol/keybase1" 10) 11 12func NewStubbedError(l *ChainLinkUnpacked) StubbedError { 13 return StubbedError{l: l, note: nil} 14} 15 16func NewStubbedErrorWithNote(l *ChainLinkUnpacked, note string) StubbedError { 17 return StubbedError{l: l, note: ¬e} 18} 19 20type StubbedError struct { 21 l *ChainLinkUnpacked 22 note *string 23} 24 25func (e StubbedError) Error() string { 26 if e.note == nil { 27 return fmt.Sprintf("stubbed link when not expected (seqno %d)", int(e.l.outerLink.Seqno)) 28 } 29 return fmt.Sprintf("%s (stubbed link when not expected; at seqno %d)", 30 *e.note, int(e.l.outerLink.Seqno)) 31} 32 33type InvalidLink struct { 34 l *ChainLinkUnpacked 35 note string 36} 37 38func (e InvalidLink) Error() string { 39 return fmt.Sprintf("invalid link (seqno %d): %s", e.l.Seqno(), e.note) 40} 41 42func NewInvalidLink(l *ChainLinkUnpacked, format string, args ...interface{}) InvalidLink { 43 return InvalidLink{l, fmt.Sprintf(format, args...)} 44} 45 46type AppendLinkError struct { 47 prevSeqno keybase1.Seqno 48 l *ChainLinkUnpacked 49 inner error 50} 51 52func (e AppendLinkError) Error() string { 53 return fmt.Sprintf("appending %v->%v: %v", e.prevSeqno, e.l.Seqno(), e.inner) 54} 55 56func (e AppendLinkError) Unwrap() error { 57 return e.inner 58} 59 60func NewAppendLinkError(l *ChainLinkUnpacked, prevSeqno keybase1.Seqno, inner error) AppendLinkError { 61 return AppendLinkError{prevSeqno, l, inner} 62} 63 64type InflateError struct { 65 l *ChainLinkUnpacked 66 note *string 67} 68 69func (e InflateError) Error() string { 70 if e.note == nil { 71 return fmt.Sprintf("error inflating previously-stubbed link (seqno %d)", int(e.l.outerLink.Seqno)) 72 } 73 return fmt.Sprintf("error inflating previously-stubbed link (seqno %d) (%s)", 74 int(e.l.outerLink.Seqno), *e.note) 75} 76 77func NewInflateError(l *ChainLinkUnpacked) InflateError { 78 return InflateError{l: l, note: nil} 79} 80 81func NewInflateErrorWithNote(l *ChainLinkUnpacked, note string) InflateError { 82 return InflateError{l: l, note: ¬e} 83} 84 85type UnexpectedSeqnoError struct { 86 expected keybase1.Seqno 87 actual keybase1.Seqno 88} 89 90func (e UnexpectedSeqnoError) Error() string { 91 return fmt.Sprintf("expected seqno:%v but got %v", e.expected, e.actual) 92} 93 94func NewUnexpectedSeqnoError(expected, actual keybase1.Seqno) UnexpectedSeqnoError { 95 return UnexpectedSeqnoError{expected, actual} 96} 97 98type AdminPermissionError struct { 99 TeamID keybase1.TeamID 100 UserVersion keybase1.UserVersion 101 Desc string 102} 103 104func (e AdminPermissionError) Error() string { 105 return fmt.Sprintf("For team %s, user %s: %s", e.TeamID, e.UserVersion.PercentForm(), e.Desc) 106} 107 108func NewAdminPermissionError(t keybase1.TeamID, uv keybase1.UserVersion, d string) AdminPermissionError { 109 return AdminPermissionError{t, uv, d} 110} 111 112type AdminNotFoundError struct { 113 Admin SCTeamAdmin 114} 115 116func (e AdminNotFoundError) Error() string { 117 return fmt.Sprintf("Admin permission specified in %+v wasn't found", e.Admin) 118} 119 120func NewAdminNotFoundError(a SCTeamAdmin) AdminNotFoundError { 121 return AdminNotFoundError{a} 122} 123 124type ProofError struct { 125 p proof 126 msg string 127} 128 129func NewProofError(p proof, s string) ProofError { 130 return ProofError{p, s} 131} 132 133func (p ProofError) Error() string { 134 return fmt.Sprintf("proof error for proof '%s': %s", p.p.reason, p.msg) 135} 136 137type PermissionError struct { 138 TeamID keybase1.TeamID 139 UserVersion keybase1.UserVersion 140 Desc string 141} 142 143func NewPermissionError(t keybase1.TeamID, uv keybase1.UserVersion, d string) PermissionError { 144 return PermissionError{t, uv, d} 145} 146 147func (e PermissionError) Error() string { 148 return fmt.Sprintf("For team %s, user %s: %s", e.TeamID, e.UserVersion.PercentForm(), e.Desc) 149} 150 151type PrevError struct { 152 Msg string 153} 154 155func NewPrevError(format string, args ...interface{}) error { 156 return PrevError{fmt.Sprintf(format, args...)} 157} 158 159func (e PrevError) Error() string { 160 return e.Msg 161} 162 163type InviteError struct { 164 id keybase1.TeamInviteID 165 err error 166} 167 168func NewInviteError(id keybase1.TeamInviteID, err error) InviteError { 169 return InviteError{id: id, err: err} 170} 171 172func (i InviteError) Error() string { 173 return fmt.Sprintf("Invite error: Invite ID %s: %s", i.id, i.err) 174} 175 176func (i InviteError) Unwrap() error { 177 return i.err 178} 179 180type InvitelinkBadRoleError struct { 181 role keybase1.TeamRole 182} 183 184func NewInvitelinkBadRoleError(role keybase1.TeamRole) InvitelinkBadRoleError { 185 return InvitelinkBadRoleError{role: role} 186} 187 188func (i InvitelinkBadRoleError) Error() string { 189 return fmt.Sprintf("Cannot create invitelink to add invitees as %s", i.role) 190} 191 192type ResolveError struct { 193 name keybase1.TeamName 194 id keybase1.TeamID 195} 196 197func (e ResolveError) Error() string { 198 return fmt.Sprintf("mismatched team name and id: %v <-/-> %v", e.name.String(), e.id.String()) 199} 200 201func NewResolveError(name keybase1.TeamName, id keybase1.TeamID) ResolveError { 202 return ResolveError{name, id} 203} 204 205type TeamDoesNotExistError struct { 206 descriptor string 207 public bool // Whether this is about the public version of the team 208} 209 210func (e TeamDoesNotExistError) Error() string { 211 if e.public { 212 return fmt.Sprintf("Team %q (public) does not exist", e.descriptor) 213 } 214 return fmt.Sprintf("Team %q does not exist", e.descriptor) 215} 216 217func NewTeamDoesNotExistError(public bool, format string, args ...interface{}) error { 218 return TeamDoesNotExistError{ 219 descriptor: fmt.Sprintf(format, args...), 220 public: public, 221 } 222} 223 224type ImplicitTeamOperationError struct { 225 msg string 226} 227 228func (e ImplicitTeamOperationError) Error() string { 229 return fmt.Sprintf("Implicit team operation not allowed: %v", e.msg) 230} 231 232type ExplicitTeamOperationError struct { 233 msg string 234} 235 236func (e ExplicitTeamOperationError) Error() string { 237 return fmt.Sprintf("Operation only allowed on implicit teams: %s", e.msg) 238} 239 240func NewImplicitTeamOperationError(format string, args ...interface{}) error { 241 return &ImplicitTeamOperationError{msg: fmt.Sprintf(format, args...)} 242} 243 244func NewExplicitTeamOperationError(m string) error { 245 return &ExplicitTeamOperationError{msg: m} 246} 247 248func IsTeamReadError(err error) bool { 249 aerr, ok := err.(libkb.AppStatusError) 250 return ok && keybase1.StatusCode(aerr.Code) == keybase1.StatusCode_SCTeamReadError 251} 252 253func FixupTeamGetError(ctx context.Context, g *libkb.GlobalContext, e error, teamDescriptor string, publicTeam bool) error { 254 return fixupTeamGetError(ctx, g, e, teamDescriptor, publicTeam) 255} 256 257func fixupTeamGetError(ctx context.Context, g *libkb.GlobalContext, e error, teamDescriptor string, publicTeam bool) error { 258 if e == nil { 259 return nil 260 } 261 switch e := e.(type) { 262 case libkb.AppStatusError: 263 switch keybase1.StatusCode(e.Code) { 264 case keybase1.StatusCode_SCTeamReadError: 265 g.Log.CDebugf(ctx, "replacing error: %v", e) 266 e.Desc = fmt.Sprintf("You are not a member of team %q; try `keybase team request-access %s` for access", teamDescriptor, teamDescriptor) 267 return e 268 case keybase1.StatusCode_SCTeamNotFound: 269 g.Log.CDebugf(ctx, "replacing error: %v", e) 270 return NewTeamDoesNotExistError(publicTeam, teamDescriptor) 271 } 272 case TeamDoesNotExistError: 273 // Replace the not found error so that it has a name instead of team ID. 274 // If subteams are involved the name might not correspond to the ID 275 // but it's better to have this understandable error message that's accurate 276 // most of the time than one with an ID that's always accurate. 277 g.Log.CDebugf(ctx, "replacing error: %v", e) 278 return NewTeamDoesNotExistError(publicTeam, teamDescriptor) 279 } 280 return e 281} 282 283func NewKeyMaskNotFoundErrorForApplication(a keybase1.TeamApplication) libkb.KeyMaskNotFoundError { 284 return libkb.KeyMaskNotFoundError{App: a} 285} 286 287func NewKeyMaskNotFoundErrorForApplicationAndGeneration(a keybase1.TeamApplication, g keybase1.PerTeamKeyGeneration) libkb.KeyMaskNotFoundError { 288 return libkb.KeyMaskNotFoundError{App: a, Gen: g} 289} 290 291type AdminPermissionRequiredError struct{} 292 293func NewAdminPermissionRequiredError() error { return &AdminPermissionRequiredError{} } 294 295func (e *AdminPermissionRequiredError) Error() string { 296 return "Only admins can perform this operation." 297} 298 299type ImplicitAdminCannotLeaveError struct{} 300 301func NewImplicitAdminCannotLeaveError() error { return &ImplicitAdminCannotLeaveError{} } 302 303func (e ImplicitAdminCannotLeaveError) Error() string { 304 return "You cannot leave this team. You are an implicit admin (admin of a parent team) but not an explicit member." 305} 306 307type NotExplicitMemberOfSubteamError struct{} 308 309func NewNotExplicitMemberOfSubteamError() error { return NotExplicitMemberOfSubteamError{} } 310 311func (e NotExplicitMemberOfSubteamError) Error() string { 312 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)" 313} 314 315func (e NotExplicitMemberOfSubteamError) HumanError() error { 316 return e 317} 318 319type TeamTombstonedError struct{} 320 321func NewTeamTombstonedError() error { return &TeamTombstonedError{} } 322 323func (e TeamTombstonedError) Error() string { 324 return "team has been tombstoned" 325} 326 327type TeamDeletedError struct{} 328 329func NewTeamDeletedError() error { return &TeamDeletedError{} } 330 331func (e TeamDeletedError) Error() string { 332 return "team has been deleted" 333} 334 335type SubteamOwnersError struct{} 336 337func NewSubteamOwnersError() error { return &SubteamOwnersError{} } 338 339func (e SubteamOwnersError) Error() string { 340 return "Subteams cannot have owners. Try admin instead." 341} 342 343// The sigchain link is problematically new. 344type GreenLinkError struct{ seqno keybase1.Seqno } 345 346func NewGreenLinkError(seqno keybase1.Seqno) error { 347 return GreenLinkError{seqno: seqno} 348} 349 350func (e GreenLinkError) Error() string { 351 // Report the probable cause for this error. 352 return fmt.Sprintf("team sigchain is being rapidly updated (seqno: %v)", e.seqno) 353} 354 355type UnsupportedLinkTypeError struct { 356 outerType libkb.SigchainV2Type 357 innerType string 358} 359 360func NewUnsupportedLinkTypeError(outerType libkb.SigchainV2Type, innerType string) error { 361 return UnsupportedLinkTypeError{ 362 outerType: outerType, 363 innerType: innerType, 364 } 365} 366 367func (e UnsupportedLinkTypeError) Error() string { 368 return fmt.Sprintf("unsupported team link type: %v (%v)", e.outerType, e.innerType) 369} 370 371type PrecheckAppendError struct { 372 Inner error 373} 374 375func NewPrecheckAppendError(inner error) error { return PrecheckAppendError{Inner: inner} } 376 377func (e PrecheckAppendError) Error() string { 378 return fmt.Sprintf("Precheck append error: %v", e.Inner) 379} 380 381func (e PrecheckAppendError) Unwrap() error { 382 return e.Inner 383} 384 385type PrecheckStructuralError struct { 386 Inner error 387 Msg string 388} 389 390func NewPrecheckStructuralError(message string, inner error) error { 391 return PrecheckStructuralError{Inner: inner, Msg: message} 392} 393 394func (e PrecheckStructuralError) Error() string { 395 if e.Inner != nil { 396 return fmt.Sprintf("Precheck structural error: %s: %v", e.Msg, e.Inner) 397 } 398 return e.Msg 399} 400 401type AttemptedInviteSocialOwnerError struct{ Msg string } 402 403func NewAttemptedInviteSocialOwnerError(assertion string) error { 404 them := assertion 405 if assertion == "" { 406 them = "That user" 407 } 408 return AttemptedInviteSocialOwnerError{Msg: fmt.Sprintf("%v doesn't have a Keybase account yet, so you can't add them"+ 409 " as an owner; you can add them as reader or writer.", them)} 410} 411 412func (e AttemptedInviteSocialOwnerError) Error() string { return e.Msg } 413 414type UserHasNotResetError struct{ Msg string } 415 416func NewUserHasNotResetError(format string, args ...interface{}) error { 417 return UserHasNotResetError{Msg: fmt.Sprintf(format, args...)} 418} 419 420func (e UserHasNotResetError) Error() string { return e.Msg } 421 422type AddMembersError struct { 423 Assertion libkb.AssertionExpression 424 Err error 425} 426 427func NewAddMembersError(a libkb.AssertionExpression, e error) AddMembersError { 428 return AddMembersError{a, e} 429} 430 431func (a AddMembersError) Error() string { 432 if a.Assertion == nil { 433 return fmt.Sprintf("Error adding members: %v", a.Err) 434 } 435 urls := a.Assertion.CollectUrls(nil) 436 if len(urls) == 1 && urls[0].IsEmail() { 437 return fmt.Sprintf("Error adding email %q: %v", urls[0].GetValue(), a.Err) 438 } 439 return fmt.Sprintf("Error adding %q: %v", a.Assertion.String(), a.Err) 440} 441 442type BadNameError struct { 443 Msg string 444} 445 446func (b BadNameError) Error() string { 447 return fmt.Sprintf("bad name error: %s", b.Msg) 448} 449 450func NewBadNameError(s string) BadNameError { 451 return BadNameError{Msg: s} 452} 453 454type FastLoadError struct { 455 Msg string 456} 457 458func (f FastLoadError) Error() string { 459 return fmt.Sprintf("fast load error: %s", f.Msg) 460} 461 462func NewFastLoadError(format string, args ...interface{}) error { 463 return FastLoadError{Msg: fmt.Sprintf(format, args...)} 464} 465 466type BadPublicError struct { 467 id keybase1.TeamID 468 isPublic bool 469} 470 471func NewBadPublicError(id keybase1.TeamID, isPublic bool) error { 472 return BadPublicError{id, isPublic} 473} 474 475func (e BadPublicError) Error() string { 476 return fmt.Sprintf("Public bit for team %s is wrong (%v)", e.id, e.isPublic) 477} 478 479type AuditError struct { 480 Msg string 481} 482 483func NewAuditError(format string, args ...interface{}) error { 484 return AuditError{Msg: fmt.Sprintf(format, args...)} 485} 486 487func (e AuditError) Error() string { 488 return fmt.Sprintf("Audit error: %s", e.Msg) 489} 490 491type KBFSKeyGenerationError struct { 492 Required, Exists int 493} 494 495func NewKBFSKeyGenerationError(required, exists int) KBFSKeyGenerationError { 496 return KBFSKeyGenerationError{ 497 Required: required, 498 Exists: exists, 499 } 500} 501 502func (e KBFSKeyGenerationError) Error() string { 503 return fmt.Sprintf("KBFS key generation too low: %v < %v", e.Exists, e.Required) 504} 505 506type FTLMissingSeedError struct { 507 gen keybase1.PerTeamKeyGeneration 508} 509 510func NewFTLMissingSeedError(g keybase1.PerTeamKeyGeneration) error { 511 return FTLMissingSeedError{gen: g} 512} 513 514func (e FTLMissingSeedError) Error() string { 515 return fmt.Sprintf("FTL Missing seed at generation: %d", e.gen) 516} 517 518type MixedServerTrustAssertionError struct{} 519 520func NewMixedServerTrustAssertionError() error { 521 return MixedServerTrustAssertionError{} 522} 523 524func (e MixedServerTrustAssertionError) Error() string { 525 return "cannot add team members via server trust (email or SMS) and also with checkable assertions" 526} 527 528type CompoundInviteError struct { 529 Assertion string 530} 531 532func NewCompoundInviteError(s string) error { 533 return CompoundInviteError{s} 534} 535 536func (e CompoundInviteError) Error() string { 537 return fmt.Sprintf("cannot pair an invitation with a compound assertion (%s)", e.Assertion) 538} 539 540type StaleBoxError interface { 541 IsStaleBoxError() 542} 543 544type BoxRaceError struct { 545 inner error 546} 547 548func (e BoxRaceError) Error() string { 549 return e.inner.Error() 550} 551 552func (e BoxRaceError) IsStaleBoxError() {} 553 554func isStaleBoxError(err error) bool { 555 if err == nil { 556 return false 557 } 558 _, ok := err.(StaleBoxError) 559 return ok 560} 561 562type NeedHiddenChainRotationError struct{} 563 564func (e NeedHiddenChainRotationError) Error() string { 565 return "need hidden chain rotation" 566} 567 568type MissingReaderKeyMaskError struct { 569 gen keybase1.PerTeamKeyGeneration 570 app keybase1.TeamApplication 571} 572 573func NewMissingReaderKeyMaskError(gen keybase1.PerTeamKeyGeneration, app keybase1.TeamApplication) error { 574 return MissingReaderKeyMaskError{gen, app} 575} 576 577func (e MissingReaderKeyMaskError) Error() string { 578 return fmt.Sprintf("missing reader key mask for gen:%v app:%v", e.gen, e.app) 579} 580 581type MapAncestorsError struct { 582 err error 583 584 // failedLoadingAtAncestorIdx indicates the team the MapTeamAncestors load failed at. 585 // So if it failed loading the initial team passed in, failedLoadingAtAncestorIdx=0. 586 // Each successive parent team adds one to the index. So if the team tree were 587 // A.B.C.D.E and MapTeamAncestors was called on D, and the function failed at B, 588 // failed=2. 589 failedLoadingAtAncestorIdx int 590} 591 592func NewMapAncestorsError(err error, failedLoadingAtAncestorIdx int) error { 593 return &MapAncestorsError{err, failedLoadingAtAncestorIdx} 594} 595 596func (e *MapAncestorsError) Error() string { 597 return fmt.Sprintf("failed to load ancestor %d during load: %s", 598 e.failedLoadingAtAncestorIdx, e.err) 599} 600 601func (e *MapAncestorsError) Unwrap() error { 602 return e.err 603} 604 605// MemberNotFoundInChainError is an error that is returned when a member is not in a team, and this 606// fact is verified in the sigchain (i.e., not servertrust). 607type MemberNotFoundInChainError struct { 608 err error 609} 610 611func NewMemberNotFoundInChainError(err error) error { 612 return &MemberNotFoundInChainError{err} 613} 614 615func (e *MemberNotFoundInChainError) Error() string { 616 return fmt.Sprintf("could not find team member in team: %s", e.err) 617} 618 619func (e *MemberNotFoundInChainError) Unwrap() error { 620 return e.err 621} 622 623type InviteLinkAcceptanceError struct { 624 Cause error 625} 626 627func (e InviteLinkAcceptanceError) Error() string { 628 return fmt.Sprintf("InviteLinkAcceptanceError: %s", e.Cause) 629} 630 631func NewInviteLinkAcceptanceError(format string, args ...interface{}) InviteLinkAcceptanceError { 632 return InviteLinkAcceptanceError{fmt.Errorf(format, args...)} 633} 634