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 }