github.com/marinho/drone@v0.2.1-0.20140504195434-d3ba962e89a7/pkg/handler/repos.go (about) 1 package handler 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "github.com/drone/drone/pkg/channel" 8 "github.com/drone/drone/pkg/database" 9 . "github.com/drone/drone/pkg/model" 10 "github.com/drone/go-bitbucket/bitbucket" 11 "github.com/drone/go-github/github" 12 13 "launchpad.net/goyaml" 14 ) 15 16 // Display a Repository dashboard. 17 func RepoDashboard(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 18 branch := r.FormValue("branch") 19 20 // get a list of all branches 21 branches, err := database.ListBranches(repo.ID) 22 if err != nil { 23 return err 24 } 25 26 // if no branch is provided then we'll 27 // want to use a default value. 28 if len(branch) == 0 { 29 branch = repo.DefaultBranch() 30 } 31 32 // get a list of recent commits for the 33 // repository and specific branch 34 commits, err := database.ListCommits(repo.ID, branch) 35 if err != nil { 36 return err 37 } 38 39 // get a token that can be exchanged with the 40 // websocket handler to authorize listening 41 // for a stream of changes for this repository 42 token := channel.Create(repo.Slug) 43 44 data := struct { 45 User *User 46 Repo *Repo 47 Branches []*Commit 48 Commits []*Commit 49 Branch string 50 Token string 51 }{u, repo, branches, commits, branch, token} 52 53 return RenderTemplate(w, "repo_dashboard.html", &data) 54 } 55 56 func RepoAddGithub(w http.ResponseWriter, r *http.Request, u *User) error { 57 settings := database.SettingsMust() 58 teams, err := database.ListTeams(u.ID) 59 if err != nil { 60 return err 61 } 62 data := struct { 63 User *User 64 Teams []*Team 65 Settings *Settings 66 }{u, teams, settings} 67 // if the user hasn't linked their GitHub account 68 // render a different template 69 if len(u.GithubToken) == 0 { 70 return RenderTemplate(w, "github_link.html", &data) 71 } 72 // otherwise display the template for adding 73 // a new GitHub repository. 74 return RenderTemplate(w, "github_add.html", &data) 75 } 76 77 func RepoAddBitbucket(w http.ResponseWriter, r *http.Request, u *User) error { 78 settings := database.SettingsMust() 79 teams, err := database.ListTeams(u.ID) 80 if err != nil { 81 return err 82 } 83 data := struct { 84 User *User 85 Teams []*Team 86 Settings *Settings 87 }{u, teams, settings} 88 // if the user hasn't linked their Bitbucket account 89 // render a different template 90 if len(u.BitbucketToken) == 0 { 91 return RenderTemplate(w, "bitbucket_link.html", &data) 92 } 93 // otherwise display the template for adding 94 // a new Bitbucket repository. 95 return RenderTemplate(w, "bitbucket_add.html", &data) 96 } 97 98 func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error { 99 teamName := r.FormValue("team") 100 owner := r.FormValue("owner") 101 name := r.FormValue("name") 102 103 // get the github settings from the database 104 settings := database.SettingsMust() 105 106 // create the GitHub client 107 client := github.New(u.GithubToken) 108 client.ApiUrl = settings.GitHubApiUrl 109 githubRepo, err := client.Repos.Find(owner, name) 110 if err != nil { 111 return fmt.Errorf("Unable to find GitHub repository %s/%s.", owner, name) 112 } 113 114 repo, err := NewGitHubRepo(settings.GitHubDomain, owner, name, githubRepo.Private) 115 if err != nil { 116 return err 117 } 118 119 repo.UserID = u.ID 120 repo.Private = githubRepo.Private 121 122 // if the user chose to assign to a team account 123 // we need to retrieve the team, verify the user 124 // has access, and then set the team id. 125 if len(teamName) > 0 { 126 team, err := database.GetTeamSlug(teamName) 127 if err != nil { 128 return fmt.Errorf("Unable to find Team %s.", teamName) 129 } 130 131 // user must be an admin member of the team 132 if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok { 133 return fmt.Errorf("Invalid permission to access Team %s.", teamName) 134 } 135 136 repo.TeamID = team.ID 137 } 138 139 // if the repository is private we'll need 140 // to upload a github key to the repository 141 if repo.Private { 142 // name the key 143 keyName := fmt.Sprintf("%s@%s", repo.Owner, settings.Domain) 144 145 // create the github key, or update if one already exists 146 _, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName) 147 if err != nil { 148 return fmt.Errorf("Unable to add Public Key to your GitHub repository.") 149 } 150 } else { 151 152 } 153 154 // create a hook so that we get notified when code 155 // is pushed to the repository and can execute a build. 156 link := fmt.Sprintf("%s://%s/hook/github.com?id=%s", settings.Scheme, settings.Domain, repo.Slug) 157 158 // add the hook 159 if _, err := client.Hooks.CreateUpdate(owner, name, link); err != nil { 160 return fmt.Errorf("Unable to add Hook to your GitHub repository.") 161 } 162 163 // Save to the database 164 if err := database.SaveRepo(repo); err != nil { 165 return fmt.Errorf("Error saving repository to the database. %s", err) 166 } 167 168 return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) 169 } 170 171 func RepoCreateBitbucket(w http.ResponseWriter, r *http.Request, u *User) error { 172 teamName := r.FormValue("team") 173 owner := r.FormValue("owner") 174 name := r.FormValue("name") 175 176 // get the bitbucket settings from the database 177 settings := database.SettingsMust() 178 179 // create the Bitbucket client 180 client := bitbucket.New( 181 settings.BitbucketKey, 182 settings.BitbucketSecret, 183 u.BitbucketToken, 184 u.BitbucketSecret, 185 ) 186 187 bitbucketRepo, err := client.Repos.Find(owner, name) 188 if err != nil { 189 return fmt.Errorf("Unable to find Bitbucket repository %s/%s.", owner, name) 190 } 191 192 repo, err := NewBitbucketRepo(owner, name, bitbucketRepo.Private) 193 if err != nil { 194 return err 195 } 196 197 repo.UserID = u.ID 198 repo.Private = bitbucketRepo.Private 199 200 // if the user chose to assign to a team account 201 // we need to retrieve the team, verify the user 202 // has access, and then set the team id. 203 if len(teamName) > 0 { 204 team, err := database.GetTeamSlug(teamName) 205 if err != nil { 206 return fmt.Errorf("Unable to find Team %s.", teamName) 207 } 208 209 // user must be an admin member of the team 210 if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok { 211 return fmt.Errorf("Invalid permission to access Team %s.", teamName) 212 } 213 214 repo.TeamID = team.ID 215 } 216 217 // if the repository is private we'll need 218 // to upload a bitbucket key to the repository 219 if repo.Private { 220 // name the key 221 keyName := fmt.Sprintf("%s@%s", repo.Owner, settings.Domain) 222 223 // create the bitbucket key, or update if one already exists 224 _, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName) 225 if err != nil { 226 return fmt.Errorf("Unable to add Public Key to your Bitbucket repository: %s", err) 227 } 228 } else { 229 230 } 231 232 // create a hook so that we get notified when code 233 // is pushed to the repository and can execute a build. 234 link := fmt.Sprintf("%s://%s/hook/bitbucket.org?id=%s", settings.Scheme, settings.Domain, repo.Slug) 235 236 // add the hook 237 if _, err := client.Brokers.CreateUpdate(owner, name, link, bitbucket.BrokerTypePost); err != nil { 238 return fmt.Errorf("Unable to add Hook to your Bitbucket repository. %s", err.Error()) 239 } 240 241 // Save to the database 242 if err := database.SaveRepo(repo); err != nil { 243 return fmt.Errorf("Error saving repository to the database. %s", err) 244 } 245 246 return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) 247 } 248 249 // Repository Settings 250 func RepoSettingsForm(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 251 252 // get the list of teams 253 teams, err := database.ListTeams(u.ID) 254 if err != nil { 255 return err 256 } 257 258 data := struct { 259 Repo *Repo 260 User *User 261 Teams []*Team 262 Owner *User 263 Team *Team 264 }{Repo: repo, User: u, Teams: teams} 265 266 // get the repo owner 267 if repo.TeamID > 0 { 268 data.Team, err = database.GetTeam(repo.TeamID) 269 if err != nil { 270 return err 271 } 272 } 273 274 // get the team owner 275 data.Owner, err = database.GetUser(repo.UserID) 276 if err != nil { 277 return err 278 } 279 280 return RenderTemplate(w, "repo_settings.html", &data) 281 } 282 283 // Repository Params (YAML parameters) Form 284 func RepoParamsForm(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 285 286 data := struct { 287 Repo *Repo 288 User *User 289 Textarea string 290 }{repo, u, ""} 291 292 if repo.Params != nil && len(repo.Params) != 0 { 293 raw, _ := goyaml.Marshal(&repo.Params) 294 data.Textarea = string(raw) 295 } 296 297 return RenderTemplate(w, "repo_params.html", &data) 298 } 299 300 func RepoBadges(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 301 // hostname from settings 302 hostname := database.SettingsMust().URL().String() 303 304 data := struct { 305 Repo *Repo 306 User *User 307 Host string 308 }{repo, u, hostname} 309 return RenderTemplate(w, "repo_badges.html", &data) 310 } 311 312 func RepoKeys(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 313 data := struct { 314 Repo *Repo 315 User *User 316 }{repo, u} 317 return RenderTemplate(w, "repo_keys.html", &data) 318 } 319 320 // Updates an existing repository. 321 func RepoUpdate(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 322 switch r.FormValue("action") { 323 case "params": 324 repo.Params = map[string]string{} 325 if err := goyaml.Unmarshal([]byte(r.FormValue("params")), &repo.Params); err != nil { 326 return err 327 } 328 default: 329 repo.Disabled = len(r.FormValue("Disabled")) == 0 330 repo.DisabledPullRequest = len(r.FormValue("DisabledPullRequest")) == 0 331 repo.Private = len(r.FormValue("Private")) > 0 332 repo.Privileged = u.Admin && len(r.FormValue("Privileged")) > 0 333 334 // value of "" indicates the currently authenticated user 335 // should be set as the administrator. 336 if len(r.FormValue("Owner")) == 0 { 337 repo.UserID = u.ID 338 repo.TeamID = 0 339 } else { 340 // else the user has chosen a team 341 team, err := database.GetTeamSlug(r.FormValue("Owner")) 342 if err != nil { 343 return err 344 } 345 346 // verify the user is a member of the team 347 if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { 348 return fmt.Errorf("Forbidden") 349 } 350 351 // set the team ID 352 repo.TeamID = team.ID 353 } 354 } 355 356 // save the page 357 if err := database.SaveRepo(repo); err != nil { 358 return err 359 } 360 361 http.Redirect(w, r, r.URL.Path, http.StatusSeeOther) 362 return nil 363 } 364 365 // Deletes a specific repository. 366 func RepoDeleteForm(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 367 data := struct { 368 Repo *Repo 369 User *User 370 }{repo, u} 371 return RenderTemplate(w, "repo_delete.html", &data) 372 } 373 374 // Deletes a specific repository. 375 func RepoDelete(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { 376 // the user must confirm their password before deleting 377 password := r.FormValue("password") 378 if err := u.ComparePassword(password); err != nil { 379 return RenderError(w, err, http.StatusBadRequest) 380 } 381 382 // delete the repo 383 if err := database.DeleteRepo(repo.ID); err != nil { 384 return err 385 } 386 387 http.Redirect(w, r, "/dashboard", http.StatusSeeOther) 388 return nil 389 }