// Copyright 2019 Drone IO, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package token import ( "context" "time" "github.com/drone/drone/core" "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/transport/oauth2" ) // expiryDelta determines how earlier a token should be considered // expired than its actual expiration time. It is used to avoid late // expirations due to client-server time mismatches. const expiryDelta = time.Minute type renewer struct { refresh *oauth2.Refresher users core.UserStore } // Renewer returns a new Renewer. func Renewer(refresh *oauth2.Refresher, store core.UserStore) core.Renewer { return &renewer{ refresh: refresh, users: store, } } func (r *renewer) Renew(ctx context.Context, user *core.User, force bool) error { if r.refresh == nil { return nil } t := &scm.Token{ Token: user.Token, Refresh: user.Refresh, Expires: time.Unix(user.Expiry, 0), } if expired(t) == false && force == false { return nil } err := r.refresh.Refresh(t) if err != nil { return err } user.Token = t.Token user.Refresh = t.Refresh user.Expiry = t.Expires.Unix() return r.users.Update(ctx, user) } // expired reports whether the token is expired. func expired(token *scm.Token) bool { if len(token.Refresh) == 0 { return false } if token.Expires.IsZero() && len(token.Token) != 0 { return false } return token.Expires.Add(-expiryDelta). Before(time.Now()) }