github.com/kvattikuti/drone@v0.2.1-0.20140603034306-d400229a327a/pkg/handler/handler.go (about)

     1  package handler
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net/http"
     7  	"net/url"
     8  
     9  	"github.com/drone/drone/pkg/database"
    10  	. "github.com/drone/drone/pkg/model"
    11  )
    12  
    13  // ErrorHandler wraps the default http.HandleFunc to handle an
    14  // error as the return value.
    15  type ErrorHandler func(w http.ResponseWriter, r *http.Request) error
    16  
    17  func (h ErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    18  	if err := h(w, r); err != nil {
    19  		log.Print(err)
    20  	}
    21  }
    22  
    23  // UserHandler wraps the default http.HandlerFunc to include
    24  // the currently authenticated User in the method signature,
    25  // in addition to handling an error as the return value.
    26  type UserHandler func(w http.ResponseWriter, r *http.Request, user *User) error
    27  
    28  func (h UserHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    29  	user, err := readUser(r)
    30  	if err != nil {
    31  		redirectLogin(w, r)
    32  		return
    33  	}
    34  
    35  	if err = h(w, r, user); err != nil {
    36  		log.Print(err)
    37  		RenderError(w, err, http.StatusBadRequest)
    38  	}
    39  }
    40  
    41  // AdminHandler wraps the default http.HandlerFunc to include
    42  // the currently authenticated User in the method signature,
    43  // in addition to handling an error as the return value. It also
    44  // verifies the user has Administrative privileges.
    45  type AdminHandler func(w http.ResponseWriter, r *http.Request, user *User) error
    46  
    47  func (h AdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    48  	user, err := readUser(r)
    49  	if err != nil {
    50  		redirectLogin(w, r)
    51  		return
    52  	}
    53  
    54  	// User MUST have administrative privileges in order
    55  	// to execute the handler.
    56  	if user.Admin == false {
    57  		RenderNotFound(w)
    58  		return
    59  	}
    60  
    61  	if err = h(w, r, user); err != nil {
    62  		log.Print(err)
    63  		RenderError(w, err, http.StatusBadRequest)
    64  	}
    65  }
    66  
    67  // RepoHandler wraps the default http.HandlerFunc to include
    68  // the currently authenticated User and requested Repository
    69  // in the method signature, in addition to handling an error
    70  // as the return value.
    71  type RepoHandler func(w http.ResponseWriter, r *http.Request, user *User, repo *Repo) error
    72  
    73  func (h RepoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    74  
    75  	// repository name from the URL parameters
    76  	hostParam := r.FormValue(":host")
    77  	userParam := r.FormValue(":owner")
    78  	nameParam := r.FormValue(":name")
    79  	repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
    80  
    81  	repo, err := database.GetRepoSlug(repoName)
    82  	if err != nil || repo == nil {
    83  		RenderNotFound(w)
    84  		return
    85  	}
    86  
    87  	// retrieve the user from the database
    88  	user, err := readUser(r)
    89  
    90  	// if the user is not found, we can still
    91  	// serve the page assuming the repository
    92  	// is public.
    93  	switch {
    94  	case err != nil && repo.Private == true:
    95  		redirectLogin(w, r)
    96  		return
    97  	case err != nil && repo.Private == false:
    98  		h(w, r, nil, repo)
    99  		return
   100  	}
   101  
   102  	// The User must own the repository OR be a member
   103  	// of the Team that owns the repository OR the repo
   104  	// must not be private.
   105  	if repo.Private && user.ID != repo.UserID {
   106  		if member, _ := database.IsMember(user.ID, repo.TeamID); !member {
   107  			RenderNotFound(w)
   108  			return
   109  		}
   110  	}
   111  
   112  	if err = h(w, r, user, repo); err != nil {
   113  		log.Print(err)
   114  		RenderError(w, err, http.StatusBadRequest)
   115  	}
   116  }
   117  
   118  // RepoHandler wraps the default http.HandlerFunc to include
   119  // the currently authenticated User and requested Repository
   120  // in the method signature, in addition to handling an error
   121  // as the return value.
   122  type RepoAdminHandler func(w http.ResponseWriter, r *http.Request, user *User, repo *Repo) error
   123  
   124  func (h RepoAdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   125  	user, err := readUser(r)
   126  	if err != nil {
   127  		redirectLogin(w, r)
   128  		return
   129  	}
   130  
   131  	// repository name from the URL parameters
   132  	hostParam := r.FormValue(":host")
   133  	userParam := r.FormValue(":owner")
   134  	nameParam := r.FormValue(":name")
   135  	repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
   136  
   137  	repo, err := database.GetRepoSlug(repoName)
   138  	if err != nil {
   139  		RenderNotFound(w)
   140  		return
   141  	}
   142  
   143  	// The User must own the repository OR be a member
   144  	// of the Team that owns the repository.
   145  	if user.ID != repo.UserID {
   146  		if admin, _ := database.IsMemberAdmin(user.ID, repo.TeamID); admin == false {
   147  			RenderNotFound(w)
   148  			return
   149  		}
   150  	}
   151  
   152  	if err = h(w, r, user, repo); err != nil {
   153  		log.Print(err)
   154  		RenderError(w, err, http.StatusBadRequest)
   155  	}
   156  }
   157  
   158  // helper function that reads the currently authenticated
   159  // user from the given http.Request.
   160  func readUser(r *http.Request) (*User, error) {
   161  	username := GetCookie(r, "_sess")
   162  	if len(username) == 0 {
   163  		return nil, fmt.Errorf("No user session")
   164  	}
   165  
   166  	// get the user from the database
   167  	user, err := database.GetUserEmail(username)
   168  	if err != nil || user == nil || user.ID == 0 {
   169  		return nil, err
   170  	}
   171  
   172  	return user, nil
   173  }
   174  
   175  // helper function that retrieves the repository based
   176  // on the URL parameters
   177  func readRepo(r *http.Request) (*Repo, error) {
   178  	// get the repo data from the URL parameters
   179  	hostParam := r.FormValue(":host")
   180  	userParam := r.FormValue(":owner")
   181  	nameParam := r.FormValue(":slug")
   182  	repoSlug := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
   183  
   184  	// get the repo from the database
   185  	return database.GetRepoSlug(repoSlug)
   186  }
   187  
   188  // helper function that sends the user to the login page.
   189  func redirectLogin(w http.ResponseWriter, r *http.Request) {
   190  	v := url.Values{}
   191  	v.Add("return_to", r.URL.String())
   192  	http.Redirect(w, r, "/login?"+v.Encode(), http.StatusSeeOther)
   193  }
   194  
   195  func renderNotFound(w http.ResponseWriter, r *http.Request) {
   196  	w.WriteHeader(http.StatusNotFound)
   197  	RenderTemplate(w, "404.amber", nil)
   198  }
   199  
   200  func renderBadRequest(w http.ResponseWriter, r *http.Request) {
   201  	w.WriteHeader(http.StatusBadRequest)
   202  	RenderTemplate(w, "500.amber", nil)
   203  }