github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/registry/regserver/handlers/protector.go (about)

     1  package handlers
     2  
     3  import (
     4  	"errors"
     5  	"net/http"
     6  
     7  	apiutil "github.com/qri-io/qri/api/util"
     8  )
     9  
    10  // MethodProtector is an interface for controling access to http.HandlerFunc's
    11  // according to request method (GET, PUT, POST, etc.)
    12  type MethodProtector interface {
    13  	// ProtectMethods should accept a list of http request methods and return a function that
    14  	// generates middleware to screen for authorization on those methods.
    15  	//
    16  	// For example if "reqHandler" is an http.HandlerFunc, the following would check for
    17  	// authentication on all POST requests:
    18  	//  Protector.ProtectMethods("POST")(reqHandler)
    19  	ProtectMethods(methods ...string) func(h http.HandlerFunc) http.HandlerFunc
    20  }
    21  
    22  // BAProtector implements HTTP Basic Auth checking as a protector
    23  type BAProtector struct {
    24  	username, password string
    25  }
    26  
    27  // NewBAProtector creates a HTTP basic auth protector from a username/password combo
    28  func NewBAProtector(username, password string) BAProtector {
    29  	return BAProtector{username, password}
    30  }
    31  
    32  // ProtectMethods implements the MethodProtector interface
    33  func (ba BAProtector) ProtectMethods(methods ...string) func(http.HandlerFunc) http.HandlerFunc {
    34  	return func(h http.HandlerFunc) http.HandlerFunc {
    35  		return func(w http.ResponseWriter, r *http.Request) {
    36  			for _, m := range methods {
    37  				if r.Method == m || m == "*" {
    38  					username, password, set := r.BasicAuth()
    39  					if !set || username != ba.username || password != ba.password {
    40  						log.Infof("invalid key")
    41  						apiutil.WriteErrResponse(w, http.StatusForbidden, errors.New("invalid key"))
    42  						return
    43  					}
    44  				}
    45  			}
    46  
    47  			h.ServeHTTP(w, r)
    48  		}
    49  	}
    50  }
    51  
    52  // NoopProtector implements the MethodProtector without doing any checks
    53  type NoopProtector uint8
    54  
    55  // NewNoopProtector creates a NoopProtector
    56  func NewNoopProtector() NoopProtector {
    57  	return NoopProtector(0)
    58  }
    59  
    60  // ProtectMethods implements the MethodProtector interface
    61  func (NoopProtector) ProtectMethods(methods ...string) func(http.HandlerFunc) http.HandlerFunc {
    62  	return func(h http.HandlerFunc) http.HandlerFunc {
    63  		return func(w http.ResponseWriter, r *http.Request) {
    64  			h.ServeHTTP(w, r)
    65  		}
    66  	}
    67  }