func TestIsMemberAdmin(t *testing.T) { Setup() defer Teardown() // expecting user is Owner if ok, err := database.IsMemberAdmin(1, 1); err != nil { t.Error(err) } else if !ok { t.Errorf("Expected IsMemberAdmin to return true, returned false") } // expecting user is Admin if ok, err := database.IsMemberAdmin(2, 1); err != nil { t.Error(err) } else if !ok { t.Errorf("Expected IsMemberAdmin to return true, returned false") } // expecting user is NOT Admin (Write role) if ok, err := database.IsMemberAdmin(3, 1); err != nil { t.Error(err) } else if ok { t.Errorf("Expected IsMemberAdmin to return false, returned true") } }
func (h RepoAdminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { user, err := readUser(r) if err != nil { redirectLogin(w, r) return } // repository name from the URL parameters hostParam := r.FormValue(":host") userParam := r.FormValue(":owner") nameParam := r.FormValue(":name") repoName := fmt.Sprintf("%s/%s/%s", hostParam, userParam, nameParam) repo, err := database.GetRepoSlug(repoName) if err != nil { RenderNotFound(w) return } // The User must own the repository OR be a member // of the Team that owns the repository. if user.ID != repo.UserID { if admin, _ := database.IsMemberAdmin(user.ID, repo.TeamID); admin == false { RenderNotFound(w) return } } if err = h(w, r, user, repo); err != nil { log.Print(err) RenderError(w, err, http.StatusBadRequest) } }
func (g *GitlabHandler) Create(w http.ResponseWriter, r *http.Request, u *User) error { teamName := r.FormValue("team") owner := r.FormValue("owner") name := r.FormValue("name") repo, err := g.newGitlabRepo(u, owner, name) if err != nil { return err } if len(teamName) > 0 { team, err := database.GetTeamSlug(teamName) if err != nil { return fmt.Errorf("Unable to find Team %s.", teamName) } // user must be an admin member of the team if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok { return fmt.Errorf("Invalid permission to access Team %s.", teamName) } repo.TeamID = team.ID } // Save to the database if err := database.SaveRepo(repo); err != nil { return fmt.Errorf("Error saving repository to the database. %s", err) } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
// Update a specific Team Member. func TeamMemberUpdate(w http.ResponseWriter, r *http.Request, u *User) error { roleParam := r.FormValue("Role") teamParam := r.FormValue(":team") // get the team from the database team, err := database.GetTeamSlug(teamParam) if err != nil { return RenderError(w, err, http.StatusNotFound) } // verify the user is a admin member of the team if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } // get the ID from the URL parameter idstr := r.FormValue("id") id, err := strconv.Atoi(idstr) if err != nil { return err } // get the user from the database user, err := database.GetUser(int64(id)) if err != nil { return RenderError(w, err, http.StatusNotFound) } // add the user to the team if err := database.SaveMember(user.ID, team.ID, roleParam); err != nil { return RenderError(w, err, http.StatusInternalServerError) } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
// Return an HTML form for editing a Team Member. func TeamMemberEdit(w http.ResponseWriter, r *http.Request, u *User) error { teamParam := r.FormValue(":team") team, err := database.GetTeamSlug(teamParam) if err != nil { return err } if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } // get the ID from the URL parameter idstr := r.FormValue("id") id, err := strconv.Atoi(idstr) if err != nil { return err } user, err := database.GetUser(int64(id)) if err != nil { return err } member, err := database.GetMember(user.ID, team.ID) if err != nil { return err } data := struct { User *User Team *Team Member *Member }{u, team, member} return RenderTemplate(w, "members_edit.html", &data) }
// Return an HTML form for editing a Team. func TeamEdit(w http.ResponseWriter, r *http.Request, u *User) error { teamParam := r.FormValue(":team") team, err := database.GetTeamSlug(teamParam) if err != nil { return err } if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } data := struct { User *User Team *Team }{u, team} return RenderTemplate(w, "team_profile.html", &data) }
// Updates an existing repository. func RepoUpdate(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) error { switch r.FormValue("action") { case "params": repo.Params = map[string]string{} if err := goyaml.Unmarshal([]byte(r.FormValue("params")), &repo.Params); err != nil { return err } default: repo.URL = r.FormValue("URL") repo.Disabled = len(r.FormValue("Disabled")) == 0 repo.DisabledPullRequest = len(r.FormValue("DisabledPullRequest")) == 0 repo.Private = len(r.FormValue("Private")) > 0 repo.Privileged = u.Admin && len(r.FormValue("Privileged")) > 0 // value of "" indicates the currently authenticated user // should be set as the administrator. if len(r.FormValue("Owner")) == 0 { repo.UserID = u.ID repo.TeamID = 0 } else { // else the user has chosen a team team, err := database.GetTeamSlug(r.FormValue("Owner")) if err != nil { return err } // verify the user is a member of the team if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } // set the team ID repo.TeamID = team.ID } } // save the page if err := database.SaveRepo(repo); err != nil { return err } http.Redirect(w, r, r.URL.Path, http.StatusSeeOther) return nil }
// Delete a specific Team. func TeamDelete(w http.ResponseWriter, r *http.Request, u *User) error { // get the team from the database teamParam := r.FormValue(":team") team, err := database.GetTeamSlug(teamParam) if err != nil { return RenderNotFound(w) } if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } // the user must confirm their password before deleting password := r.FormValue("password") if err := u.ComparePassword(password); err != nil { return RenderError(w, err, http.StatusBadRequest) } database.DeleteTeam(team.ID) http.Redirect(w, r, "/account/user/teams", http.StatusSeeOther) return nil }
// Display a list of Team Members. func TeamMembers(w http.ResponseWriter, r *http.Request, u *User) error { teamParam := r.FormValue(":team") team, err := database.GetTeamSlug(teamParam) if err != nil { return err } // user must be a team member admin if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } members, err := database.ListMembers(team.ID) if err != nil { return err } data := struct { User *User Team *Team Members []*Member }{u, team, members} return RenderTemplate(w, "team_members.html", &data) }
// Update a specific Team. func TeamUpdate(w http.ResponseWriter, r *http.Request, u *User) error { // get team from the database teamName := r.FormValue(":team") team, err := database.GetTeamSlug(teamName) if err != nil { return fmt.Errorf("Forbidden") } if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } team.Name = r.FormValue("name") team.SetEmail(r.FormValue("email")) if err := team.Validate(); err != nil { return RenderError(w, err, http.StatusBadRequest) } if err := database.SaveTeam(team); err != nil { return RenderError(w, err, http.StatusBadRequest) } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
// Invite a new Team Member. func TeamMemberInvite(w http.ResponseWriter, r *http.Request, u *User) error { teamParam := r.FormValue(":team") mailParam := r.FormValue("email") team, err := database.GetTeamSlug(teamParam) if err != nil { return RenderError(w, err, http.StatusNotFound) } if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } // generate a token that is valid for 3 days to join the team token := authcookie.New(strconv.Itoa(int(team.ID)), time.Now().Add(72*time.Hour), secret) // hostname from settings hostname := database.SettingsMust().URL().String() emailEnabled := database.SettingsMust().SmtpServer != "" if !emailEnabled { // Email is not enabled, so must let the user know the signup link link := fmt.Sprintf("%v/accept?token=%v", hostname, token) return RenderText(w, link, http.StatusOK) } // send the invitation data := struct { User *User Team *Team Token string Host string }{u, team, token, hostname} // send email async go mail.SendInvitation(team.Name, mailParam, &data) return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
// Delete a specific Team Member. func TeamMemberDelete(w http.ResponseWriter, r *http.Request, u *User) error { // get the team from the database teamParam := r.FormValue(":team") team, err := database.GetTeamSlug(teamParam) if err != nil { return RenderNotFound(w) } if member, _ := database.IsMemberAdmin(u.ID, team.ID); !member { return fmt.Errorf("Forbidden") } // get the ID from the URL parameter idstr := r.FormValue("id") id, err := strconv.Atoi(idstr) if err != nil { return err } // get the user from the database user, err := database.GetUser(int64(id)) if err != nil { return RenderNotFound(w) } // must be at least 1 member members, err := database.ListMembers(team.ID) if err != nil { return err } else if len(members) == 1 { return fmt.Errorf("There must be at least 1 member per team") } // delete the member database.DeleteMember(user.ID, team.ID) http.Redirect(w, r, fmt.Sprintf("/account/team/%s/members", team.Name), http.StatusSeeOther) return nil }
func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error { teamName := r.FormValue("team") owner := r.FormValue("owner") name := r.FormValue("name") // get the github settings from the database settings := database.SettingsMust() // create the GitHub client client := github.New(u.GithubToken) githubRepo, err := client.Repos.Find(owner, name) if err != nil { return err } repo, err := NewGitHubRepo(owner, name, githubRepo.Private) if err != nil { return err } repo.UserID = u.ID repo.Private = githubRepo.Private // if the user chose to assign to a team account // we need to retrieve the team, verify the user // has access, and then set the team id. if len(teamName) > 0 { team, err := database.GetTeamSlug(teamName) if err != nil { log.Printf("error retrieving team %s", teamName) return err } // user must be an admin member of the team if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok { return fmt.Errorf("Forbidden") } repo.TeamID = team.ID } // if the repository is private we'll need // to upload a github key to the repository if repo.Private { // name the key keyName := fmt.Sprintf("%s@%s", repo.Owner, settings.Domain) // create the github key, or update if one already exists _, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName) if err != nil { return fmt.Errorf("Unable to add Private Key to your GitHub repository") } } else { } // create a hook so that we get notified when code // is pushed to the repository and can execute a build. link := fmt.Sprintf("%s://%s/hook/github.com?id=%s", settings.Scheme, settings.Domain, repo.Slug) // add the hook if _, err := client.Hooks.CreateUpdate(owner, name, link); err != nil { return fmt.Errorf("Unable to add Hook to your GitHub repository. %s", err.Error()) } // Save to the database if err := database.SaveRepo(repo); err != nil { log.Print("error saving new repository to the database") return err } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
func RepoCreateBitbucket(w http.ResponseWriter, r *http.Request, u *User) error { teamName := r.FormValue("team") owner := r.FormValue("owner") name := r.FormValue("name") // get the bitbucket settings from the database settings := database.SettingsMust() // create the Bitbucket client client := bitbucket.New( settings.BitbucketKey, settings.BitbucketSecret, u.BitbucketToken, u.BitbucketSecret, ) bitbucketRepo, err := client.Repos.Find(owner, name) if err != nil { return fmt.Errorf("Unable to find Bitbucket repository %s/%s.", owner, name) } repo, err := NewBitbucketRepo(owner, name, bitbucketRepo.Private) if err != nil { return err } repo.UserID = u.ID repo.Private = bitbucketRepo.Private // if the user chose to assign to a team account // we need to retrieve the team, verify the user // has access, and then set the team id. if len(teamName) > 0 { team, err := database.GetTeamSlug(teamName) if err != nil { return fmt.Errorf("Unable to find Team %s.", teamName) } // user must be an admin member of the team if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok { return fmt.Errorf("Invalid permission to access Team %s.", teamName) } repo.TeamID = team.ID } // if the repository is private we'll need // to upload a bitbucket key to the repository if repo.Private { // name the key keyName := fmt.Sprintf("%s@%s", repo.Owner, settings.Domain) // create the bitbucket key, or update if one already exists _, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName) if err != nil { return fmt.Errorf("Unable to add Public Key to your Bitbucket repository: %s", err) } } else { } // create a hook so that we get notified when code // is pushed to the repository and can execute a build. link := fmt.Sprintf("%s://%s/hook/bitbucket.org?id=%s", settings.Scheme, settings.Domain, repo.Slug) // add the hook if _, err := client.Brokers.CreateUpdate(owner, name, link, bitbucket.BrokerTypePost); err != nil { return fmt.Errorf("Unable to add Hook to your Bitbucket repository. %s", err.Error()) } // Save to the database if err := database.SaveRepo(repo); err != nil { return fmt.Errorf("Error saving repository to the database. %s", err) } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }
func RepoCreateGithubLimited(w http.ResponseWriter, r *http.Request, u *User) error { teamName := r.FormValue("team") owner := r.FormValue("owner") name := r.FormValue("name") readToken := r.FormValue("read-token") writeToken := r.FormValue("write-token") u.GithubToken = readToken u.GithubWriteToken = writeToken // get the github settings from the database settings := database.SettingsMust() fmt.Printf("got settings: %s\n", settings) // create the GitHub client rClient := github.New(readToken) wClient := github.New(writeToken) rClient.ApiUrl = settings.GitHubApiUrl wClient.ApiUrl = settings.GitHubApiUrl githubRepo, err := rClient.Repos.Find(owner, name) if err != nil { fmt.Printf("err1, %s\n", err) return err } repo, err := NewGitHubRepo(settings.GitHubDomain, owner, name, githubRepo.Private) if err != nil { fmt.Printf("err2, %s\n", err) return err } repo.URL = fmt.Sprintf("https://%s@%s/%s/%s", readToken, settings.GitHubDomain, owner, name) repo.UserID = u.ID repo.Private = githubRepo.Private // if the user chose to assign to a team account // we need to retrieve the team, verify the user // has access, and then set the team id. if len(teamName) > 0 { team, err := database.GetTeamSlug(teamName) if err != nil { return fmt.Errorf("Unable to find Team %s.", teamName) } // user must be an admin member of the team if ok, _ := database.IsMemberAdmin(u.ID, team.ID); !ok { return fmt.Errorf("Invalid permission to access Team %s.", teamName) } repo.TeamID = team.ID } // create a hook so that we get notified when code // is pushed to the repository and can execute a build. link := fmt.Sprintf("%s://%s/hook/github.com?id=%s", settings.Scheme, settings.Domain, repo.Slug) // add the hook if _, err := wClient.Hooks.CreateUpdate(owner, name, link); err != nil { return fmt.Errorf("Unable to add Hook to your GitHub repository. %s", err.Error()) } // Save to the database if err := database.SaveRepo(repo); err != nil { return fmt.Errorf("Error saving repository to the database. %s", err) } // Save user to the database if err := database.SaveUser(u); err != nil { return fmt.Errorf("Error saving user to the database. %s", err) } return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) }