2021-09-16 14:34:54 +01:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2021-09-16 14:34:54 +01:00
package private
import (
2025-04-24 21:26:57 +02:00
"errors"
2021-09-16 14:34:54 +01:00
"fmt"
"net/http"
"os"
2022-03-22 17:29:07 +08:00
asymkey_model "code.gitea.io/gitea/models/asymkey"
2022-06-12 23:51:54 +08:00
git_model "code.gitea.io/gitea/models/git"
2022-06-13 17:37:59 +08:00
issues_model "code.gitea.io/gitea/models/issues"
2022-03-22 17:29:07 +08:00
perm_model "code.gitea.io/gitea/models/perm"
2022-05-11 18:09:36 +08:00
access_model "code.gitea.io/gitea/models/perm/access"
2021-11-10 03:57:58 +08:00
"code.gitea.io/gitea/models/unit"
2021-11-24 17:49:20 +08:00
user_model "code.gitea.io/gitea/models/user"
2021-09-16 14:34:54 +01:00
"code.gitea.io/gitea/modules/git"
2025-09-15 23:33:12 -07:00
"code.gitea.io/gitea/modules/git/gitcmd"
2025-03-15 19:48:59 -07:00
"code.gitea.io/gitea/modules/gitrepo"
2021-09-16 14:34:54 +01:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
2025-10-25 10:08:25 -07:00
"code.gitea.io/gitea/modules/util"
2021-09-16 14:34:54 +01:00
"code.gitea.io/gitea/modules/web"
2025-10-25 10:08:25 -07:00
"code.gitea.io/gitea/services/agit"
2024-02-27 15:12:22 +08:00
gitea_context "code.gitea.io/gitea/services/context"
2021-09-16 14:34:54 +01:00
pull_service "code.gitea.io/gitea/services/pull"
)
type preReceiveContext struct {
* gitea_context . PrivateContext
2022-03-22 17:29:07 +08:00
// loadedPusher indicates that where the following information are loaded
loadedPusher bool
user * user_model . User // it's the org user if a DeployKey is used
2022-05-11 18:09:36 +08:00
userPerm access_model . Permission
2022-03-22 17:29:07 +08:00
deployKeyAccessMode perm_model . AccessMode
2021-09-16 14:34:54 +01:00
canCreatePullRequest bool
checkedCanCreatePullRequest bool
canWriteCode bool
checkedCanWriteCode bool
2022-06-12 23:51:54 +08:00
protectedTags [ ] * git_model . ProtectedTag
2021-09-16 14:34:54 +01:00
gotProtectedTags bool
env [ ] string
opts * private . HookOptions
2022-04-28 17:45:33 +02:00
branchName string
2021-09-16 14:34:54 +01:00
}
2022-03-22 17:29:07 +08:00
// CanWriteCode returns true if pusher can write code
2021-09-16 14:34:54 +01:00
func ( ctx * preReceiveContext ) CanWriteCode ( ) bool {
if ! ctx . checkedCanWriteCode {
2022-03-22 17:29:07 +08:00
if ! ctx . loadPusherAndPermission ( ) {
return false
}
2023-07-22 22:14:27 +08:00
ctx . canWriteCode = issues_model . CanMaintainerWriteToBranch ( ctx , ctx . userPerm , ctx . branchName , ctx . user ) || ctx . deployKeyAccessMode >= perm_model . AccessModeWrite
2021-09-16 14:34:54 +01:00
ctx . checkedCanWriteCode = true
}
return ctx . canWriteCode
}
2022-03-22 17:29:07 +08:00
// AssertCanWriteCode returns true if pusher can write code
2021-09-16 14:34:54 +01:00
func ( ctx * preReceiveContext ) AssertCanWriteCode ( ) bool {
if ! ctx . CanWriteCode ( ) {
if ctx . Written ( ) {
return false
}
2023-03-29 14:32:26 +08:00
ctx . JSON ( http . StatusForbidden , private . Response {
UserMsg : "User permission denied for writing." ,
2021-09-16 14:34:54 +01:00
} )
return false
}
return true
}
2022-03-22 17:29:07 +08:00
// CanCreatePullRequest returns true if pusher can create pull requests
2021-09-16 14:34:54 +01:00
func ( ctx * preReceiveContext ) CanCreatePullRequest ( ) bool {
if ! ctx . checkedCanCreatePullRequest {
2022-03-22 17:29:07 +08:00
if ! ctx . loadPusherAndPermission ( ) {
return false
}
ctx . canCreatePullRequest = ctx . userPerm . CanRead ( unit . TypePullRequests )
2021-09-16 14:34:54 +01:00
ctx . checkedCanCreatePullRequest = true
}
return ctx . canCreatePullRequest
}
2022-03-22 17:29:07 +08:00
// AssertCreatePullRequest returns true if can create pull requests
2021-09-16 14:34:54 +01:00
func ( ctx * preReceiveContext ) AssertCreatePullRequest ( ) bool {
if ! ctx . CanCreatePullRequest ( ) {
if ctx . Written ( ) {
return false
}
2023-03-29 14:32:26 +08:00
ctx . JSON ( http . StatusForbidden , private . Response {
UserMsg : "User permission denied for creating pull-request." ,
2021-09-16 14:34:54 +01:00
} )
return false
}
return true
}
// HookPreReceive checks whether a individual commit is acceptable
func HookPreReceive ( ctx * gitea_context . PrivateContext ) {
opts := web . GetForm ( ctx ) . ( * private . HookOptions )
ourCtx := & preReceiveContext {
PrivateContext : ctx ,
env : generateGitEnv ( opts ) , // Generate git environment for checking commits
opts : opts ,
}
// Iterate across the provided old commit IDs
for i := range opts . OldCommitIDs {
oldCommitID := opts . OldCommitIDs [ i ]
newCommitID := opts . NewCommitIDs [ i ]
refFullName := opts . RefFullNames [ i ]
switch {
2023-05-26 09:04:48 +08:00
case refFullName . IsBranch ( ) :
2021-09-16 14:34:54 +01:00
preReceiveBranch ( ourCtx , oldCommitID , newCommitID , refFullName )
2023-05-26 09:04:48 +08:00
case refFullName . IsTag ( ) :
2024-04-29 04:47:56 -04:00
preReceiveTag ( ourCtx , refFullName )
2024-05-07 00:34:16 +08:00
case git . DefaultFeatures ( ) . SupportProcReceive && refFullName . IsFor ( ) :
2024-04-29 04:47:56 -04:00
preReceiveFor ( ourCtx , refFullName )
2021-09-16 14:34:54 +01:00
default :
ourCtx . AssertCanWriteCode ( )
}
if ctx . Written ( ) {
return
}
}
2021-12-15 14:59:57 +08:00
ctx . PlainText ( http . StatusOK , "ok" )
2021-09-16 14:34:54 +01:00
}
2023-05-26 09:04:48 +08:00
func preReceiveBranch ( ctx * preReceiveContext , oldCommitID , newCommitID string , refFullName git . RefName ) {
branchName := refFullName . BranchName ( )
2022-04-28 17:45:33 +02:00
ctx . branchName = branchName
2021-09-16 14:34:54 +01:00
if ! ctx . AssertCanWriteCode ( ) {
return
}
repo := ctx . Repo . Repository
gitRepo := ctx . Repo . GitRepo
2024-02-24 14:55:19 +08:00
objectFormat := ctx . Repo . GetObjectFormat ( )
2021-09-16 14:34:54 +01:00
2026-03-02 12:58:07 -08:00
defaultBranch := repo . DefaultBranch
if ctx . opts . IsWiki && repo . DefaultWikiBranch != "" {
defaultBranch = repo . DefaultWikiBranch
}
if branchName == defaultBranch && newCommitID == objectFormat . EmptyObjectID ( ) . String ( ) {
2021-09-16 14:34:54 +01:00
log . Warn ( "Forbidden: Branch: %s is the default branch in %-v and cannot be deleted" , branchName , repo )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "branch %s is the default branch and cannot be deleted" , branchName ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
2023-01-16 16:00:22 +08:00
protectBranch , err := git_model . GetFirstMatchProtectedBranchRule ( ctx , repo . ID , branchName )
2021-09-16 14:34:54 +01:00
if err != nil {
log . Error ( "Unable to get protected branch: %s in %-v Error: %v" , branchName , repo , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : err . Error ( ) ,
} )
return
}
// Allow pushes to non-protected branches
2023-01-16 16:00:22 +08:00
if protectBranch == nil {
2021-09-16 14:34:54 +01:00
return
}
2023-01-16 16:00:22 +08:00
protectBranch . Repo = repo
2021-09-16 14:34:54 +01:00
// This ref is a protected branch.
//
// First of all we need to enforce absolutely:
//
// 1. Detect and prevent deletion of the branch
2023-12-17 19:56:08 +08:00
if newCommitID == objectFormat . EmptyObjectID ( ) . String ( ) {
2021-09-16 14:34:54 +01:00
log . Warn ( "Forbidden: Branch: %s in %-v is protected from deletion" , branchName , repo )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "branch %s is protected from deletion" , branchName ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
2024-07-06 04:21:56 +10:00
isForcePush := false
2021-09-16 14:34:54 +01:00
// 2. Disallow force pushes to protected branches
2023-12-17 19:56:08 +08:00
if oldCommitID != objectFormat . EmptyObjectID ( ) . String ( ) {
2026-01-19 07:10:33 +08:00
output , _ , err := gitrepo . RunCmdString ( ctx ,
2025-10-07 02:06:51 -07:00
repo ,
gitcmd . NewCommand ( "rev-list" , "--max-count=1" ) .
AddDynamicArguments ( oldCommitID , "^" + newCommitID ) .
WithEnv ( ctx . env ) ,
)
2021-09-16 14:34:54 +01:00
if err != nil {
log . Error ( "Unable to detect force push between: %s and %s in %-v Error: %v" , oldCommitID , newCommitID , repo , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Fail to detect force push: %v" , err ) ,
} )
return
} else if len ( output ) > 0 {
2024-07-06 04:21:56 +10:00
if protectBranch . CanForcePush {
isForcePush = true
} else {
log . Warn ( "Forbidden: Branch: %s in %-v is protected from force push" , branchName , repo )
ctx . JSON ( http . StatusForbidden , private . Response {
UserMsg : fmt . Sprintf ( "branch %s is protected from force push" , branchName ) ,
} )
return
}
2021-09-16 14:34:54 +01:00
}
}
// 3. Enforce require signed commits
if protectBranch . RequireSignedCommits {
err := verifyCommits ( oldCommitID , newCommitID , gitRepo , ctx . env )
if err != nil {
if ! isErrUnverifiedCommit ( err ) {
log . Error ( "Unable to check commits from %s to %s in %-v: %v" , oldCommitID , newCommitID , repo , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to check commits from %s to %s: %v" , oldCommitID , newCommitID , err ) ,
} )
return
}
unverifiedCommit := err . ( * errUnverifiedCommit ) . sha
log . Warn ( "Forbidden: Branch: %s in %-v is protected from unverified commit %s" , branchName , repo , unverifiedCommit )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "branch %s is protected from unverified commit %s" , branchName , unverifiedCommit ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
}
// Now there are several tests which can be overridden:
//
// 4. Check protected file patterns - this is overridable from the UI
changedProtectedfiles := false
protectedFilePath := ""
globs := protectBranch . GetProtectedFilePatterns ( )
if len ( globs ) > 0 {
2024-08-06 21:32:49 +08:00
_ , err := pull_service . CheckFileProtection ( gitRepo , branchName , oldCommitID , newCommitID , globs , 1 , ctx . env )
2021-09-16 14:34:54 +01:00
if err != nil {
2024-12-20 10:05:29 -08:00
if ! pull_service . IsErrFilePathProtected ( err ) {
2021-09-16 14:34:54 +01:00
log . Error ( "Unable to check file protection for commits from %s to %s in %-v: %v" , oldCommitID , newCommitID , repo , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to check file protection for commits from %s to %s: %v" , oldCommitID , newCommitID , err ) ,
} )
return
}
changedProtectedfiles = true
2024-12-20 10:05:29 -08:00
protectedFilePath = err . ( pull_service . ErrFilePathProtected ) . Path
2021-09-16 14:34:54 +01:00
}
}
2024-07-06 04:21:56 +10:00
// 5. Check if the doer is allowed to push (and force-push if the incoming push is a force-push)
2022-06-20 12:02:49 +02:00
var canPush bool
2022-03-22 17:29:07 +08:00
if ctx . opts . DeployKeyID != 0 {
2024-07-06 04:21:56 +10:00
// This flag is only ever true if protectBranch.CanForcePush is true
if isForcePush {
canPush = ! changedProtectedfiles && protectBranch . CanPush && ( ! protectBranch . EnableForcePushAllowlist || protectBranch . ForcePushAllowlistDeployKeys )
} else {
canPush = ! changedProtectedfiles && protectBranch . CanPush && ( ! protectBranch . EnableWhitelist || protectBranch . WhitelistDeployKeys )
}
2021-09-16 14:34:54 +01:00
} else {
2023-01-16 16:00:22 +08:00
user , err := user_model . GetUserByID ( ctx , ctx . opts . UserID )
if err != nil {
log . Error ( "Unable to GetUserByID for commits from %s to %s in %-v: %v" , oldCommitID , newCommitID , repo , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to GetUserByID for commits from %s to %s: %v" , oldCommitID , newCommitID , err ) ,
} )
return
}
2024-07-06 04:21:56 +10:00
if isForcePush {
canPush = ! changedProtectedfiles && protectBranch . CanUserForcePush ( ctx , user )
} else {
canPush = ! changedProtectedfiles && protectBranch . CanUserPush ( ctx , user )
}
2021-09-16 14:34:54 +01:00
}
// 6. If we're not allowed to push directly
if ! canPush {
// Is this is a merge from the UI/API?
if ctx . opts . PullRequestID == 0 {
// 6a. If we're not merging from the UI/API then there are two ways we got here:
//
// We are changing a protected file and we're not allowed to do that
if changedProtectedfiles {
log . Warn ( "Forbidden: Branch: %s in %-v is protected from changing file %s" , branchName , repo , protectedFilePath )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "branch %s is protected from changing file %s" , branchName , protectedFilePath ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
// Allow commits that only touch unprotected files
globs := protectBranch . GetUnprotectedFilePatterns ( )
if len ( globs ) > 0 {
2024-08-06 21:32:49 +08:00
unprotectedFilesOnly , err := pull_service . CheckUnprotectedFiles ( gitRepo , branchName , oldCommitID , newCommitID , globs , ctx . env )
2021-09-16 14:34:54 +01:00
if err != nil {
log . Error ( "Unable to check file protection for commits from %s to %s in %-v: %v" , oldCommitID , newCommitID , repo , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to check file protection for commits from %s to %s: %v" , oldCommitID , newCommitID , err ) ,
} )
return
}
if unprotectedFilesOnly {
// Commit only touches unprotected files, this is allowed
return
}
}
// Or we're simply not able to push to this protected branch
2024-07-06 04:21:56 +10:00
if isForcePush {
log . Warn ( "Forbidden: User %d is not allowed to force-push to protected branch: %s in %-v" , ctx . opts . UserID , branchName , repo )
ctx . JSON ( http . StatusForbidden , private . Response {
2025-04-01 12:14:01 +02:00
UserMsg : "Not allowed to force-push to protected branch " + branchName ,
2024-07-06 04:21:56 +10:00
} )
return
}
2021-09-16 14:34:54 +01:00
log . Warn ( "Forbidden: User %d is not allowed to push to protected branch: %s in %-v" , ctx . opts . UserID , branchName , repo )
ctx . JSON ( http . StatusForbidden , private . Response {
2025-04-01 12:14:01 +02:00
UserMsg : "Not allowed to push to protected branch " + branchName ,
2021-09-16 14:34:54 +01:00
} )
return
}
// 6b. Merge (from UI or API)
// Get the PR, user and permissions for the user in the repository
2022-06-13 17:37:59 +08:00
pr , err := issues_model . GetPullRequestByID ( ctx , ctx . opts . PullRequestID )
2021-09-16 14:34:54 +01:00
if err != nil {
log . Error ( "Unable to get PullRequest %d Error: %v" , ctx . opts . PullRequestID , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to get PullRequest %d Error: %v" , ctx . opts . PullRequestID , err ) ,
} )
return
}
2022-03-22 17:29:07 +08:00
// although we should have called `loadPusherAndPermission` before, here we call it explicitly again because we need to access ctx.user below
if ! ctx . loadPusherAndPermission ( ) {
// if error occurs, loadPusherAndPermission had written the error response
return
}
2021-09-16 14:34:54 +01:00
// Now check if the user is allowed to merge PRs for this repository
// Note: we can use ctx.perm and ctx.user directly as they will have been loaded above
2022-05-03 21:46:28 +02:00
allowedMerge , err := pull_service . IsUserAllowedToMerge ( ctx , pr , ctx . userPerm , ctx . user )
2021-09-16 14:34:54 +01:00
if err != nil {
log . Error ( "Error calculating if allowed to merge: %v" , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Error calculating if allowed to merge: %v" , err ) ,
} )
return
}
if ! allowedMerge {
log . Warn ( "Forbidden: User %d is not allowed to push to protected branch: %s in %-v and is not allowed to merge pr #%d" , ctx . opts . UserID , branchName , repo , pr . Index )
ctx . JSON ( http . StatusForbidden , private . Response {
2025-04-01 12:14:01 +02:00
UserMsg : "Not allowed to push to protected branch " + branchName ,
2021-09-16 14:34:54 +01:00
} )
return
}
// If we're an admin for the repository we can ignore status checks, reviews and override protected files
2022-03-22 17:29:07 +08:00
if ctx . userPerm . IsAdmin ( ) {
2021-09-16 14:34:54 +01:00
return
}
// Now if we're not an admin - we can't overwrite protected files so fail now
if changedProtectedfiles {
log . Warn ( "Forbidden: Branch: %s in %-v is protected from changing file %s" , branchName , repo , protectedFilePath )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "branch %s is protected from changing file %s" , branchName , protectedFilePath ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
// Check all status checks and reviews are ok
2022-05-02 01:54:44 +02:00
if err := pull_service . CheckPullBranchProtections ( ctx , pr , true ) ; err != nil {
2025-04-24 21:26:57 +02:00
if errors . Is ( err , pull_service . ErrNotReadyToMerge ) {
2021-09-16 14:34:54 +01:00
log . Warn ( "Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s" , ctx . opts . UserID , branchName , repo , pr . Index , err . Error ( ) )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "Not allowed to push to protected branch %s and pr #%d is not ready to be merged: %s" , branchName , ctx . opts . PullRequestID , err . Error ( ) ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
2024-04-27 10:03:49 +02:00
log . Error ( "Unable to check if mergeable: protected branch %s in %-v and pr #%d. Error: %v" , ctx . opts . UserID , branchName , repo , pr . Index , err )
2021-09-16 14:34:54 +01:00
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to get status of pull request %d. Error: %v" , ctx . opts . PullRequestID , err ) ,
} )
return
}
}
}
2024-04-29 04:47:56 -04:00
func preReceiveTag ( ctx * preReceiveContext , refFullName git . RefName ) {
2021-09-16 14:34:54 +01:00
if ! ctx . AssertCanWriteCode ( ) {
return
}
2023-05-26 09:04:48 +08:00
tagName := refFullName . TagName ( )
2021-09-16 14:34:54 +01:00
if ! ctx . gotProtectedTags {
var err error
2022-11-19 09:12:33 +01:00
ctx . protectedTags , err = git_model . GetProtectedTags ( ctx , ctx . Repo . Repository . ID )
2021-09-16 14:34:54 +01:00
if err != nil {
log . Error ( "Unable to get protected tags for %-v Error: %v" , ctx . Repo . Repository , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : err . Error ( ) ,
} )
return
}
ctx . gotProtectedTags = true
}
2022-11-19 09:12:33 +01:00
isAllowed , err := git_model . IsUserAllowedToControlTag ( ctx , ctx . protectedTags , tagName , ctx . opts . UserID )
2021-09-16 14:34:54 +01:00
if err != nil {
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : err . Error ( ) ,
} )
return
}
if ! isAllowed {
log . Warn ( "Forbidden: Tag %s in %-v is protected" , tagName , ctx . Repo . Repository )
ctx . JSON ( http . StatusForbidden , private . Response {
2023-03-29 14:32:26 +08:00
UserMsg : fmt . Sprintf ( "Tag %s is protected" , tagName ) ,
2021-09-16 14:34:54 +01:00
} )
return
}
}
2024-04-29 04:47:56 -04:00
func preReceiveFor ( ctx * preReceiveContext , refFullName git . RefName ) {
2021-09-16 14:34:54 +01:00
if ! ctx . AssertCreatePullRequest ( ) {
return
}
if ctx . Repo . Repository . IsEmpty {
2023-03-29 14:32:26 +08:00
ctx . JSON ( http . StatusForbidden , private . Response {
UserMsg : "Can't create pull request for an empty repository." ,
2021-09-16 14:34:54 +01:00
} )
return
}
if ctx . opts . IsWiki {
2023-03-29 14:32:26 +08:00
ctx . JSON ( http . StatusForbidden , private . Response {
UserMsg : "Pull requests are not supported on the wiki." ,
2021-09-16 14:34:54 +01:00
} )
return
}
2025-10-25 10:08:25 -07:00
_ , _ , err := agit . GetAgitBranchInfo ( ctx , ctx . Repo . Repository . ID , refFullName . ForBranchName ( ) )
if err != nil {
if ! errors . Is ( err , util . ErrNotExist ) {
ctx . JSON ( http . StatusForbidden , private . Response {
UserMsg : fmt . Sprintf ( "Unexpected ref: %s" , refFullName ) ,
} )
} else {
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : err . Error ( ) ,
} )
2021-09-16 14:34:54 +01:00
}
}
}
func generateGitEnv ( opts * private . HookOptions ) ( env [ ] string ) {
env = os . Environ ( )
if opts . GitAlternativeObjectDirectories != "" {
env = append ( env ,
private . GitAlternativeObjectDirectories + "=" + opts . GitAlternativeObjectDirectories )
}
if opts . GitObjectDirectory != "" {
env = append ( env ,
private . GitObjectDirectory + "=" + opts . GitObjectDirectory )
}
if opts . GitQuarantinePath != "" {
env = append ( env ,
private . GitQuarantinePath + "=" + opts . GitQuarantinePath )
}
return env
}
2022-03-22 17:29:07 +08:00
// loadPusherAndPermission returns false if an error occurs, and it writes the error response
func ( ctx * preReceiveContext ) loadPusherAndPermission ( ) bool {
if ctx . loadedPusher {
return true
}
2023-01-31 09:45:19 +08:00
if ctx . opts . UserID == user_model . ActionsUserID {
2026-03-21 23:39:47 +01:00
taskID := ctx . opts . ActionsTaskID
ctx . user = user_model . NewActionsUserWithTaskID ( taskID )
if taskID == 0 {
log . Error ( "HookPreReceive: ActionsUser with task ID 0" )
2023-01-31 09:45:19 +08:00
ctx . JSON ( http . StatusInternalServerError , private . Response {
2026-03-21 23:39:47 +01:00
Err : "ActionsUser with task ID 0" ,
} )
return false
}
userPerm , err := access_model . GetActionsUserRepoPermission ( ctx , ctx . Repo . Repository , ctx . user , taskID )
if err != nil {
log . Error ( "Unable to get Actions user repo permission for task %d Error: %v" , taskID , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to get Actions user repo permission for task %d Error: %v" , taskID , err ) ,
2023-01-31 09:45:19 +08:00
} )
return false
}
2026-03-21 23:39:47 +01:00
ctx . userPerm = userPerm
2023-01-31 09:45:19 +08:00
} else {
user , err := user_model . GetUserByID ( ctx , ctx . opts . UserID )
if err != nil {
log . Error ( "Unable to get User id %d Error: %v" , ctx . opts . UserID , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to get User id %d Error: %v" , ctx . opts . UserID , err ) ,
} )
return false
}
ctx . user = user
2026-03-29 11:21:14 +02:00
userPerm , err := access_model . GetDoerRepoPermission ( ctx , ctx . Repo . Repository , user )
2023-01-31 09:45:19 +08:00
if err != nil {
log . Error ( "Unable to get Repo permission of repo %s/%s of User %s: %v" , ctx . Repo . Repository . OwnerName , ctx . Repo . Repository . Name , user . Name , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to get Repo permission of repo %s/%s of User %s: %v" , ctx . Repo . Repository . OwnerName , ctx . Repo . Repository . Name , user . Name , err ) ,
} )
return false
}
ctx . userPerm = userPerm
2022-03-22 17:29:07 +08:00
}
if ctx . opts . DeployKeyID != 0 {
deployKey , err := asymkey_model . GetDeployKeyByID ( ctx , ctx . opts . DeployKeyID )
if err != nil {
log . Error ( "Unable to get DeployKey id %d Error: %v" , ctx . opts . DeployKeyID , err )
ctx . JSON ( http . StatusInternalServerError , private . Response {
Err : fmt . Sprintf ( "Unable to get DeployKey id %d Error: %v" , ctx . opts . DeployKeyID , err ) ,
} )
return false
}
ctx . deployKeyAccessMode = deployKey . Mode
2021-09-16 14:34:54 +01:00
}
2022-03-22 17:29:07 +08:00
ctx . loadedPusher = true
return true
2021-09-16 14:34:54 +01:00
}