1
1
mirror of https://github.com/go-gitea/gitea synced 2025-09-13 12:18:13 +00:00

Fix SSH signing key path will be displayed in the pull request UI (#35381)

Closes #35361

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
ChristopherHX
2025-09-12 05:00:18 +02:00
committed by GitHub
parent 16e1207449
commit 84812e42df
8 changed files with 70 additions and 18 deletions

View File

@@ -25,7 +25,7 @@ type CommitVerification struct {
SigningUser *user_model.User // if Verified, then SigningUser is non-nil
CommittingUser *user_model.User // if Verified, then CommittingUser is non-nil
SigningEmail string
SigningKey *GPGKey
SigningKey *GPGKey // FIXME: need to refactor it to a new name like "SigningGPGKey", it is also used in some templates
SigningSSHKey *PublicKey
TrustStatus string
}

View File

@@ -0,0 +1,37 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package asymkey
import (
"os"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
func GetDisplaySigningKey(key *git.SigningKey) string {
if key == nil || key.Format == "" {
return ""
}
switch key.Format {
case git.SigningKeyFormatOpenPGP:
return key.KeyID
case git.SigningKeyFormatSSH:
content, err := os.ReadFile(key.KeyID)
if err != nil {
log.Error("Unable to read SSH key %s: %v", key.KeyID, err)
return "(Unable to read SSH key)"
}
display, err := CalcFingerprint(string(content))
if err != nil {
log.Error("Unable to calculate fingerprint for SSH key %s: %v", key.KeyID, err)
return "(Unable to calculate fingerprint for SSH key)"
}
return display
}
setting.PanicInDevOrTesting("Unknown signing key format: %s", key.Format)
return "(Unknown key format)"
}

View File

@@ -3,13 +3,24 @@
package git
import "code.gitea.io/gitea/modules/setting"
// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat
const (
SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli
SigningKeyFormatSSH = "ssh"
)
// SigningKey represents an instance key info which will be used to sign git commits.
// FIXME: need to refactor it to a new name, this name conflicts with the variable names for "asymkey.GPGKey" in many places.
type SigningKey struct {
KeyID string
Format string
}
func (s *SigningKey) String() string {
// Do not expose KeyID
// In case the key is a file path and the struct is rendered in a template, then the server path will be exposed.
setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path")
return "SigningKey:" + s.Format
}

View File

@@ -12,6 +12,7 @@ import (
"strconv"
activities_model "code.gitea.io/gitea/models/activities"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -494,7 +495,7 @@ func preparePullViewSigning(ctx *context.Context, issue *issues_model.Issue) {
if ctx.Doer != nil {
sign, key, _, err := asymkey_service.SignMerge(ctx, pull, ctx.Doer, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitHeadRefName())
ctx.Data["WillSign"] = sign
ctx.Data["SigningKey"] = key
ctx.Data["SigningKeyMergeDisplay"] = asymkey_model.GetDisplaySigningKey(key)
if err != nil {
if asymkey_service.IsErrWontSign(err) {
ctx.Data["WontSignReason"] = err.(*asymkey_service.ErrWontSign).Reason

View File

@@ -14,6 +14,7 @@ import (
"path"
"strings"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
@@ -99,7 +100,7 @@ type CommitFormOptions struct {
UserCanPush bool
RequireSigned bool
WillSign bool
SigningKey *git.SigningKey
SigningKeyFormDisplay string
WontSignReason string
CanCreatePullRequest bool
CanCreateBasePullRequest bool
@@ -139,7 +140,7 @@ func PrepareCommitFormOptions(ctx *Context, doer *user_model.User, targetRepo *r
protectionRequireSigned = protectedBranch.RequireSignedCommits
}
willSign, signKeyID, _, err := asymkey_service.SignCRUDAction(ctx, targetRepo.RepoPath(), doer, targetRepo.RepoPath(), refName.String())
willSign, signKey, _, err := asymkey_service.SignCRUDAction(ctx, targetRepo.RepoPath(), doer, targetRepo.RepoPath(), refName.String())
wontSignReason := ""
if asymkey_service.IsErrWontSign(err) {
wontSignReason = string(err.(*asymkey_service.ErrWontSign).Reason)
@@ -162,7 +163,7 @@ func PrepareCommitFormOptions(ctx *Context, doer *user_model.User, targetRepo *r
UserCanPush: canPushWithProtection,
RequireSigned: protectionRequireSigned,
WillSign: willSign,
SigningKey: signKeyID,
SigningKeyFormDisplay: asymkey_model.GetDisplaySigningKey(signKey),
WontSignReason: wontSignReason,
CanCreatePullRequest: canCreatePullRequest,

View File

@@ -8,7 +8,7 @@ so this template should be kept as small as possbile, DO NOT put large component
*/}}
{{- $commit := $.Commit -}}
{{- $commitBaseLink := $.CommitBaseLink -}}
{{- $verification := $.CommitSignVerification -}}
{{- $verification := $.CommitSignVerification -}}{{- /* asymkey.CommitVerification */ -}}
{{- $extraClass := "" -}}
{{- $verified := false -}}
@@ -50,7 +50,7 @@ so this template should be kept as small as possbile, DO NOT put large component
{{- if $verification.SigningSSHKey -}}
{{- $msgSigningKey = print (ctx.Locale.Tr "repo.commits.ssh_key_fingerprint") ": " $verification.SigningSSHKey.Fingerprint -}}
{{- else if $verification.SigningKey -}}
{{- else if $verification.SigningKey -}}{{- /* asymkey.GPGKey */ -}}
{{- $msgSigningKey = print (ctx.Locale.Tr "repo.commits.gpg_key_id") ": " $verification.SigningKey.PaddedKeyID -}}
{{- end -}}
{{- end -}}

View File

@@ -1,13 +1,15 @@
<div class="commit-form-wrapper">
{{ctx.AvatarUtils.Avatar .SignedUser 40 "commit-avatar"}}
<div class="commit-form avatar-content-left-arrow">
<h3>{{- if .CommitFormOptions.WillSign}}
<span title="{{ctx.Locale.Tr "repo.signing.will_sign" .CommitFormOptions.SigningKey}}">{{svg "octicon-lock" 24}}</span>
<h3>
{{- if .CommitFormOptions.WillSign}}
<span data-tooltip-content="{{ctx.Locale.Tr "repo.signing.will_sign" .CommitFormOptions.SigningKeyFormDisplay}}">{{svg "octicon-lock" 24}}</span>
{{ctx.Locale.Tr "repo.editor.commit_signed_changes"}}
{{- else}}
<span title="{{ctx.Locale.Tr (printf "repo.signing.wont_sign.%s" .CommitFormOptions.WontSignReason)}}">{{svg "octicon-unlock" 24}}</span>
{{ctx.Locale.Tr "repo.editor.commit_changes"}}
{{- end}}</h3>
{{- end}}
</h3>
<div class="field">
<input name="commit_summary" maxlength="100" placeholder="{{if .PageIsDelete}}{{ctx.Locale.Tr "repo.editor.delete" .TreePath}}{{else if .PageIsUpload}}{{ctx.Locale.Tr "repo.editor.upload_files_to_dir" .TreePath}}{{else if .IsNewFile}}{{ctx.Locale.Tr "repo.editor.add_tmpl"}}{{else if .PageIsPatch}}{{ctx.Locale.Tr "repo.editor.patch"}}{{else}}{{ctx.Locale.Tr "repo.editor.update" .TreePath}}{{end}}" value="{{.commit_summary}}" autofocus>
</div>

View File

@@ -188,7 +188,7 @@
{{if .WillSign}}
<div class="item">
{{svg "octicon-lock" 16 "text green"}}
{{ctx.Locale.Tr "repo.signing.will_sign" .SigningKey}}
{{ctx.Locale.Tr "repo.signing.will_sign" .SigningKeyMergeDisplay}}
</div>
{{else if .IsSigned}}
<div class="item">