70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
|
package channel
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"net/http"
|
||
|
"time"
|
||
|
|
||
|
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
|
||
|
)
|
||
|
|
||
|
type AuthCheckerFunc func() *api.ChannelSettings
|
||
|
|
||
|
// Regularly checks that authorization is still valid for a channel, outputting
|
||
|
// to the stopper when it isn't
|
||
|
type AuthChecker struct {
|
||
|
Checker AuthCheckerFunc
|
||
|
Template *api.ChannelSettings
|
||
|
StopCh chan error
|
||
|
Done chan struct{}
|
||
|
Count int64
|
||
|
}
|
||
|
|
||
|
var ErrAuthChanged = errors.New("connection closed: authentication changed or endpoint unavailable")
|
||
|
|
||
|
func NewAuthChecker(f AuthCheckerFunc, template *api.ChannelSettings, stopCh chan error) *AuthChecker {
|
||
|
return &AuthChecker{
|
||
|
Checker: f,
|
||
|
Template: template,
|
||
|
StopCh: stopCh,
|
||
|
Done: make(chan struct{}),
|
||
|
}
|
||
|
}
|
||
|
func (c *AuthChecker) Loop(interval time.Duration) {
|
||
|
for {
|
||
|
select {
|
||
|
case <-time.After(interval):
|
||
|
settings := c.Checker()
|
||
|
if !c.Template.IsEqual(settings) {
|
||
|
c.StopCh <- ErrAuthChanged
|
||
|
return
|
||
|
}
|
||
|
c.Count = c.Count + 1
|
||
|
case <-c.Done:
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *AuthChecker) Close() error {
|
||
|
close(c.Done)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Generates a CheckerFunc from an *api.API + request needing authorization
|
||
|
func authCheckFunc(myAPI *api.API, r *http.Request, suffix string) AuthCheckerFunc {
|
||
|
return func() *api.ChannelSettings {
|
||
|
httpResponse, authResponse, err := myAPI.PreAuthorize(suffix, r)
|
||
|
if err != nil {
|
||
|
return nil
|
||
|
}
|
||
|
defer httpResponse.Body.Close()
|
||
|
|
||
|
if httpResponse.StatusCode != http.StatusOK || authResponse == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return authResponse.Channel
|
||
|
}
|
||
|
}
|