2017-09-14 11:16:22 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"fmt"
"strings"
2019-09-18 08:39:45 +03:00
"time"
2017-09-14 11:16:22 +03:00
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
2019-03-27 12:33:00 +03:00
"code.gitea.io/gitea/modules/git"
2017-09-14 11:16:22 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
// ProtectedBranch render the page to protect the repository
func ProtectedBranch ( ctx * context . Context ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings" )
ctx . Data [ "PageIsSettingsBranches" ] = true
protectedBranches , err := ctx . Repo . Repository . GetProtectedBranches ( )
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetProtectedBranches" , err )
2017-09-14 11:16:22 +03:00
return
}
ctx . Data [ "ProtectedBranches" ] = protectedBranches
branches := ctx . Data [ "Branches" ] . ( [ ] string )
leftBranches := make ( [ ] string , 0 , len ( branches ) - len ( protectedBranches ) )
for _ , b := range branches {
var protected bool
for _ , pb := range protectedBranches {
if b == pb . BranchName {
protected = true
break
}
}
if ! protected {
leftBranches = append ( leftBranches , b )
}
}
ctx . Data [ "LeftBranches" ] = leftBranches
ctx . HTML ( 200 , tplBranches )
}
// ProtectedBranchPost response for protect for a branch of a repository
func ProtectedBranchPost ( ctx * context . Context ) {
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings" )
ctx . Data [ "PageIsSettingsBranches" ] = true
repo := ctx . Repo . Repository
switch ctx . Query ( "action" ) {
case "default_branch" :
if ctx . HasError ( ) {
ctx . HTML ( 200 , tplBranches )
return
}
branch := ctx . Query ( "branch" )
if ! ctx . Repo . GitRepo . IsBranchExist ( branch ) {
ctx . Status ( 404 )
return
} else if repo . DefaultBranch != branch {
repo . DefaultBranch = branch
if err := ctx . Repo . GitRepo . SetDefaultBranch ( branch ) ; err != nil {
if ! git . IsErrUnsupportedVersion ( err ) {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "SetDefaultBranch" , err )
2017-09-14 11:16:22 +03:00
return
}
}
if err := repo . UpdateDefaultBranch ( ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "SetDefaultBranch" , err )
2017-09-14 11:16:22 +03:00
return
}
}
log . Trace ( "Repository basic settings updated: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( setting . AppSubURL + ctx . Req . URL . Path )
default :
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "" , nil )
2017-09-14 11:16:22 +03:00
}
}
// SettingsProtectedBranch renders the protected branch setting page
func SettingsProtectedBranch ( c * context . Context ) {
branch := c . Params ( "*" )
if ! c . Repo . GitRepo . IsBranchExist ( branch ) {
2018-01-11 00:34:17 +03:00
c . NotFound ( "IsBranchExist" , nil )
2017-09-14 11:16:22 +03:00
return
}
2018-03-21 21:12:49 +03:00
c . Data [ "Title" ] = c . Tr ( "repo.settings.protected_branch" ) + " - " + branch
2017-09-14 11:16:22 +03:00
c . Data [ "PageIsSettingsBranches" ] = true
protectBranch , err := models . GetProtectedBranchBy ( c . Repo . Repository . ID , branch )
if err != nil {
2019-04-19 15:17:27 +03:00
if ! git . IsErrBranchNotExist ( err ) {
2018-01-11 00:34:17 +03:00
c . ServerError ( "GetProtectBranchOfRepoByName" , err )
2017-09-14 11:16:22 +03:00
return
}
}
if protectBranch == nil {
// No options found, create defaults.
protectBranch = & models . ProtectedBranch {
BranchName : branch ,
}
}
2019-10-08 22:18:17 +03:00
users , err := c . Repo . Repository . GetReaders ( )
2017-09-14 11:16:22 +03:00
if err != nil {
2019-10-08 22:18:17 +03:00
c . ServerError ( "Repo.Repository.GetReaders" , err )
2017-09-14 11:16:22 +03:00
return
}
c . Data [ "Users" ] = users
c . Data [ "whitelist_users" ] = strings . Join ( base . Int64sToStrings ( protectBranch . WhitelistUserIDs ) , "," )
2018-03-25 13:01:32 +03:00
c . Data [ "merge_whitelist_users" ] = strings . Join ( base . Int64sToStrings ( protectBranch . MergeWhitelistUserIDs ) , "," )
2018-12-11 14:28:37 +03:00
c . Data [ "approvals_whitelist_users" ] = strings . Join ( base . Int64sToStrings ( protectBranch . ApprovalsWhitelistUserIDs ) , "," )
2019-09-18 08:39:45 +03:00
contexts , _ := models . FindRepoRecentCommitStatusContexts ( c . Repo . Repository . ID , 7 * 24 * time . Hour ) // Find last week status check contexts
for _ , context := range protectBranch . StatusCheckContexts {
var found bool
for _ , ctx := range contexts {
if ctx == context {
found = true
break
}
}
if ! found {
contexts = append ( contexts , context )
}
}
c . Data [ "branch_status_check_contexts" ] = contexts
c . Data [ "is_context_required" ] = func ( context string ) bool {
for _ , c := range protectBranch . StatusCheckContexts {
if c == context {
return true
}
}
return false
}
2017-09-14 11:16:22 +03:00
if c . Repo . Owner . IsOrganization ( ) {
2018-12-11 14:28:37 +03:00
teams , err := c . Repo . Owner . TeamsWithAccessToRepo ( c . Repo . Repository . ID , models . AccessModeRead )
2017-09-14 11:16:22 +03:00
if err != nil {
2018-01-11 00:34:17 +03:00
c . ServerError ( "Repo.Owner.TeamsWithAccessToRepo" , err )
2017-09-14 11:16:22 +03:00
return
}
c . Data [ "Teams" ] = teams
c . Data [ "whitelist_teams" ] = strings . Join ( base . Int64sToStrings ( protectBranch . WhitelistTeamIDs ) , "," )
2018-03-25 13:01:32 +03:00
c . Data [ "merge_whitelist_teams" ] = strings . Join ( base . Int64sToStrings ( protectBranch . MergeWhitelistTeamIDs ) , "," )
2018-12-11 14:28:37 +03:00
c . Data [ "approvals_whitelist_teams" ] = strings . Join ( base . Int64sToStrings ( protectBranch . ApprovalsWhitelistTeamIDs ) , "," )
2017-09-14 11:16:22 +03:00
}
c . Data [ "Branch" ] = protectBranch
c . HTML ( 200 , tplProtectedBranch )
}
// SettingsProtectedBranchPost updates the protected branch settings
func SettingsProtectedBranchPost ( ctx * context . Context , f auth . ProtectBranchForm ) {
branch := ctx . Params ( "*" )
if ! ctx . Repo . GitRepo . IsBranchExist ( branch ) {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "IsBranchExist" , nil )
2017-09-14 11:16:22 +03:00
return
}
protectBranch , err := models . GetProtectedBranchBy ( ctx . Repo . Repository . ID , branch )
if err != nil {
2019-04-19 15:17:27 +03:00
if ! git . IsErrBranchNotExist ( err ) {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetProtectBranchOfRepoByName" , err )
2017-09-14 11:16:22 +03:00
return
}
}
if f . Protected {
if protectBranch == nil {
// No options found, create defaults.
protectBranch = & models . ProtectedBranch {
RepoID : ctx . Repo . Repository . ID ,
BranchName : branch ,
}
}
2018-12-11 14:28:37 +03:00
if f . RequiredApprovals < 0 {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.protected_branch_required_approvals_min" ) )
ctx . Redirect ( fmt . Sprintf ( "%s/settings/branches/%s" , ctx . Repo . RepoLink , branch ) )
}
2017-09-14 11:16:22 +03:00
2018-12-11 14:28:37 +03:00
var whitelistUsers , whitelistTeams , mergeWhitelistUsers , mergeWhitelistTeams , approvalsWhitelistUsers , approvalsWhitelistTeams [ ] int64
2019-12-04 04:08:56 +03:00
switch f . EnablePush {
case "all" :
protectBranch . CanPush = true
protectBranch . EnableWhitelist = false
protectBranch . WhitelistDeployKeys = false
case "whitelist" :
protectBranch . CanPush = true
protectBranch . EnableWhitelist = true
protectBranch . WhitelistDeployKeys = f . WhitelistDeployKeys
if strings . TrimSpace ( f . WhitelistUsers ) != "" {
whitelistUsers , _ = base . StringsToInt64s ( strings . Split ( f . WhitelistUsers , "," ) )
}
if strings . TrimSpace ( f . WhitelistTeams ) != "" {
whitelistTeams , _ = base . StringsToInt64s ( strings . Split ( f . WhitelistTeams , "," ) )
}
default :
protectBranch . CanPush = false
protectBranch . EnableWhitelist = false
protectBranch . WhitelistDeployKeys = false
2018-11-28 14:26:14 +03:00
}
2019-12-04 04:08:56 +03:00
2018-03-25 13:01:32 +03:00
protectBranch . EnableMergeWhitelist = f . EnableMergeWhitelist
2019-12-04 04:08:56 +03:00
if f . EnableMergeWhitelist {
if strings . TrimSpace ( f . MergeWhitelistUsers ) != "" {
mergeWhitelistUsers , _ = base . StringsToInt64s ( strings . Split ( f . MergeWhitelistUsers , "," ) )
}
if strings . TrimSpace ( f . MergeWhitelistTeams ) != "" {
mergeWhitelistTeams , _ = base . StringsToInt64s ( strings . Split ( f . MergeWhitelistTeams , "," ) )
}
2018-11-28 14:26:14 +03:00
}
2019-09-18 08:39:45 +03:00
protectBranch . EnableStatusCheck = f . EnableStatusCheck
2019-12-04 04:08:56 +03:00
if f . EnableStatusCheck {
protectBranch . StatusCheckContexts = f . StatusCheckContexts
} else {
protectBranch . StatusCheckContexts = nil
}
2019-09-18 08:39:45 +03:00
2018-12-11 14:28:37 +03:00
protectBranch . RequiredApprovals = f . RequiredApprovals
2019-12-04 04:08:56 +03:00
protectBranch . EnableApprovalsWhitelist = f . EnableApprovalsWhitelist
if f . EnableApprovalsWhitelist {
if strings . TrimSpace ( f . ApprovalsWhitelistUsers ) != "" {
approvalsWhitelistUsers , _ = base . StringsToInt64s ( strings . Split ( f . ApprovalsWhitelistUsers , "," ) )
}
if strings . TrimSpace ( f . ApprovalsWhitelistTeams ) != "" {
approvalsWhitelistTeams , _ = base . StringsToInt64s ( strings . Split ( f . ApprovalsWhitelistTeams , "," ) )
}
2018-12-11 14:28:37 +03:00
}
2020-01-03 20:47:10 +03:00
protectBranch . BlockOnRejectedReviews = f . BlockOnRejectedReviews
2020-01-09 04:47:45 +03:00
protectBranch . DismissStaleApprovals = f . DismissStaleApprovals
2020-01-15 11:32:57 +03:00
protectBranch . RequireSignedCommits = f . RequireSignedCommits
2020-03-27 01:26:34 +03:00
protectBranch . ProtectedFilePatterns = f . ProtectedFilePatterns
2020-04-17 04:00:36 +03:00
protectBranch . BlockOnOutdatedBranch = f . BlockOnOutdatedBranch
2019-12-04 04:08:56 +03:00
2018-12-11 14:28:37 +03:00
err = models . UpdateProtectBranch ( ctx . Repo . Repository , protectBranch , models . WhitelistOptions {
UserIDs : whitelistUsers ,
TeamIDs : whitelistTeams ,
MergeUserIDs : mergeWhitelistUsers ,
MergeTeamIDs : mergeWhitelistTeams ,
ApprovalsUserIDs : approvalsWhitelistUsers ,
ApprovalsTeamIDs : approvalsWhitelistTeams ,
} )
2017-09-14 11:16:22 +03:00
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "UpdateProtectBranch" , err )
2017-09-14 11:16:22 +03:00
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_protect_branch_success" , branch ) )
ctx . Redirect ( fmt . Sprintf ( "%s/settings/branches/%s" , ctx . Repo . RepoLink , branch ) )
} else {
if protectBranch != nil {
if err := ctx . Repo . Repository . DeleteProtectedBranch ( protectBranch . ID ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "DeleteProtectedBranch" , err )
2017-09-14 11:16:22 +03:00
return
}
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.remove_protected_branch_success" , branch ) )
ctx . Redirect ( fmt . Sprintf ( "%s/settings/branches" , ctx . Repo . RepoLink ) )
}
}