github.com/jonathaningram/gophish@v0.3.1-0.20170829042651-ac3fe6aeae6c/middleware/middleware.go (about)

     1  package middleware
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"strings"
     8  
     9  	"github.com/gophish/gophish/auth"
    10  	ctx "github.com/gophish/gophish/context"
    11  	"github.com/gophish/gophish/models"
    12  	"github.com/gorilla/csrf"
    13  )
    14  
    15  var CSRFExemptPrefixes = []string{
    16  	"/api",
    17  }
    18  
    19  func CSRFExceptions(handler http.Handler) http.HandlerFunc {
    20  	return func(w http.ResponseWriter, r *http.Request) {
    21  		for _, prefix := range CSRFExemptPrefixes {
    22  			if strings.HasPrefix(r.URL.Path, prefix) {
    23  				r = csrf.UnsafeSkipCheck(r)
    24  				break
    25  			}
    26  		}
    27  		handler.ServeHTTP(w, r)
    28  	}
    29  }
    30  
    31  // GetContext wraps each request in a function which fills in the context for a given request.
    32  // This includes setting the User and Session keys and values as necessary for use in later functions.
    33  func GetContext(handler http.Handler) http.HandlerFunc {
    34  	// Set the context here
    35  	return func(w http.ResponseWriter, r *http.Request) {
    36  		// Parse the request form
    37  		err := r.ParseForm()
    38  		if err != nil {
    39  			http.Error(w, "Error parsing request", http.StatusInternalServerError)
    40  		}
    41  		// Set the context appropriately here.
    42  		// Set the session
    43  		session, _ := auth.Store.Get(r, "gophish")
    44  		// Put the session in the context so that we can
    45  		// reuse the values in different handlers
    46  		r = ctx.Set(r, "session", session)
    47  		if id, ok := session.Values["id"]; ok {
    48  			u, err := models.GetUser(id.(int64))
    49  			if err != nil {
    50  				r = ctx.Set(r, "user", nil)
    51  			} else {
    52  				r = ctx.Set(r, "user", u)
    53  			}
    54  		} else {
    55  			r = ctx.Set(r, "user", nil)
    56  		}
    57  		handler.ServeHTTP(w, r)
    58  		// Remove context contents
    59  		ctx.Clear(r)
    60  	}
    61  }
    62  
    63  func RequireAPIKey(handler http.Handler) http.HandlerFunc {
    64  	return func(w http.ResponseWriter, r *http.Request) {
    65  		r.ParseForm()
    66  		ak := r.Form.Get("api_key")
    67  		w.Header().Set("Access-Control-Allow-Origin", "*")
    68  		if r.Method == "OPTIONS" {
    69  			w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
    70  			w.Header().Set("Access-Control-Max-Age", "1000")
    71  			w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
    72  			return
    73  		}
    74  		if ak == "" {
    75  			JSONError(w, 400, "API Key not set")
    76  			return
    77  		} else {
    78  			u, err := models.GetUserByAPIKey(ak)
    79  			if err != nil {
    80  				JSONError(w, 400, "Invalid API Key")
    81  				return
    82  			}
    83  			r = ctx.Set(r, "user_id", u.Id)
    84  			r = ctx.Set(r, "api_key", ak)
    85  			handler.ServeHTTP(w, r)
    86  		}
    87  	}
    88  }
    89  
    90  // RequireLogin is a simple middleware which checks to see if the user is currently logged in.
    91  // If not, the function returns a 302 redirect to the login page.
    92  func RequireLogin(handler http.Handler) http.HandlerFunc {
    93  	return func(w http.ResponseWriter, r *http.Request) {
    94  		if u := ctx.Get(r, "user"); u != nil {
    95  			handler.ServeHTTP(w, r)
    96  		} else {
    97  			http.Redirect(w, r, "/login", 302)
    98  		}
    99  	}
   100  }
   101  
   102  // JSONError returns an error in JSON format with the given
   103  // status code and message
   104  func JSONError(w http.ResponseWriter, c int, m string) {
   105  	cj, _ := json.MarshalIndent(models.Response{Success: false, Message: m}, "", "  ")
   106  	w.Header().Set("Content-Type", "application/json")
   107  	w.WriteHeader(c)
   108  	fmt.Fprintf(w, "%s", cj)
   109  }