github.com/unclejack/drone@v0.2.1-0.20140918182345-831b034aa33b/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  // PublicHandler wraps the default http.HandlerFunc to include
    68  // requested Repository in the method signature, in addition
    69  // to handling an error as the return value.
    70  type PublicHandler func(w http.ResponseWriter, r *http.Request, repo *Repo) error
    71  
    72  func (h PublicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    73  	// repository name from the URL parameters
    74  	hostParam := r.FormValue(":host")
    75  	userParam := r.FormValue(":owner")
    76  	nameParam := r.FormValue(":name")
    77  	repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
    78  
    79  	repo, err := database.GetRepoSlug(repoName)
    80  	if err != nil || repo == nil {
    81  		RenderNotFound(w)
    82  		return
    83  	}
    84  
    85  	h(w, r, repo)
    86  	return
    87  }
    88  
    89  // RepoHandler wraps the default http.HandlerFunc to include
    90  // the currently authenticated User and requested Repository
    91  // in the method signature, in addition to handling an error
    92  // as the return value.
    93  
    94  type RepoHandler func(w http.ResponseWriter, r *http.Request, user *User, repo *Repo) error
    95  
    96  func (h RepoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    97  
    98  	// repository name from the URL parameters
    99  	hostParam := r.FormValue(":host")
   100  	userParam := r.FormValue(":owner")
   101  	nameParam := r.FormValue(":name")
   102  	repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
   103  
   104  	repo, err := database.GetRepoSlug(repoName)
   105  	if err != nil || repo == nil {
   106  		RenderNotFound(w)
   107  		return
   108  	}
   109  
   110  	// retrieve the user from the database
   111  	user, err := readUser(r)
   112  
   113  	// if the user is not found, we can still
   114  	// serve the page assuming the repository
   115  	// is public.
   116  	switch {
   117  	case err != nil && repo.Private == true:
   118  		redirectLogin(w, r)
   119  		return
   120  	case err != nil && repo.Private == false:
   121  		h(w, r, nil, repo)
   122  		return
   123  	}
   124  
   125  	// The User must own the repository OR be a member
   126  	// of the Team that owns the repository OR the repo
   127  	// must not be private.
   128  	if repo.Private && user.ID != repo.UserID {
   129  		if member, _ := database.IsMember(user.ID, repo.TeamID); !member {
   130  			RenderNotFound(w)
   131  			return
   132  		}
   133  	}
   134  
   135  	if err = h(w, r, user, repo); err != nil {
   136  		log.Print(err)
   137  		RenderError(w, err, http.StatusBadRequest)
   138  	}
   139  }
   140  
   141  // RepoHandler wraps the default http.HandlerFunc to include
   142  // the currently authenticated User and requested Repository
   143  // in the method signature, in addition to handling an error
   144  // as the return value.
   145  type RepoAdminHandler func(w http.ResponseWriter, r *http.Request, user *User, repo *Repo) error
   146  
   147  func (h RepoAdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   148  	user, err := readUser(r)
   149  	if err != nil {
   150  		redirectLogin(w, r)
   151  		return
   152  	}
   153  
   154  	// repository name from the URL parameters
   155  	hostParam := r.FormValue(":host")
   156  	userParam := r.FormValue(":owner")
   157  	nameParam := r.FormValue(":name")
   158  	repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
   159  
   160  	repo, err := database.GetRepoSlug(repoName)
   161  	if err != nil {
   162  		RenderNotFound(w)
   163  		return
   164  	}
   165  
   166  	// The User must own the repository OR be a member
   167  	// of the Team that owns the repository.
   168  	if admin, _ := database.IsRepoAdmin(user, repo); admin == false {
   169  		RenderNotFound(w)
   170  		return
   171  	}
   172  
   173  	if err = h(w, r, user, repo); err != nil {
   174  		log.Print(err)
   175  		RenderError(w, err, http.StatusBadRequest)
   176  	}
   177  }
   178  
   179  // helper function that reads the currently authenticated
   180  // user from the given http.Request.
   181  func readUser(r *http.Request) (*User, error) {
   182  	username := GetCookie(r, "_sess")
   183  	if len(username) == 0 {
   184  		return nil, fmt.Errorf("No user session")
   185  	}
   186  
   187  	// get the user from the database
   188  	user, err := database.GetUserEmail(username)
   189  	if err != nil || user == nil || user.ID == 0 {
   190  		return nil, err
   191  	}
   192  
   193  	return user, nil
   194  }
   195  
   196  // helper function that retrieves the repository based
   197  // on the URL parameters
   198  func readRepo(r *http.Request) (*Repo, error) {
   199  	// get the repo data from the URL parameters
   200  	hostParam := r.FormValue(":host")
   201  	userParam := r.FormValue(":owner")
   202  	nameParam := r.FormValue(":slug")
   203  	repoSlug := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam)
   204  
   205  	// get the repo from the database
   206  	return database.GetRepoSlug(repoSlug)
   207  }
   208  
   209  // helper function that sends the user to the login page.
   210  func redirectLogin(w http.ResponseWriter, r *http.Request) {
   211  	v := url.Values{}
   212  	v.Add("return_to", r.URL.String())
   213  	http.Redirect(w, r, "/login?"+v.Encode(), http.StatusSeeOther)
   214  }
   215  
   216  func renderNotFound(w http.ResponseWriter, r *http.Request) {
   217  	w.WriteHeader(http.StatusNotFound)
   218  	RenderTemplate(w, "404.amber", nil)
   219  }
   220  
   221  func renderBadRequest(w http.ResponseWriter, r *http.Request) {
   222  	w.WriteHeader(http.StatusBadRequest)
   223  	RenderTemplate(w, "500.amber", nil)
   224  }