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  }