-
-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Make git clone URL could use current signed-in user #33091
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
fafb816
fix
wxiaoguang 6547db3
add tests
wxiaoguang 6834311
Merge branch 'main' into fix-ssh-user
wxiaoguang e5f12f3
Merge branch 'main' into fix-ssh-user
wxiaoguang 216e948
Merge branch 'main' into fix-ssh-user
wxiaoguang bbe2fe9
Merge branch 'main' into fix-ssh-user
wxiaoguang 1e93838
giturl
wxiaoguang c398fd0
Apply suggestions from code review
wxiaoguang 143a056
Update custom/conf/app.example.ini
wxiaoguang 9c42045
fix ROOT_URL comment
wxiaoguang 76265dc
Merge branch 'main' into fix-ssh-user
GiteaBot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ import ( | |
user_model "code.gitea.io/gitea/models/user" | ||
"code.gitea.io/gitea/modules/base" | ||
"code.gitea.io/gitea/modules/git" | ||
giturl "code.gitea.io/gitea/modules/git/url" | ||
"code.gitea.io/gitea/modules/httplib" | ||
"code.gitea.io/gitea/modules/log" | ||
"code.gitea.io/gitea/modules/markup" | ||
|
@@ -637,14 +638,26 @@ type CloneLink struct { | |
} | ||
|
||
// ComposeHTTPSCloneURL returns HTTPS clone URL based on given owner and repository name. | ||
func ComposeHTTPSCloneURL(owner, repo string) string { | ||
return fmt.Sprintf("%s%s/%s.git", setting.AppURL, url.PathEscape(owner), url.PathEscape(repo)) | ||
func ComposeHTTPSCloneURL(ctx context.Context, owner, repo string) string { | ||
return fmt.Sprintf("%s%s/%s.git", httplib.GuessCurrentAppURL(ctx), url.PathEscape(owner), url.PathEscape(repo)) | ||
} | ||
|
||
func ComposeSSHCloneURL(ownerName, repoName string) string { | ||
func ComposeSSHCloneURL(doer *user_model.User, ownerName, repoName string) string { | ||
sshUser := setting.SSH.User | ||
sshDomain := setting.SSH.Domain | ||
|
||
if sshUser == "(DOER_USERNAME)" { | ||
// Some users use SSH reverse-proxy and need to use the current signed-in username as the SSH user | ||
// to make the SSH reverse-proxy could prepare the user's public keys ahead. | ||
// For most cases we have the correct "doer", then use it as the SSH user. | ||
// If we can't get the doer, then use the built-in SSH user. | ||
if doer != nil { | ||
sshUser = doer.Name | ||
} else { | ||
sshUser = setting.SSH.BuiltinServerUser | ||
} | ||
} | ||
|
||
// non-standard port, it must use full URI | ||
if setting.SSH.Port != 22 { | ||
sshHost := net.JoinHostPort(sshDomain, strconv.Itoa(setting.SSH.Port)) | ||
|
@@ -662,21 +675,20 @@ func ComposeSSHCloneURL(ownerName, repoName string) string { | |
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshHost, url.PathEscape(ownerName), url.PathEscape(repoName)) | ||
} | ||
|
||
func (repo *Repository) cloneLink(isWiki bool) *CloneLink { | ||
repoName := repo.Name | ||
if isWiki { | ||
repoName += ".wiki" | ||
} | ||
|
||
func (repo *Repository) cloneLink(ctx context.Context, doer *user_model.User, repoPathName string) *CloneLink { | ||
cl := new(CloneLink) | ||
cl.SSH = ComposeSSHCloneURL(repo.OwnerName, repoName) | ||
cl.HTTPS = ComposeHTTPSCloneURL(repo.OwnerName, repoName) | ||
cl.SSH = ComposeSSHCloneURL(doer, repo.OwnerName, repoPathName) | ||
cl.HTTPS = ComposeHTTPSCloneURL(ctx, repo.OwnerName, repoPathName) | ||
return cl | ||
} | ||
|
||
// CloneLink returns clone URLs of repository. | ||
func (repo *Repository) CloneLink() (cl *CloneLink) { | ||
return repo.cloneLink(false) | ||
func (repo *Repository) CloneLink(ctx context.Context, doer *user_model.User) (cl *CloneLink) { | ||
return repo.cloneLink(ctx, doer, repo.Name) | ||
} | ||
|
||
func (repo *Repository) CloneLinkGeneral(ctx context.Context) (cl *CloneLink) { | ||
return repo.cloneLink(ctx, nil /* no doer, use a general git user */, repo.Name) | ||
} | ||
|
||
// GetOriginalURLHostname returns the hostname of a URL or the URL | ||
|
@@ -772,47 +784,75 @@ func GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*Repo | |
return &repo, err | ||
} | ||
|
||
// getRepositoryURLPathSegments returns segments (owner, reponame) extracted from a url | ||
func getRepositoryURLPathSegments(repoURL string) []string { | ||
if strings.HasPrefix(repoURL, setting.AppURL) { | ||
return strings.Split(strings.TrimPrefix(repoURL, setting.AppURL), "/") | ||
func parseRepositoryURL(ctx context.Context, repoURL string) (ret struct { | ||
OwnerName, RepoName, RemainingPath string | ||
}, | ||
) { | ||
// possible urls for git: | ||
// https://my.domain/sub-path/<owner>/<repo>[.git] | ||
// git+ssh://[email protected]/<owner>/<repo>[.git] | ||
// ssh://[email protected]/<owner>/<repo>[.git] | ||
// [email protected]:<owner>/<repo>[.git] | ||
|
||
fillPathParts := func(s string) { | ||
s = strings.TrimPrefix(s, "/") | ||
fields := strings.SplitN(s, "/", 3) | ||
if len(fields) >= 2 { | ||
ret.OwnerName = fields[0] | ||
ret.RepoName = strings.TrimSuffix(fields[1], ".git") | ||
if len(fields) == 3 { | ||
ret.RemainingPath = "/" + fields[2] | ||
} | ||
} | ||
} | ||
|
||
sshURLVariants := [4]string{ | ||
setting.SSH.Domain + ":", | ||
setting.SSH.User + "@" + setting.SSH.Domain + ":", | ||
"git+ssh://" + setting.SSH.Domain + "/", | ||
"git+ssh://" + setting.SSH.User + "@" + setting.SSH.Domain + "/", | ||
parsed, err := giturl.ParseGitURL(repoURL) | ||
if err != nil { | ||
return ret | ||
} | ||
|
||
for _, sshURL := range sshURLVariants { | ||
if strings.HasPrefix(repoURL, sshURL) { | ||
return strings.Split(strings.TrimPrefix(repoURL, sshURL), "/") | ||
if parsed.URL.Scheme == "http" || parsed.URL.Scheme == "https" { | ||
if !httplib.IsCurrentGiteaSiteURL(ctx, repoURL) { | ||
return ret | ||
} | ||
fillPathParts(strings.TrimPrefix(parsed.URL.Path, setting.AppSubURL)) | ||
} else if parsed.URL.Scheme == "ssh" || parsed.URL.Scheme == "git+ssh" { | ||
domainSSH := setting.SSH.Domain | ||
domainCur := httplib.GuessCurrentHostDomain(ctx) | ||
urlDomain, _, _ := net.SplitHostPort(parsed.URL.Host) | ||
urlDomain = util.IfZero(urlDomain, parsed.URL.Host) | ||
if urlDomain == "" { | ||
return ret | ||
} | ||
// check whether URL domain is the App domain | ||
domainMatches := domainSSH == urlDomain | ||
// check whether URL domain is current domain from context | ||
domainMatches = domainMatches || (domainCur != "" && domainCur == urlDomain) | ||
if domainMatches { | ||
fillPathParts(parsed.URL.Path) | ||
} | ||
} | ||
|
||
return nil | ||
return ret | ||
} | ||
|
||
// GetRepositoryByURL returns the repository by given url | ||
func GetRepositoryByURL(ctx context.Context, repoURL string) (*Repository, error) { | ||
// possible urls for git: | ||
// https://my.domain/sub-path/<owner>/<repo>.git | ||
// https://my.domain/sub-path/<owner>/<repo> | ||
// git+ssh://[email protected]/<owner>/<repo>.git | ||
// git+ssh://[email protected]/<owner>/<repo> | ||
// [email protected]:<owner>/<repo>.git | ||
// [email protected]:<owner>/<repo> | ||
|
||
pathSegments := getRepositoryURLPathSegments(repoURL) | ||
|
||
if len(pathSegments) != 2 { | ||
ret := parseRepositoryURL(ctx, repoURL) | ||
if ret.OwnerName == "" { | ||
return nil, fmt.Errorf("unknown or malformed repository URL") | ||
} | ||
return GetRepositoryByOwnerAndName(ctx, ret.OwnerName, ret.RepoName) | ||
} | ||
|
||
ownerName := pathSegments[0] | ||
repoName := strings.TrimSuffix(pathSegments[1], ".git") | ||
return GetRepositoryByOwnerAndName(ctx, ownerName, repoName) | ||
// GetRepositoryByURLRelax also accepts an SSH clone URL without user part | ||
func GetRepositoryByURLRelax(ctx context.Context, repoURL string) (*Repository, error) { | ||
if !strings.Contains(repoURL, "://") && !strings.Contains(repoURL, "@") { | ||
// convert "example.com:owner/repo" to "@example.com:owner/repo" | ||
p1, p2, p3 := strings.Index(repoURL, "."), strings.Index(repoURL, ":"), strings.Index(repoURL, "/") | ||
if 0 < p1 && p1 < p2 && p2 < p3 { | ||
repoURL = "@" + repoURL | ||
} | ||
} | ||
return GetRepositoryByURL(ctx, repoURL) | ||
} | ||
|
||
// GetRepositoryByID returns the repository by given id if exists. | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.