Function bodies 134 total
googleapi.RetryTransport.sleep method · go · L151-L165 (15 LOC)internal/googleapi/transport.go
func (t *RetryTransport) sleep(ctx context.Context, d time.Duration) error {
if d <= 0 {
return nil
}
timer := time.NewTimer(d)
defer timer.Stop()
select {
case <-timer.C:
return nil
case <-ctx.Done():
return fmt.Errorf("sleep interrupted: %w", ctx.Err())
}
}googleapi.newBaseTransport function · go · L167-L190 (24 LOC)internal/googleapi/transport.go
func newBaseTransport() *http.Transport {
defaultTransport, ok := http.DefaultTransport.(*http.Transport)
if !ok || defaultTransport == nil {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
}
}
transport := defaultTransport.Clone()
if transport.TLSClientConfig == nil {
transport.TLSClientConfig = &tls.Config{MinVersion: tls.VersionTLS12}
return transport
}
if transport.TLSClientConfig.MinVersion < tls.VersionTLS12 {
transport.TLSClientConfig.MinVersion = tls.VersionTLS12
}
return transport
}googleapi.bytesReader.Read method · go · L202-L211 (10 LOC)internal/googleapi/transport.go
func (r *bytesReader) Read(p []byte) (n int, err error) {
if r.pos >= len(r.data) {
return 0, io.EOF
}
n = copy(p, r.data[r.pos:])
r.pos += n
return n, nil
}googleapi.ensureReplayableBody function · go · L213-L231 (19 LOC)internal/googleapi/transport.go
func ensureReplayableBody(req *http.Request) error {
if req == nil || req.Body == nil || req.GetBody != nil {
return nil
}
bodyBytes, err := io.ReadAll(req.Body)
if err != nil {
return fmt.Errorf("read request body: %w", err)
}
_ = req.Body.Close()
req.GetBody = func() (io.ReadCloser, error) {
return io.NopCloser(newBytesReader(bodyBytes)), nil
}
req.Body = io.NopCloser(newBytesReader(bodyBytes))
return nil
}googleapi.drainAndClose function · go · L233-L240 (8 LOC)internal/googleapi/transport.go
func drainAndClose(body io.ReadCloser) {
if body == nil {
return
}
_, _ = io.Copy(io.Discard, io.LimitReader(body, 1<<20))
_ = body.Close()
}googleauth.manualStatePath function · go · L79-L86 (8 LOC)internal/googleauth/oauth_flow.go
func manualStatePath(state string) (string, error) {
dir, err := manualStateDir()
if err != nil {
return "", err
}
return filepath.Join(dir, manualStateFilePrefix+state+manualStateFileSuffix), nil
}googleauth.saveManualState function · go · L88-L111 (24 LOC)internal/googleauth/oauth_flow.go
func saveManualState(st manualState) error {
path, err := manualStatePath(st.State)
if err != nil {
return err
}
data, err := json.MarshalIndent(st, "", " ")
if err != nil {
return fmt.Errorf("encode manual auth state: %w", err)
}
data = append(data, '\n')
tmp := path + ".tmp"
if err := os.WriteFile(tmp, data, 0o600); err != nil {
return fmt.Errorf("write manual auth state: %w", err)
}
if err := os.Rename(tmp, path); err != nil {
return fmt.Errorf("commit manual auth state: %w", err)
}
return nil
}Repobility · open methodology · https://repobility.com/research/
googleauth.loadManualState function · go · L113-L167 (55 LOC)internal/googleauth/oauth_flow.go
func loadManualState(scopes []string) (manualState, bool, error) {
dir, err := manualStateDir()
if err != nil {
return manualState{}, false, err
}
entries, err := os.ReadDir(dir)
if err != nil {
return manualState{}, false, fmt.Errorf("read manual auth state dir: %w", err)
}
normalizedScopes := normalizeScopes(scopes)
for _, ent := range entries {
if ent.IsDir() {
continue
}
name := ent.Name()
if !strings.HasPrefix(name, manualStateFilePrefix) || !strings.HasSuffix(name, manualStateFileSuffix) {
continue
}
path := filepath.Join(dir, name)
data, err := os.ReadFile(path) //nolint:gosec
if err != nil {
continue
}
var st manualState
if err := json.Unmarshal(data, &st); err != nil {
_ = os.Remove(path)
continue
}
if st.State == "" || st.RedirectURI == "" {
_ = os.Remove(path)
continue
}
if time.Since(st.CreatedAt) > manualStateTTL {
_ = os.Remove(path)
continue
}
if !scopesEqual(st.Scopes, normalizedScopes) {googleauth.loadManualStateByState function · go · L169-L210 (42 LOC)internal/googleauth/oauth_flow.go
func loadManualStateByState(state string, scopes []string) (manualState, bool, error) {
if strings.TrimSpace(state) == "" {
return manualState{}, false, nil
}
path, err := manualStatePath(state)
if err != nil {
return manualState{}, false, err
}
data, err := os.ReadFile(path) //nolint:gosec
if err != nil {
if os.IsNotExist(err) {
return manualState{}, false, nil
}
return manualState{}, false, fmt.Errorf("read manual auth state: %w", err)
}
var st manualState
if err := json.Unmarshal(data, &st); err != nil {
_ = os.Remove(path)
return manualState{}, false, nil
}
if st.State == "" || st.RedirectURI == "" {
_ = os.Remove(path)
return manualState{}, false, nil
}
if time.Since(st.CreatedAt) > manualStateTTL {
_ = os.Remove(path)
return manualState{}, false, nil
}
normalizedScopes := normalizeScopes(scopes)
if !scopesEqual(st.Scopes, normalizedScopes) {
return manualState{}, false, nil
}
return st, true, nil
}googleauth.clearManualState function · go · L212-L223 (12 LOC)internal/googleauth/oauth_flow.go
func clearManualState(state string) error {
path, err := manualStatePath(state)
if err != nil {
return err
}
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("remove manual auth state: %w", err)
}
return nil
}googleauth.randomState function · go · L225-L232 (8 LOC)internal/googleauth/oauth_flow.go
func randomState() (string, error) {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
return "", fmt.Errorf("generate state: %w", err)
}
return base64.RawURLEncoding.EncodeToString(b), nil
}googleauth.randomRedirectURI function · go · L234-L272 (39 LOC)internal/googleauth/oauth_flow.go
func randomRedirectURI(ctx context.Context) (string, error) {
ln, err := (&net.ListenConfig{}).Listen(ctx, "tcp", "127.0.0.1:0")
if err != nil {
return "", fmt.Errorf("listen for redirect port: %w", err)
}
defer func() { _ = ln.Close() }()
port := ln.Addr().(*net.TCPAddr).Port
return fmt.Sprintf("http://127.0.0.1:%d/oauth2/callback", port), nil
}
func parseRedirectURL(rawURL string) (code, state, redirectURI string, err error) {
parsed, err := url.Parse(strings.TrimSpace(rawURL))
if err != nil {
return "", "", "", fmt.Errorf("parse redirect url: %w", err)
}
if parsed.Scheme == "" || parsed.Host == "" {
return "", "", "", fmt.Errorf("parse redirect url: %w", errInvalidRedirectURL)
}
path := parsed.EscapedPath()
if path == "" {
path = "/"
}
redirectURI = fmt.Sprintf("%s://%s%s", parsed.Scheme, parsed.Host, path)
code = parsed.Query().Get("code")
if code == "" {
return "", "", "", errNoCodeInURL
}
state = parsed.Query().Get("state")
return code, stagoogleauth.authURLParams function · go · L274-L284 (11 LOC)internal/googleauth/oauth_flow.go
func authURLParams(forceConsent bool) []oauth2.AuthCodeOption {
opts := []oauth2.AuthCodeOption{
oauth2.AccessTypeOffline,
oauth2.SetAuthURLParam("include_granted_scopes", "true"),
}
if forceConsent {
opts = append(opts, oauth2.SetAuthURLParam("prompt", "consent"))
}
return opts
}googleauth.Step1 function · go · L289-L349 (61 LOC)internal/googleauth/oauth_flow.go
func Step1(ctx context.Context, creds config.ClientCredentials, opts AuthorizeOptions) (Step1Result, error) {
if len(opts.Scopes) == 0 {
return Step1Result{}, errMissingScopes
}
scopes := normalizeScopes(opts.Scopes)
// Reuse existing state if available.
if st, ok, err := loadManualState(scopes); err == nil && ok {
cfg := oauth2.Config{
ClientID: creds.ClientID,
ClientSecret: creds.ClientSecret,
Endpoint: oauthEndpoint,
RedirectURL: st.RedirectURI,
Scopes: scopes,
}
authURL := cfg.AuthCodeURL(st.State, authURLParams(opts.ForceConsent)...)
return Step1Result{
AuthURL: authURL,
NextStep: "run again with --auth-url <redirect URL from browser>",
}, nil
}
redirectURI, err := randomRedirectURI(ctx)
if err != nil {
return Step1Result{}, err
}
state, err := randomState()
if err != nil {
return Step1Result{}, err
}
st := manualState{
State: state,
RedirectURI: redirectURI,
Scopes: scopes,
CreatedAt: tigoogleauth.Step2 function · go · L352-L413 (62 LOC)internal/googleauth/oauth_flow.go
func Step2(ctx context.Context, creds config.ClientCredentials, opts AuthorizeOptions, redirectURLFromBrowser string) (Step2Result, error) {
if len(opts.Scopes) == 0 {
return Step2Result{}, errMissingScopes
}
code, state, redirectURI, err := parseRedirectURL(redirectURLFromBrowser)
if err != nil {
return Step2Result{}, err
}
if strings.TrimSpace(state) == "" {
return Step2Result{}, errMissingState
}
scopes := normalizeScopes(opts.Scopes)
st, ok, err := loadManualStateByState(state, scopes)
if err != nil {
return Step2Result{}, err
}
if !ok {
return Step2Result{}, fmt.Errorf("state mismatch or expired state; run step 1 again")
}
// Clean up state file after successful load.
defer func() { _ = clearManualState(st.State) }()
// Use stored redirect URI if available (more reliable), otherwise use parsed one.
if st.RedirectURI != "" {
redirectURI = st.RedirectURI
}
if redirectURI == "" {
return Step2Result{}, fmt.Errorf("missing redirect URI; run step 1Repobility · MCP-ready · https://repobility.com
googleauth.emailFromUserInfo function · go · L415-L460 (46 LOC)internal/googleauth/oauth_flow.go
func emailFromUserInfo(ctx context.Context, tok *oauth2.Token) (string, error) {
if tok == nil {
return "", errNoEmailInToken
}
accessToken := strings.TrimSpace(tok.AccessToken)
if accessToken == "" {
return "", errNoEmailInToken
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, oauthUserInfoEndpoint, nil)
if err != nil {
return "", fmt.Errorf("build userinfo request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+accessToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("request userinfo: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(io.LimitReader(resp.Body, oauthUserInfoBodyLimit))
return "", fmt.Errorf("userinfo status %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}
var claims struct {
Email string `json:"email"`
// Google returns this field in OpenID userinfo response.
EmailVerified bool `json:"email_verified"`
}
if err := jsongoogleauth.normalizeScopes function · go · L462-L471 (10 LOC)internal/googleauth/oauth_flow.go
func normalizeScopes(scopes []string) []string {
if len(scopes) == 0 {
return nil
}
out := append([]string(nil), scopes...)
sort.Strings(out)
return out
}googleauth.scopesEqual function · go · L473-L488 (16 LOC)internal/googleauth/oauth_flow.go
func scopesEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
na := normalizeScopes(a)
nb := normalizeScopes(b)
for i := range na {
if na[i] != nb[i] {
return false
}
}
return true
}googleauth.ParseService function · go · L60-L67 (8 LOC)internal/googleauth/service.go
func ParseService(s string) (Service, error) {
svc := Service(strings.ToLower(strings.TrimSpace(s)))
if _, ok := serviceScopes[svc]; ok {
return svc, nil
}
return "", fmt.Errorf("%w %q (expected gmail, calendar, docs, drive, sheets, or slides)", errUnknownService, s)
}googleauth.Scopes function · go · L70-L77 (8 LOC)internal/googleauth/service.go
func Scopes(service Service) ([]string, error) {
scopes, ok := serviceScopes[service]
if !ok {
return nil, errUnknownService
}
return append([]string(nil), scopes...), nil
}googleauth.ScopesForServices function · go · L80-L107 (28 LOC)internal/googleauth/service.go
func ScopesForServices(services []Service) ([]string, error) {
set := make(map[string]struct{})
for _, svc := range services {
scopes, err := Scopes(svc)
if err != nil {
return nil, fmt.Errorf("unknown service %q: %w", svc, err)
}
for _, s := range scopes {
set[s] = struct{}{}
}
}
// Always include identity scopes.
for _, s := range []string{scopeOpenID, scopeEmail, scopeUserinfoEmail} {
set[s] = struct{}{}
}
out := make([]string, 0, len(set))
for s := range set {
out = append(out, s)
}
sort.Strings(out)
return out, nil
}output.ExitCode function · go · L39-L50 (12 LOC)internal/output/output.go
func ExitCode(err error) int {
if err == nil {
return ExitCodeOK
}
var e *ExitCodeErr
if errors.As(err, &e) {
return e.Code
}
return ExitCodeError
}output.WriteJSON function · go · L53-L59 (7 LOC)internal/output/output.go
func WriteJSON(w io.Writer, val any) error {
enc := json.NewEncoder(w)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
return enc.Encode(val)
}Repobility — same analyzer, your code, free for public repos · /scan/
output.WriteError function · go · L69-L78 (10 LOC)internal/output/output.go
func WriteError(code int, codeStr, msg string) error {
payload := errorPayload{Error: msg, Code: codeStr}
enc := json.NewEncoder(os.Stderr)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
_ = enc.Encode(payload)
return &ExitCodeErr{Code: code, Err: fmt.Errorf("%s", msg)}
}secrets.fileKeyringPasswordFunc function · go · L55-L68 (14 LOC)internal/secrets/store.go
func fileKeyringPasswordFunc() keyring.PromptFunc {
password, passwordSet := os.LookupEnv(keyringPasswordEnv)
if passwordSet {
return keyring.FixedStringPrompt(password)
}
if term.IsTerminal(int(os.Stdin.Fd())) {
return keyring.TerminalPrompt
}
return func(_ string) (string, error) {
return "", fmt.Errorf("%w; set %s", errNoTTY, keyringPasswordEnv)
}
}secrets.openKeyring function · go · L70-L116 (47 LOC)internal/secrets/store.go
func openKeyring() (keyring.Keyring, error) {
keyringDir, err := config.EnsureKeyringDir()
if err != nil {
return nil, fmt.Errorf("ensure keyring dir: %w", err)
}
backendEnv := strings.ToLower(strings.TrimSpace(os.Getenv(keyringBackendEnv)))
var backends []keyring.BackendType
switch backendEnv {
case "keychain":
backends = []keyring.BackendType{keyring.KeychainBackend}
case "file":
if err := requireFileBackendPassword(backendEnv); err != nil {
return nil, err
}
backends = []keyring.BackendType{keyring.FileBackend}
default:
// On Linux with no D-Bus, force file backend to avoid hangs.
dbusAddr := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
if runtime.GOOS == "linux" && dbusAddr == "" {
backends = []keyring.BackendType{keyring.FileBackend}
}
}
cfg := keyring.Config{
ServiceName: config.AppName,
KeychainTrustApplication: false,
AllowedBackends: backends,
FileDir: keyringDir,
FilePasswordFunc: fileKeysecrets.requireFileBackendPassword function · go · L118-L124 (7 LOC)internal/secrets/store.go
func requireFileBackendPassword(backendEnv string) error {
if backendEnv == "file" && strings.TrimSpace(os.Getenv(keyringPasswordEnv)) == "" {
return errMissingKeyringPassword
}
return nil
}secrets.openKeyringWithTimeout function · go · L131-L150 (20 LOC)internal/secrets/store.go
func openKeyringWithTimeout(cfg keyring.Config, timeout time.Duration) (keyring.Keyring, error) {
ch := make(chan keyringResult, 1)
go func() {
ring, err := keyringOpenFunc(cfg)
ch <- keyringResult{ring, err}
}()
select {
case res := <-ch:
if res.err != nil {
return nil, fmt.Errorf("open keyring: %w", res.err)
}
return res.ring, nil
case <-time.After(timeout):
return nil, fmt.Errorf("%w after %v; set %s=file and %s=<password> to use file storage",
errKeyringTimeout, timeout, keyringBackendEnv, keyringPasswordEnv)
}
}secrets.OpenDefault function · go · L153-L160 (8 LOC)internal/secrets/store.go
func OpenDefault() (*Store, error) {
ring, err := openKeyring()
if err != nil {
return nil, err
}
return &Store{ring: ring}, nil
}secrets.keyringItem function · go · L166-L172 (7 LOC)internal/secrets/store.go
func keyringItem(key string, data []byte) keyring.Item {
return keyring.Item{
Key: key,
Data: data,
Label: config.AppName,
}
}secrets.Store.SetToken method · go · L175-L204 (30 LOC)internal/secrets/store.go
func (s *Store) SetToken(email string, tok Token) error {
email = strings.ToLower(strings.TrimSpace(email))
if email == "" {
return errMissingEmail
}
if tok.RefreshToken == "" {
return errMissingRefreshToken
}
if tok.CreatedAt.IsZero() {
tok.CreatedAt = time.Now().UTC()
}
payload, err := json.Marshal(storedToken{
RefreshToken: tok.RefreshToken,
Services: tok.Services,
Scopes: tok.Scopes,
CreatedAt: tok.CreatedAt,
})
if err != nil {
return fmt.Errorf("encode token: %w", err)
}
if err := s.ring.Set(keyringItem(tokenKey(email), payload)); err != nil {
return fmt.Errorf("store token: %w", err)
}
return nil
}Repobility analyzer · published findings · https://repobility.com
secrets.Store.GetToken method · go · L207-L230 (24 LOC)internal/secrets/store.go
func (s *Store) GetToken(email string) (Token, error) {
email = strings.ToLower(strings.TrimSpace(email))
if email == "" {
return Token{}, errMissingEmail
}
item, err := s.ring.Get(tokenKey(email))
if err != nil {
return Token{}, fmt.Errorf("read token: %w", err)
}
var st storedToken
if err := json.Unmarshal(item.Data, &st); err != nil {
return Token{}, fmt.Errorf("decode token: %w", err)
}
return Token{
Email: email,
Services: st.Services,
Scopes: st.Scopes,
CreatedAt: st.CreatedAt,
RefreshToken: st.RefreshToken,
}, nil
}secrets.Store.DeleteToken method · go · L233-L244 (12 LOC)internal/secrets/store.go
func (s *Store) DeleteToken(email string) error {
email = strings.ToLower(strings.TrimSpace(email))
if email == "" {
return errMissingEmail
}
if err := s.ring.Remove(tokenKey(email)); err != nil && !errors.Is(err, keyring.ErrKeyNotFound) {
return fmt.Errorf("delete token: %w", err)
}
return nil
}secrets.Store.ListTokens method · go · L247-L280 (34 LOC)internal/secrets/store.go
func (s *Store) ListTokens() ([]Token, error) {
keys, err := s.ring.Keys()
if err != nil {
return nil, fmt.Errorf("list keyring keys: %w", err)
}
out := make([]Token, 0)
seen := make(map[string]struct{})
for _, k := range keys {
if !strings.HasPrefix(k, "token:") {
continue
}
email := strings.TrimPrefix(k, "token:")
if email == "" {
continue
}
if _, ok := seen[email]; ok {
continue
}
tok, err := s.GetToken(email)
if err != nil {
continue
}
seen[email] = struct{}{}
out = append(out, tok)
}
return out, nil
}‹ prevpage 3 / 3