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 }