mirror of https://github.com/go-gitea/gitea.git
Show Signer in commit lists and add basic trust (#10425)
* Show Signer in commit lists and add basic trust Show the avatar of the signer in the commit list pages as we do not enforce that the signer is an author or committer. This makes it clearer who has signed the commit. Also display commits signed by non-members differently from members and in particular make it clear when a non-member signer is different from the committer to help reduce the risk of spoofing. Signed-off-by: Andrew Thornton <art27@cantab.net> * ensure orange text and background is available Signed-off-by: Andrew Thornton <art27@cantab.net> * Update gpg_key.go * Update models/gpg_key.go * Apply suggestions from code review * Require team collaborators to have access to UnitTypeCode * as per @6543 * fix position of sha as per @silverwind * as per @guillep2k
This commit is contained in:
parent
858aebc2d8
commit
90919bb37e
|
@ -60,7 +60,7 @@ _Symbols used in table:_
|
||||||
| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ⁄ | ✓ |
|
| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ⁄ | ✓ |
|
||||||
| Group Milestones | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
| Group Milestones | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||||
| Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
| Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
|
||||||
| Verified Committer | ✘ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
|
| Verified Committer | ⁄ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
|
||||||
| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
| Reject unsigned commits | [✓](https://github.com/go-gitea/gitea/pull/9708) | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
| Reject unsigned commits | [✓](https://github.com/go-gitea/gitea/pull/9708) | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
|
||||||
| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
|
|
@ -374,6 +374,7 @@ type CommitVerification struct {
|
||||||
CommittingUser *User
|
CommittingUser *User
|
||||||
SigningEmail string
|
SigningEmail string
|
||||||
SigningKey *GPGKey
|
SigningKey *GPGKey
|
||||||
|
TrustStatus string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignCommit represents a commit with validation of signature.
|
// SignCommit represents a commit with validation of signature.
|
||||||
|
@ -759,18 +760,54 @@ func verifyWithGPGSettings(gpgSettings *git.GPGSettings, sig *packet.Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
|
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
|
||||||
func ParseCommitsWithSignature(oldCommits *list.List) *list.List {
|
func ParseCommitsWithSignature(oldCommits *list.List, repository *Repository) *list.List {
|
||||||
var (
|
var (
|
||||||
newCommits = list.New()
|
newCommits = list.New()
|
||||||
e = oldCommits.Front()
|
e = oldCommits.Front()
|
||||||
)
|
)
|
||||||
|
memberMap := map[int64]bool{}
|
||||||
|
|
||||||
for e != nil {
|
for e != nil {
|
||||||
c := e.Value.(UserCommit)
|
c := e.Value.(UserCommit)
|
||||||
newCommits.PushBack(SignCommit{
|
signCommit := SignCommit{
|
||||||
UserCommit: &c,
|
UserCommit: &c,
|
||||||
Verification: ParseCommitWithSignature(c.Commit),
|
Verification: ParseCommitWithSignature(c.Commit),
|
||||||
})
|
}
|
||||||
|
|
||||||
|
_ = CalculateTrustStatus(signCommit.Verification, repository, &memberMap)
|
||||||
|
|
||||||
|
newCommits.PushBack(signCommit)
|
||||||
e = e.Next()
|
e = e.Next()
|
||||||
}
|
}
|
||||||
return newCommits
|
return newCommits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalculateTrustStatus will calculate the TrustStatus for a commit verification within a repository
|
||||||
|
func CalculateTrustStatus(verification *CommitVerification, repository *Repository, memberMap *map[int64]bool) (err error) {
|
||||||
|
if verification.Verified {
|
||||||
|
verification.TrustStatus = "trusted"
|
||||||
|
if verification.SigningUser.ID != 0 {
|
||||||
|
var isMember bool
|
||||||
|
if memberMap != nil {
|
||||||
|
var has bool
|
||||||
|
isMember, has = (*memberMap)[verification.SigningUser.ID]
|
||||||
|
if !has {
|
||||||
|
isMember, err = repository.IsOwnerMemberCollaborator(verification.SigningUser.ID)
|
||||||
|
(*memberMap)[verification.SigningUser.ID] = isMember
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isMember, err = repository.IsOwnerMemberCollaborator(verification.SigningUser.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isMember {
|
||||||
|
verification.TrustStatus = "untrusted"
|
||||||
|
if verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||||
|
// The committing user and the signing user are not the same and are not the default key
|
||||||
|
// This should be marked as questionable unless the signing user is a collaborator/team member etc.
|
||||||
|
verification.TrustStatus = "unmatched"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -210,3 +210,23 @@ func (repo *Repository) getRepoTeams(e Engine) (teams []*Team, err error) {
|
||||||
func (repo *Repository) GetRepoTeams() ([]*Team, error) {
|
func (repo *Repository) GetRepoTeams() ([]*Team, error) {
|
||||||
return repo.getRepoTeams(x)
|
return repo.getRepoTeams(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository
|
||||||
|
func (repo *Repository) IsOwnerMemberCollaborator(userID int64) (bool, error) {
|
||||||
|
if repo.OwnerID == userID {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
teamMember, err := x.Join("INNER", "team_repo", "team_repo.team_id = team_user.team_id").
|
||||||
|
Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id").
|
||||||
|
Where("team_repo.repo_id = ?", repo.ID).
|
||||||
|
And("team_unit.`type` = ?", UnitTypeCode).
|
||||||
|
And("team_user.uid = ?", userID).Table("team_user").Exist(&TeamUser{})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if teamMember {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.Get(&Collaboration{RepoID: repo.ID, UserID: userID})
|
||||||
|
}
|
||||||
|
|
|
@ -809,6 +809,8 @@ commits.date = Date
|
||||||
commits.older = Older
|
commits.older = Older
|
||||||
commits.newer = Newer
|
commits.newer = Newer
|
||||||
commits.signed_by = Signed by
|
commits.signed_by = Signed by
|
||||||
|
commits.signed_by_untrusted_user = Signed by untrusted user
|
||||||
|
commits.signed_by_untrusted_user_unmatched = Signed by untrusted user who does not match committer
|
||||||
commits.gpg_key_id = GPG Key ID
|
commits.gpg_key_id = GPG Key ID
|
||||||
|
|
||||||
ext_issues = Ext. Issues
|
ext_issues = Ext. Issues
|
||||||
|
|
|
@ -90,10 +90,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Info("have commit %s", commit.ID.String())
|
|
||||||
verification := models.ParseCommitWithSignature(commit)
|
verification := models.ParseCommitWithSignature(commit)
|
||||||
if !verification.Verified {
|
if !verification.Verified {
|
||||||
log.Info("unverified commit %s", commit.ID.String())
|
|
||||||
cancel()
|
cancel()
|
||||||
return &errUnverifiedCommit{
|
return &errUnverifiedCommit{
|
||||||
commit.ID.String(),
|
commit.ID.String(),
|
||||||
|
|
|
@ -70,7 +70,7 @@ func Commits(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
commits = models.ValidateCommitsWithEmails(commits)
|
commits = models.ValidateCommitsWithEmails(commits)
|
||||||
commits = models.ParseCommitsWithSignature(commits)
|
commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository)
|
||||||
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["Commits"] = commits
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ func SearchCommits(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
commits = models.ValidateCommitsWithEmails(commits)
|
commits = models.ValidateCommitsWithEmails(commits)
|
||||||
commits = models.ParseCommitsWithSignature(commits)
|
commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository)
|
||||||
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["Commits"] = commits
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func FileHistory(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
commits = models.ValidateCommitsWithEmails(commits)
|
commits = models.ValidateCommitsWithEmails(commits)
|
||||||
commits = models.ParseCommitsWithSignature(commits)
|
commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository)
|
||||||
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["Commits"] = commits
|
||||||
|
|
||||||
|
@ -269,12 +269,18 @@ func Diff(ctx *context.Context) {
|
||||||
setPathsCompareContext(ctx, parentCommit, commit, headTarget)
|
setPathsCompareContext(ctx, parentCommit, commit, headTarget)
|
||||||
ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
|
ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
|
||||||
ctx.Data["Commit"] = commit
|
ctx.Data["Commit"] = commit
|
||||||
ctx.Data["Verification"] = models.ParseCommitWithSignature(commit)
|
verification := models.ParseCommitWithSignature(commit)
|
||||||
|
ctx.Data["Verification"] = verification
|
||||||
ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
|
ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
|
||||||
ctx.Data["Diff"] = diff
|
ctx.Data["Diff"] = diff
|
||||||
ctx.Data["Parents"] = parents
|
ctx.Data["Parents"] = parents
|
||||||
ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
|
ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0
|
||||||
|
|
||||||
|
if err := models.CalculateTrustStatus(verification, ctx.Repo.Repository, nil); err != nil {
|
||||||
|
ctx.ServerError("CalculateTrustStatus", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
note := &git.Note{}
|
note := &git.Note{}
|
||||||
err = git.GetNote(ctx.Repo.GitRepo, commitID, note)
|
err = git.GetNote(ctx.Repo.GitRepo, commitID, note)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
@ -316,7 +316,7 @@ func PrepareCompareDiff(
|
||||||
}
|
}
|
||||||
|
|
||||||
compareInfo.Commits = models.ValidateCommitsWithEmails(compareInfo.Commits)
|
compareInfo.Commits = models.ValidateCommitsWithEmails(compareInfo.Commits)
|
||||||
compareInfo.Commits = models.ParseCommitsWithSignature(compareInfo.Commits)
|
compareInfo.Commits = models.ParseCommitsWithSignature(compareInfo.Commits, headRepo)
|
||||||
compareInfo.Commits = models.ParseCommitsWithStatus(compareInfo.Commits, headRepo)
|
compareInfo.Commits = models.ParseCommitsWithStatus(compareInfo.Commits, headRepo)
|
||||||
ctx.Data["Commits"] = compareInfo.Commits
|
ctx.Data["Commits"] = compareInfo.Commits
|
||||||
ctx.Data["CommitCount"] = compareInfo.Commits.Len()
|
ctx.Data["CommitCount"] = compareInfo.Commits.Len()
|
||||||
|
|
|
@ -495,7 +495,7 @@ func ViewPullCommits(ctx *context.Context) {
|
||||||
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
||||||
commits = prInfo.Commits
|
commits = prInfo.Commits
|
||||||
commits = models.ValidateCommitsWithEmails(commits)
|
commits = models.ValidateCommitsWithEmails(commits)
|
||||||
commits = models.ParseCommitsWithSignature(commits)
|
commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository)
|
||||||
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository)
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["Commits"] = commits
|
||||||
ctx.Data["CommitCount"] = commits.Len()
|
ctx.Data["CommitCount"] = commits.Len()
|
||||||
|
|
|
@ -333,7 +333,14 @@ func renderDirectory(ctx *context.Context, treeLink string) {
|
||||||
// Show latest commit info of repository in table header,
|
// Show latest commit info of repository in table header,
|
||||||
// or of directory if not in root directory.
|
// or of directory if not in root directory.
|
||||||
ctx.Data["LatestCommit"] = latestCommit
|
ctx.Data["LatestCommit"] = latestCommit
|
||||||
ctx.Data["LatestCommitVerification"] = models.ParseCommitWithSignature(latestCommit)
|
verification := models.ParseCommitWithSignature(latestCommit)
|
||||||
|
|
||||||
|
if err := models.CalculateTrustStatus(verification, ctx.Repo.Repository, nil); err != nil {
|
||||||
|
ctx.ServerError("CalculateTrustStatus", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["LatestCommitVerification"] = verification
|
||||||
|
|
||||||
ctx.Data["LatestCommitUser"] = models.ValidateCommitWithEmail(latestCommit)
|
ctx.Data["LatestCommitUser"] = models.ValidateCommitWithEmail(latestCommit)
|
||||||
|
|
||||||
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository, ctx.Repo.Commit.ID.String(), 0)
|
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository, ctx.Repo.Commit.ID.String(), 0)
|
||||||
|
|
|
@ -284,7 +284,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
commitsHistory = models.ValidateCommitsWithEmails(commitsHistory)
|
commitsHistory = models.ValidateCommitsWithEmails(commitsHistory)
|
||||||
commitsHistory = models.ParseCommitsWithSignature(commitsHistory)
|
commitsHistory = models.ParseCommitsWithSignature(commitsHistory, ctx.Repo.Repository)
|
||||||
|
|
||||||
ctx.Data["Commits"] = commitsHistory
|
ctx.Data["Commits"] = commitsHistory
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,22 @@
|
||||||
<div class="repository diff">
|
<div class="repository diff">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui container {{if .IsSplitStyle}}fluid padded{{end}}">
|
<div class="ui container {{if .IsSplitStyle}}fluid padded{{end}}">
|
||||||
<div class="ui top attached info clearing segment {{if .Commit.Signature}} isSigned {{if .Verification.Verified }} isVerified {{end}}{{end}}">
|
{{$class := ""}}
|
||||||
|
{{if .Commit.Signature}}
|
||||||
|
{{$class = (printf "%s%s" $class " isSigned")}}
|
||||||
|
{{if .Verification.Verified}}
|
||||||
|
{{if eq .Verification.TrustStatus "trusted"}}
|
||||||
|
{{$class = (printf "%s%s" $class " isVerified")}}
|
||||||
|
{{else if eq .Verification.TrustStatus "untrusted"}}
|
||||||
|
{{$class = (printf "%s%s" $class " isVerifiedUntrusted")}}
|
||||||
|
{{else}}
|
||||||
|
{{$class = (printf "%s%s" $class " isVerifiedUnmatched")}}
|
||||||
|
{{end}}
|
||||||
|
{{else if .Verification.Warning}}
|
||||||
|
{{$class = (printf "%s%s" $class " isWarning")}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
<div class="ui top attached info clearing segment {{$class}}">
|
||||||
<a class="ui floated right blue tiny button" href="{{EscapePound .SourcePath}}">
|
<a class="ui floated right blue tiny button" href="{{EscapePound .SourcePath}}">
|
||||||
{{.i18n.Tr "repo.diff.browse_source"}}
|
{{.i18n.Tr "repo.diff.browse_source"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -12,15 +27,15 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
<span class="text grey">{{svg "octicon-git-branch" 16}}{{.BranchName}}</span>
|
<span class="text grey">{{svg "octicon-git-branch" 16}}{{.BranchName}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui attached info segment {{if .Commit.Signature}} isSigned {{if .Verification.Verified }} isVerified {{end}}{{end}}">
|
<div class="ui attached info segment {{$class}}">
|
||||||
<div class="ui stackable grid">
|
<div class="ui stackable grid">
|
||||||
<div class="nine wide column">
|
<div class="nine wide column">
|
||||||
{{if .Author}}
|
{{if .Author}}
|
||||||
<img class="ui avatar image" src="{{.Author.RelAvatarLink}}" />
|
<img class="ui avatar image" src="{{.Author.RelAvatarLink}}" />
|
||||||
{{if .Author.FullName}}
|
{{if .Author.FullName}}
|
||||||
<a href="{{.Author.HomeLink}}"><strong>{{.Author.FullName}}</strong></a> {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}}
|
<a href="{{.Author.HomeLink}}"><strong>{{.Author.FullName}}</strong> {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="{{.Author.HomeLink}}"><strong>{{.Commit.Author.Name}}</strong></a> {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}}
|
<a href="{{.Author.HomeLink}}"><strong>{{.Commit.Author.Name}}</strong> {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<img class="ui avatar image" src="{{AvatarLink .Commit.Author.Email}}" />
|
<img class="ui avatar image" src="{{AvatarLink .Commit.Author.Email}}" />
|
||||||
|
@ -30,7 +45,7 @@
|
||||||
<span> </span>
|
<span> </span>
|
||||||
{{if ne .Verification.CommittingUser.ID 0}}
|
{{if ne .Verification.CommittingUser.ID 0}}
|
||||||
<img class="ui avatar image" src="{{.Verification.CommittingUser.RelAvatarLink}}" />
|
<img class="ui avatar image" src="{{.Verification.CommittingUser.RelAvatarLink}}" />
|
||||||
<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong></a> <{{.Commit.Committer.Email}}>
|
<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong> <{{.Commit.Committer.Email}}></a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<img class="ui avatar image" src="{{AvatarLink .Commit.Committer.Email}}" />
|
<img class="ui avatar image" src="{{AvatarLink .Commit.Committer.Email}}" />
|
||||||
<strong>{{.Commit.Committer.Name}}</strong>
|
<strong>{{.Commit.Committer.Name}}</strong>
|
||||||
|
@ -58,40 +73,42 @@
|
||||||
</div><!-- end grid -->
|
</div><!-- end grid -->
|
||||||
</div>
|
</div>
|
||||||
{{if .Commit.Signature}}
|
{{if .Commit.Signature}}
|
||||||
{{if .Verification.Verified }}
|
<div class="ui bottom attached message {{$class}}">
|
||||||
<div class="ui bottom attached positive message">
|
{{if .Verification.Verified }}
|
||||||
{{if ne .Verification.SigningUser.ID 0}}
|
{{if ne .Verification.SigningUser.ID 0}}
|
||||||
<i class="green lock icon"></i>
|
<i class="lock icon"></i>
|
||||||
<span>{{.i18n.Tr "repo.commits.signed_by"}}:</span>
|
{{if eq .Verification.TrustStatus "trusted"}}
|
||||||
|
<span class="ui text">{{.i18n.Tr "repo.commits.signed_by"}}:</span>
|
||||||
|
{{else if eq .Verification.TrustStatus "untrusted"}}
|
||||||
|
<span class="ui text">{{.i18n.Tr "repo.commits.signed_by_untrusted_user"}}:</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="ui text">{{.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}:</span>
|
||||||
|
{{end}}
|
||||||
<img class="ui avatar image" src="{{.Verification.SigningUser.RelAvatarLink}}" />
|
<img class="ui avatar image" src="{{.Verification.SigningUser.RelAvatarLink}}" />
|
||||||
<a href="{{.Verification.SigningUser.HomeLink}}"><strong>{{.Verification.SigningUser.Name}}</strong></a> <{{.Verification.SigningEmail}}>
|
<a href="{{.Verification.SigningUser.HomeLink}}"><strong>{{.Verification.SigningUser.Name}}</strong> <{{.Verification.SigningEmail}}></a>
|
||||||
<span class="pull-right"><span>{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> {{.Verification.SigningKey.KeyID}}</span>
|
<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> {{.Verification.SigningKey.KeyID}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<i class="icons" title="{{.i18n.Tr "gpg.default_key"}}">
|
<i class="icons" title="{{.i18n.Tr "gpg.default_key"}}">
|
||||||
<i class="green lock icon"></i>
|
<i class="lock icon"></i>
|
||||||
<i class="tiny inverted cog icon centerlock"></i>
|
<i class="tiny inverted cog icon centerlock"></i>
|
||||||
</i>
|
</i>
|
||||||
<span>{{.i18n.Tr "repo.commits.signed_by"}}:</span>
|
<span class="ui text">{{.i18n.Tr "repo.commits.signed_by"}}:</span>
|
||||||
<img class="ui avatar image" src="{{AvatarLink .Verification.SigningEmail}}" />
|
<img class="ui avatar image" src="{{AvatarLink .Verification.SigningEmail}}" />
|
||||||
<strong>{{.Verification.SigningUser.Name}}</strong> <{{.Verification.SigningEmail}}>
|
<strong>{{.Verification.SigningUser.Name}}</strong> <{{.Verification.SigningEmail}}>
|
||||||
<span class="pull-right"><span>{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="cogs icon" title="{{.i18n.Tr "gpg.default_key"}}"></i>{{.Verification.SigningKey.KeyID}}</span>
|
<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="cogs icon" title="{{.i18n.Tr "gpg.default_key"}}"></i>{{.Verification.SigningKey.KeyID}}</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
{{else if .Verification.Warning}}
|
||||||
{{else if .Verification.Warning}}
|
<i class="unlock icon"></i>
|
||||||
<div class="ui bottom attached message">
|
<span class="ui text">{{.i18n.Tr .Verification.Reason}}</span>
|
||||||
<i class="red unlock icon"></i>
|
<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="warning icon"></i>{{.Verification.SigningKey.KeyID}}</span>
|
||||||
<span class="red text">{{.i18n.Tr .Verification.Reason}}</span>
|
{{else}}
|
||||||
<span class="pull-right"><span class="red text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="red warning icon"></i>{{.Verification.SigningKey.KeyID}}</span>
|
<i class="unlock icon"></i>
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="ui bottom attached message">
|
|
||||||
<i class="grey unlock icon"></i>
|
|
||||||
{{.i18n.Tr .Verification.Reason}}
|
{{.i18n.Tr .Verification.Reason}}
|
||||||
{{if and .Verification.SigningKey (ne .Verification.SigningKey.KeyID "")}}
|
{{if and .Verification.SigningKey (ne .Verification.SigningKey.KeyID "")}}
|
||||||
<span class="pull-right"><span class="red text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="red warning icon"></i>{{.Verification.SigningKey.KeyID}}</span>
|
<span class="pull-right"><span class="ui text">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span> <i class="warning icon"></i>{{.Verification.SigningKey.KeyID}}</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
{{end}}
|
||||||
{{end}}
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .Note}}
|
{{if .Note}}
|
||||||
<div class="ui top attached info segment message git-notes">
|
<div class="ui top attached info segment message git-notes">
|
||||||
|
|
|
@ -28,7 +28,13 @@
|
||||||
{{if .Signature}}
|
{{if .Signature}}
|
||||||
{{$class = (printf "%s%s" $class " isSigned")}}
|
{{$class = (printf "%s%s" $class " isSigned")}}
|
||||||
{{if .Verification.Verified}}
|
{{if .Verification.Verified}}
|
||||||
{{$class = (printf "%s%s" $class " isVerified")}}
|
{{if eq .Verification.TrustStatus "trusted"}}
|
||||||
|
{{$class = (printf "%s%s" $class " isVerified")}}
|
||||||
|
{{else if eq .Verification.TrustStatus "untrusted"}}
|
||||||
|
{{$class = (printf "%s%s" $class " isVerifiedUntrusted")}}
|
||||||
|
{{else}}
|
||||||
|
{{$class = (printf "%s%s" $class " isVerifiedUnmatched")}}
|
||||||
|
{{end}}
|
||||||
{{else if .Verification.Warning}}
|
{{else if .Verification.Warning}}
|
||||||
{{$class = (printf "%s%s" $class " isWarning")}}
|
{{$class = (printf "%s%s" $class " isWarning")}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -38,20 +44,22 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="{{$class}}">
|
<span class="{{$class}}">
|
||||||
{{end}}
|
{{end}}
|
||||||
{{ShortSha .ID.String}}
|
<span class="shortsha">{{ShortSha .ID.String}}</span>
|
||||||
{{if .Signature}}
|
{{if .Signature}}
|
||||||
<div class="ui detail icon button">
|
<div class="ui detail icon button">
|
||||||
{{if .Verification.Verified}}
|
{{if .Verification.Verified}}
|
||||||
{{if ne .Verification.SigningUser.ID 0}}
|
<div title="{{if eq .Verification.TrustStatus "trusted"}}{{else if eq .Verification.TrustStatus "untrusted"}}{{$.i18n.Tr "repo.commits.signed_by_untrusted_user"}}: {{else}}{{$.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}}{{.Verification.Reason}}">
|
||||||
<i title="{{.Verification.Reason}}" class="lock green icon"></i>
|
{{if ne .Verification.SigningUser.ID 0}}
|
||||||
{{else}}
|
<i class="lock icon"></i>
|
||||||
<i title="{{.Verification.Reason}}" class="icons">
|
<img class="ui signature avatar image" src="{{.Verification.SigningUser.RelAvatarLink}}" />
|
||||||
<i class="green lock icon"></i>
|
{{else}}
|
||||||
<i class="tiny inverted cog icon centerlock"></i>
|
<i title="{{.Verification.Reason}}" class="icons">
|
||||||
</i>
|
<i class="lock icon"></i>
|
||||||
{{end}}
|
<i class="tiny inverted cog icon centerlock"></i>
|
||||||
{{else if .Verification.Warning}}
|
</i>
|
||||||
<i title="{{$.i18n.Tr .Verification.Reason}}" class="red unlock icon"></i>
|
<img class="ui signature avatar image" src="{{AvatarLink .Verification.SigningEmail}}" />
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<i title="{{$.i18n.Tr .Verification.Reason}}" class="unlock icon"></i>
|
<i title="{{$.i18n.Tr .Verification.Reason}}" class="unlock icon"></i>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -15,16 +15,27 @@
|
||||||
<strong>{{.LatestCommit.Author.Name}}</strong>
|
<strong>{{.LatestCommit.Author.Name}}</strong>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
<a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified {{end}}{{end}}" href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
|
<a rel="nofollow" class="ui sha label {{if .LatestCommit.Signature}} isSigned {{if .LatestCommitVerification.Verified }} isVerified{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}Untrusted{{else}}Unmatched{{end}}{{else if .LatestCommitVerification.Warning}} isWarning{{end}}{{end}}" href="{{.RepoLink}}/commit/{{.LatestCommit.ID}}">
|
||||||
{{ShortSha .LatestCommit.ID.String}}
|
<span class="shortsha">{{ShortSha .LatestCommit.ID.String}}</span>
|
||||||
{{if .LatestCommit.Signature}}
|
{{if .LatestCommit.Signature}}
|
||||||
<div class="ui detail icon button">
|
{{if .LatestCommitVerification.Verified}}
|
||||||
{{if .LatestCommitVerification.Verified}}
|
<div class="ui detail icon button" title="{{if eq .LatestCommitVerification.TrustStatus "trusted"}}{{else if eq .LatestCommitVerification.TrustStatus "untrusted"}}{{.i18n.Tr "repo.commits.signed_by_untrusted_user"}}: {{else}}{{.i18n.Tr "repo.commits.signed_by_untrusted_user_unmatched"}}: {{end}}{{.LatestCommitVerification.Reason}}">
|
||||||
<i title="{{.LatestCommitVerification.Reason}}" class="lock green icon"></i>
|
{{if ne .LatestCommitVerification.SigningUser.ID 0}}
|
||||||
{{else}}
|
<i class="lock icon"></i>
|
||||||
|
<img class="ui signature avatar image" src="{{.LatestCommitVerification.SigningUser.RelAvatarLink}}" />
|
||||||
|
{{else}}
|
||||||
|
<i title="{{.LatestCommitVerification.Reason}}" class="icons">
|
||||||
|
<i class="lock icon"></i>
|
||||||
|
<i class="tiny inverted cog icon centerlock"></i>
|
||||||
|
</i>
|
||||||
|
<img class="ui signature avatar image" src="{{AvatarLink .LatestCommitVerification.SigningEmail}}" />
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="ui detail icon button">
|
||||||
<i title="{{$.i18n.Tr .LatestCommitVerification.Reason}}" class="unlock icon"></i>
|
<i title="{{$.i18n.Tr .LatestCommitVerification.Reason}}" class="unlock icon"></i>
|
||||||
{{end}}
|
</div>
|
||||||
</div>
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</a>
|
</a>
|
||||||
{{template "repo/commit_status" .LatestCommitStatus}}
|
{{template "repo/commit_status" .LatestCommitStatus}}
|
||||||
|
|
|
@ -443,6 +443,10 @@ code,
|
||||||
color: #fbbd08 !important;
|
color: #fbbd08 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.orange {
|
||||||
|
color: #f2711c !important;
|
||||||
|
}
|
||||||
|
|
||||||
&.gold {
|
&.gold {
|
||||||
color: #a1882b !important;
|
color: #a1882b !important;
|
||||||
}
|
}
|
||||||
|
@ -640,6 +644,10 @@ code,
|
||||||
background-color: #fbbf09 !important;
|
background-color: #fbbf09 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.orange {
|
||||||
|
background-color: #f2711c !important;
|
||||||
|
}
|
||||||
|
|
||||||
&.gold {
|
&.gold {
|
||||||
background-color: #a1882b !important;
|
background-color: #a1882b !important;
|
||||||
}
|
}
|
||||||
|
@ -691,6 +699,10 @@ code,
|
||||||
border-color: #fbbd08 !important;
|
border-color: #fbbd08 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.orange {
|
||||||
|
border-color: #f2711c !important;
|
||||||
|
}
|
||||||
|
|
||||||
&.gold {
|
&.gold {
|
||||||
border-color: #a1882b !important;
|
border-color: #a1882b !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1234,7 +1234,7 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
width: 140px;
|
width: 175px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1255,21 +1255,49 @@
|
||||||
#repo-files-table .sha.label {
|
#repo-files-table .sha.label {
|
||||||
border: 1px solid #bbbbbb;
|
border: 1px solid #bbbbbb;
|
||||||
|
|
||||||
|
.ui.signature.avatar {
|
||||||
|
height: 16px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.detail.icon {
|
.detail.icon {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
margin: -6px -10px -4px 0;
|
margin: -6px -10px -4px 0;
|
||||||
padding: 5px 3px 5px 6px;
|
padding: 5px 4px 5px 6px;
|
||||||
border-left: 1px solid #bbbbbb;
|
border-left: 1px solid #bbbbbb;
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 0;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.isSigned.isWarning {
|
&.isSigned.isWarning {
|
||||||
border: 1px solid #db2828;
|
border: 1px solid #db2828;
|
||||||
background: fade(#db2828, 10%);
|
background: fade(#db2828, 10%);
|
||||||
|
|
||||||
|
.shortsha {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.detail.icon {
|
.detail.icon {
|
||||||
border-left: 1px solid fade(#db2828, 50%);
|
border-left: 1px solid #db2828;
|
||||||
|
color: #db2828;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: fade(#db2828, 30%) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1277,14 +1305,58 @@
|
||||||
border: 1px solid #21ba45;
|
border: 1px solid #21ba45;
|
||||||
background: fade(#21ba45, 10%);
|
background: fade(#21ba45, 10%);
|
||||||
|
|
||||||
|
.shortsha {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.detail.icon {
|
.detail.icon {
|
||||||
border-left: 1px solid #21ba45;
|
border-left: 1px solid #21ba45;
|
||||||
|
color: #21ba45;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: fade(#21ba45, 30%) !important;
|
background: fade(#21ba45, 30%) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.isSigned.isVerifiedUntrusted {
|
||||||
|
border: 1px solid #fbbd08;
|
||||||
|
background: fade(#fbbd08, 10%);
|
||||||
|
|
||||||
|
.shortsha {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail.icon {
|
||||||
|
border-left: 1px solid #fbbd08;
|
||||||
|
color: #fbbd08;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: fade(#fbbd08, 30%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.isSigned.isVerifiedUnmatched {
|
||||||
|
border: 1px solid #f2711c;
|
||||||
|
background: fade(#f2711c, 10%);
|
||||||
|
|
||||||
|
.shortsha {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail.icon {
|
||||||
|
border-left: 1px solid #f2711c;
|
||||||
|
color: #f2711c;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: fade(#f2711c, 30%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.diff-detail-box {
|
.diff-detail-box {
|
||||||
|
@ -1893,21 +1965,114 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.attached.isSigned.isVerified {
|
.ui.attached.isSigned.isWarning {
|
||||||
&:not(.positive) {
|
border-left: 1px solid #c29393;
|
||||||
border-left: 1px solid #a3c293;
|
border-right: 1px solid #c29393;
|
||||||
border-right: 1px solid #a3c293;
|
|
||||||
|
&.top,
|
||||||
|
&.message {
|
||||||
|
border-top: 1px solid #c29393;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.top:not(.positive) {
|
&.message {
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #fff5f5;
|
||||||
|
color: #d95c5c;
|
||||||
|
|
||||||
|
.ui.text {
|
||||||
|
color: #d64444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child,
|
||||||
|
&.bottom {
|
||||||
|
border-bottom: 1px solid #c29393;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.attached.isSigned:not(.isWarning) .pull-right {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.attached.isSigned.isVerified {
|
||||||
|
border-left: 1px solid #a3c293;
|
||||||
|
border-right: 1px solid #a3c293;
|
||||||
|
|
||||||
|
&.top,
|
||||||
|
&.message {
|
||||||
border-top: 1px solid #a3c293;
|
border-top: 1px solid #a3c293;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.positive):last-child {
|
&.message {
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #fcfff5;
|
||||||
|
color: #6cc644;
|
||||||
|
|
||||||
|
.pull-right {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.text {
|
||||||
|
color: #21ba45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child,
|
||||||
|
&.bottom {
|
||||||
border-bottom: 1px solid #a3c293;
|
border-bottom: 1px solid #a3c293;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.attached.isSigned.isVerifiedUntrusted {
|
||||||
|
border-left: 1px solid #c2c193;
|
||||||
|
border-right: 1px solid #c2c193;
|
||||||
|
|
||||||
|
&.top,
|
||||||
|
&.message {
|
||||||
|
border-top: 1px solid #c2c193;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.message {
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #fffff5;
|
||||||
|
color: #fbbd08;
|
||||||
|
|
||||||
|
.ui.text {
|
||||||
|
color: #d2ab00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child,
|
||||||
|
&.bottom {
|
||||||
|
border-bottom: 1px solid #c2c193;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.attached.isSigned.isVerifiedUnmatched {
|
||||||
|
border-left: 1px solid #c2a893;
|
||||||
|
border-right: 1px solid #c2a893;
|
||||||
|
|
||||||
|
&.top,
|
||||||
|
&.message {
|
||||||
|
border-top: 1px solid #c2a893;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.message {
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: #fffaf5;
|
||||||
|
color: #f2711c;
|
||||||
|
|
||||||
|
.ui.text {
|
||||||
|
color: #ee5f00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child,
|
||||||
|
&.bottom {
|
||||||
|
border-bottom: 1px solid #c2a893;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ui.segment.sub-menu {
|
.ui.segment.sub-menu {
|
||||||
padding: 7px;
|
padding: 7px;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
|
|
|
@ -1156,6 +1156,64 @@ a.ui.labels .label:hover {
|
||||||
border-left-color: #888;
|
border-left-color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.repository .ui.attached.message.isSigned.isVerified {
|
||||||
|
background-color: #394829;
|
||||||
|
color: #9e9e9e;
|
||||||
|
|
||||||
|
&.message {
|
||||||
|
color: #87ab63;
|
||||||
|
.ui.text {
|
||||||
|
color: #9e9e9e;
|
||||||
|
}
|
||||||
|
.pull-right {
|
||||||
|
color: #87ab63;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository .ui.attached.message.isSigned.isVerifiedUntrusted {
|
||||||
|
background-color: #4a3903;
|
||||||
|
color: #9e9e9e;
|
||||||
|
&.message {
|
||||||
|
color: #c2c193;
|
||||||
|
.ui.text {
|
||||||
|
color: #9e9e9e;
|
||||||
|
}
|
||||||
|
.pull-right,
|
||||||
|
a {
|
||||||
|
color: #c2c193;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository .ui.attached.message.isSigned.isVerifiedUnmatched {
|
||||||
|
background-color: #4e3321;
|
||||||
|
color: #9e9e9e;
|
||||||
|
&.message {
|
||||||
|
color: #c2a893;
|
||||||
|
.ui.text {
|
||||||
|
color: #9e9e9e;
|
||||||
|
}
|
||||||
|
.pull-right,
|
||||||
|
a {
|
||||||
|
color: #c2a893;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.repository .ui.attached.message.isSigned.isWarning {
|
||||||
|
background-color: rgba(80, 23, 17, .6);
|
||||||
|
&.message {
|
||||||
|
color: #d07d7d;
|
||||||
|
.ui.text {
|
||||||
|
color: #d07d7d;
|
||||||
|
}
|
||||||
|
.pull-right {
|
||||||
|
color: #9e9e9e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.repository .label.list .item {
|
.repository .label.list .item {
|
||||||
border-bottom: 1px dashed #4c505c;
|
border-bottom: 1px dashed #4c505c;
|
||||||
}
|
}
|
||||||
|
@ -1166,6 +1224,11 @@ a.ui.labels .label:hover {
|
||||||
color: #87ab63 !important;
|
color: #87ab63 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.text.yellow,
|
||||||
|
.yellow.icon.icon.icon {
|
||||||
|
color: #e4ac07 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),
|
||||||
|
|
Loading…
Reference in New Issue