bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
68 lines
2.4 KiB
Go
68 lines
2.4 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package auth
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/larksuite/cli/errs"
|
|
"github.com/larksuite/cli/internal/output"
|
|
)
|
|
|
|
const (
|
|
needUserAuthorizationMarker = "need_user_authorization"
|
|
)
|
|
|
|
// TokenRetryCodes contains error codes that allow retry after token refresh.
|
|
var TokenRetryCodes = map[int]bool{
|
|
output.LarkErrTokenInvalid: true,
|
|
output.LarkErrTokenExpired: true,
|
|
}
|
|
|
|
// NeedAuthorizationError is the sentinel preserved in the Cause chain of the
|
|
// typed missing-UAT error so existing errors.As(&NeedAuthorizationError{})
|
|
// consumers keep matching after the construction site moved to the typed
|
|
// taxonomy. It is never surfaced on the wire on its own.
|
|
type NeedAuthorizationError struct {
|
|
UserOpenId string
|
|
}
|
|
|
|
// Error returns the error message for NeedAuthorizationError.
|
|
func (e *NeedAuthorizationError) Error() string {
|
|
return fmt.Sprintf("%s (user: %s)", needUserAuthorizationMarker, e.UserOpenId)
|
|
}
|
|
|
|
// NewNeedUserAuthorizationError builds the typed *errs.AuthenticationError
|
|
// returned when no valid UAT exists for userOpenID. The Message keeps the
|
|
// need_user_authorization marker, the Hint converges on the same auth-login
|
|
// recovery vocabulary as the token-missing surface in internal/client, and the
|
|
// legacy *NeedAuthorizationError sentinel is preserved in the Cause chain for
|
|
// errors.As / errors.Is traversal.
|
|
func NewNeedUserAuthorizationError(userOpenID string) *errs.AuthenticationError {
|
|
return errs.NewAuthenticationError(errs.SubtypeTokenMissing,
|
|
"%s (user: %s)", needUserAuthorizationMarker, userOpenID).
|
|
WithUserOpenID(userOpenID).
|
|
WithHint("run: lark-cli auth login to re-authorize").
|
|
WithCause(&NeedAuthorizationError{UserOpenId: userOpenID})
|
|
}
|
|
|
|
// IsNeedUserAuthorizationError reports whether err represents a missing-UAT
|
|
// failure. It matches the legacy *NeedAuthorizationError sentinel, which is
|
|
// preserved in the Cause chain of the typed missing-UAT error, so errors.As
|
|
// traverses into the typed *errs.AuthenticationError as well.
|
|
func IsNeedUserAuthorizationError(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
|
|
var needAuthErr *NeedAuthorizationError
|
|
return errors.As(err, &needAuthErr)
|
|
}
|
|
|
|
// SecurityPolicyError is preserved as a Go type alias so existing
|
|
// errors.As(&SecurityPolicyError{}) consumers (cmd/root.go etc.) keep working.
|
|
// The concrete struct lives in errs/types.go.
|
|
type SecurityPolicyError = errs.SecurityPolicyError
|