From 90919bb37e2bcc62440e393439825fe0e1e1f343 Mon Sep 17 00:00:00 2001 From: zeripath Date: Thu, 27 Feb 2020 19:20:55 +0000 Subject: [PATCH] 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 * ensure orange text and background is available Signed-off-by: Andrew Thornton * 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 --- docs/content/doc/features/comparison.en-us.md | 2 +- models/gpg_key.go | 43 +++- models/repo_collaboration.go | 20 ++ options/locale/locale_en-US.ini | 2 + routers/private/hook.go | 2 - routers/repo/commit.go | 14 +- routers/repo/compare.go | 2 +- routers/repo/pull.go | 2 +- routers/repo/view.go | 9 +- routers/repo/wiki.go | 2 +- templates/repo/commit_page.tmpl | 71 ++++--- templates/repo/commits_list.tmpl | 32 +-- templates/repo/view_list.tmpl | 27 ++- web_src/less/_base.less | 12 ++ web_src/less/_repository.less | 183 +++++++++++++++++- web_src/less/themes/theme-arc-green.less | 63 ++++++ 16 files changed, 416 insertions(+), 70 deletions(-) diff --git a/docs/content/doc/features/comparison.en-us.md b/docs/content/doc/features/comparison.en-us.md index 21731b20fddf..dab1ee7eafc3 100644 --- a/docs/content/doc/features/comparison.en-us.md +++ b/docs/content/doc/features/comparison.en-us.md @@ -60,7 +60,7 @@ _Symbols used in table:_ | Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ⁄ | ✓ | | Group Milestones | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | | Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Verified Committer | ✘ | ✘ | ? | ✓ | ✓ | ✓ | ✘ | +| Verified Committer | ⁄ | ✘ | ? | ✓ | ✓ | ✓ | ✘ | | GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | | Reject unsigned commits | [✓](https://github.com/go-gitea/gitea/pull/9708) | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ | | Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | diff --git a/models/gpg_key.go b/models/gpg_key.go index 643aa6822c0c..a32312a12dd6 100644 --- a/models/gpg_key.go +++ b/models/gpg_key.go @@ -374,6 +374,7 @@ type CommitVerification struct { CommittingUser *User SigningEmail string SigningKey *GPGKey + TrustStatus string } // 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. -func ParseCommitsWithSignature(oldCommits *list.List) *list.List { +func ParseCommitsWithSignature(oldCommits *list.List, repository *Repository) *list.List { var ( newCommits = list.New() e = oldCommits.Front() ) + memberMap := map[int64]bool{} + for e != nil { c := e.Value.(UserCommit) - newCommits.PushBack(SignCommit{ + signCommit := SignCommit{ UserCommit: &c, Verification: ParseCommitWithSignature(c.Commit), - }) + } + + _ = CalculateTrustStatus(signCommit.Verification, repository, &memberMap) + + newCommits.PushBack(signCommit) e = e.Next() } 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 +} diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index 8c6ef3623037..85bc99f32034 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -210,3 +210,23 @@ func (repo *Repository) getRepoTeams(e Engine) (teams []*Team, err error) { func (repo *Repository) GetRepoTeams() ([]*Team, error) { 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}) +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index cbe8aaad7a49..4a38dc62c1fb 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -809,6 +809,8 @@ commits.date = Date commits.older = Older commits.newer = Newer 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 ext_issues = Ext. Issues diff --git a/routers/private/hook.go b/routers/private/hook.go index 44e82ebe6c73..1d8cb4b48ec5 100644 --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -90,10 +90,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error { if err != nil { return err } - log.Info("have commit %s", commit.ID.String()) verification := models.ParseCommitWithSignature(commit) if !verification.Verified { - log.Info("unverified commit %s", commit.ID.String()) cancel() return &errUnverifiedCommit{ commit.ID.String(), diff --git a/routers/repo/commit.go b/routers/repo/commit.go index b2fa2790bcd8..2767986fda6e 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -70,7 +70,7 @@ func Commits(ctx *context.Context) { return } commits = models.ValidateCommitsWithEmails(commits) - commits = models.ParseCommitsWithSignature(commits) + commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository) commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository) ctx.Data["Commits"] = commits @@ -139,7 +139,7 @@ func SearchCommits(ctx *context.Context) { return } commits = models.ValidateCommitsWithEmails(commits) - commits = models.ParseCommitsWithSignature(commits) + commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository) commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository) ctx.Data["Commits"] = commits @@ -185,7 +185,7 @@ func FileHistory(ctx *context.Context) { return } commits = models.ValidateCommitsWithEmails(commits) - commits = models.ParseCommitsWithSignature(commits) + commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository) commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository) ctx.Data["Commits"] = commits @@ -269,12 +269,18 @@ func Diff(ctx *context.Context) { setPathsCompareContext(ctx, parentCommit, commit, headTarget) ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID) 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["Diff"] = diff ctx.Data["Parents"] = parents 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{} err = git.GetNote(ctx.Repo.GitRepo, commitID, note) if err == nil { diff --git a/routers/repo/compare.go b/routers/repo/compare.go index 833b7d91829a..d7fddc45587c 100644 --- a/routers/repo/compare.go +++ b/routers/repo/compare.go @@ -316,7 +316,7 @@ func PrepareCompareDiff( } 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) ctx.Data["Commits"] = compareInfo.Commits ctx.Data["CommitCount"] = compareInfo.Commits.Len() diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 11c376be7e63..92538945b024 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -495,7 +495,7 @@ func ViewPullCommits(ctx *context.Context) { ctx.Data["Reponame"] = ctx.Repo.Repository.Name commits = prInfo.Commits commits = models.ValidateCommitsWithEmails(commits) - commits = models.ParseCommitsWithSignature(commits) + commits = models.ParseCommitsWithSignature(commits, ctx.Repo.Repository) commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository) ctx.Data["Commits"] = commits ctx.Data["CommitCount"] = commits.Len() diff --git a/routers/repo/view.go b/routers/repo/view.go index 8364b1636b2b..5bcf4dae3bb9 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -333,7 +333,14 @@ func renderDirectory(ctx *context.Context, treeLink string) { // Show latest commit info of repository in table header, // or of directory if not in root directory. 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) statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository, ctx.Repo.Commit.ID.String(), 0) diff --git a/routers/repo/wiki.go b/routers/repo/wiki.go index f18625a59972..a01498fb0a1a 100644 --- a/routers/repo/wiki.go +++ b/routers/repo/wiki.go @@ -284,7 +284,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) return nil, nil } commitsHistory = models.ValidateCommitsWithEmails(commitsHistory) - commitsHistory = models.ParseCommitsWithSignature(commitsHistory) + commitsHistory = models.ParseCommitsWithSignature(commitsHistory, ctx.Repo.Repository) ctx.Data["Commits"] = commitsHistory diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index 0c3430c6acde..1cfd0944d513 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -2,7 +2,22 @@
{{template "repo/header" .}}
-
+ {{$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}} +
{{.i18n.Tr "repo.diff.browse_source"}} @@ -12,15 +27,15 @@ {{end}} {{svg "octicon-git-branch" 16}}{{.BranchName}}
-
+
{{if .Author}} {{if .Author.FullName}} - {{.Author.FullName}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} + {{.Author.FullName}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} {{else}} - {{.Commit.Author.Name}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} + {{.Commit.Author.Name}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} {{end}} {{else}} @@ -30,7 +45,7 @@ {{if ne .Verification.CommittingUser.ID 0}} - {{.Commit.Committer.Name}} <{{.Commit.Committer.Email}}> + {{.Commit.Committer.Name}} <{{.Commit.Committer.Email}}> {{else}} {{.Commit.Committer.Name}} @@ -58,40 +73,42 @@
{{if .Commit.Signature}} - {{if .Verification.Verified }} -
+
+ {{if .Verification.Verified }} {{if ne .Verification.SigningUser.ID 0}} - - {{.i18n.Tr "repo.commits.signed_by"}}: + + {{if eq .Verification.TrustStatus "trusted"}} + {{.i18n.Tr "repo.commits.signed_by"}}: + {{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.SigningUser.Name}} <{{.Verification.SigningEmail}}> - {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} + {{.Verification.SigningUser.Name}} <{{.Verification.SigningEmail}}> + {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} {{else}} - + - {{.i18n.Tr "repo.commits.signed_by"}}: + {{.i18n.Tr "repo.commits.signed_by"}}: {{.Verification.SigningUser.Name}} <{{.Verification.SigningEmail}}> - {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} + {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} {{end}} -
- {{else if .Verification.Warning}} -
- - {{.i18n.Tr .Verification.Reason}} - {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} -
- {{else}} -
- + {{else if .Verification.Warning}} + + {{.i18n.Tr .Verification.Reason}} + {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} + {{else}} + {{.i18n.Tr .Verification.Reason}} {{if and .Verification.SigningKey (ne .Verification.SigningKey.KeyID "")}} - {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} + {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} {{end}} -
- {{end}} + {{end}} +
{{end}} {{if .Note}}
diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl index 01096f2085dc..5dc12c642bdb 100644 --- a/templates/repo/commits_list.tmpl +++ b/templates/repo/commits_list.tmpl @@ -28,7 +28,13 @@ {{if .Signature}} {{$class = (printf "%s%s" $class " isSigned")}} {{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}} {{$class = (printf "%s%s" $class " isWarning")}} {{end}} @@ -38,20 +44,22 @@ {{else}} {{end}} - {{ShortSha .ID.String}} + {{ShortSha .ID.String}} {{if .Signature}}
{{if .Verification.Verified}} - {{if ne .Verification.SigningUser.ID 0}} - - {{else}} - - - - - {{end}} - {{else if .Verification.Warning}} - +
+ {{if ne .Verification.SigningUser.ID 0}} + + + {{else}} + + + + + + {{end}} +
{{else}} {{end}} diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl index e8163787f55f..c296eb7beec6 100644 --- a/templates/repo/view_list.tmpl +++ b/templates/repo/view_list.tmpl @@ -15,16 +15,27 @@ {{.LatestCommit.Author.Name}} {{end}} {{end}} - - {{ShortSha .LatestCommit.ID.String}} + + {{ShortSha .LatestCommit.ID.String}} {{if .LatestCommit.Signature}} -
- {{if .LatestCommitVerification.Verified}} - - {{else}} + {{if .LatestCommitVerification.Verified}} +
+ {{if ne .LatestCommitVerification.SigningUser.ID 0}} + + + {{else}} + + + + + + {{end}} +
+ {{else}} +
- {{end}} -
+
+ {{end}} {{end}}
{{template "repo/commit_status" .LatestCommitStatus}} diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 3b40abe208b5..1df012454204 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -443,6 +443,10 @@ code, color: #fbbd08 !important; } + &.orange { + color: #f2711c !important; + } + &.gold { color: #a1882b !important; } @@ -640,6 +644,10 @@ code, background-color: #fbbf09 !important; } + &.orange { + background-color: #f2711c !important; + } + &.gold { background-color: #a1882b !important; } @@ -691,6 +699,10 @@ code, border-color: #fbbd08 !important; } + &.orange { + border-color: #f2711c !important; + } + &.gold { border-color: #a1882b !important; } diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 7618a4d76357..503ef1debd52 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -1234,7 +1234,7 @@ text-align: center; } - width: 140px; + width: 175px; } } @@ -1255,21 +1255,49 @@ #repo-files-table .sha.label { border: 1px solid #bbbbbb; + .ui.signature.avatar { + height: 16px; + margin-bottom: 0; + width: auto; + } + .detail.icon { background: #fafafa; margin: -6px -10px -4px 0; - padding: 5px 3px 5px 6px; + padding: 5px 4px 5px 6px; border-left: 1px solid #bbbbbb; + border-top: 0; + border-right: 0; + border-bottom: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; + + img { + margin-right: 0; + } + + > div { + display: inline-flex; + align-items: center; + } } &.isSigned.isWarning { border: 1px solid #db2828; background: fade(#db2828, 10%); + .shortsha { + display: inline-block; + padding-top: 1px; + } + .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; background: fade(#21ba45, 10%); + .shortsha { + display: inline-block; + padding-top: 1px; + } + .detail.icon { border-left: 1px solid #21ba45; + color: #21ba45; } &:hover { 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 { @@ -1893,21 +1965,114 @@ } } - .ui.attached.isSigned.isVerified { - &:not(.positive) { - border-left: 1px solid #a3c293; - border-right: 1px solid #a3c293; + .ui.attached.isSigned.isWarning { + border-left: 1px solid #c29393; + border-right: 1px solid #c29393; + + &.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; } - &: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; } } + .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 { padding: 7px; line-height: 0; diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index a6f58e85d2d6..fdae5ecdc1de 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -1156,6 +1156,64 @@ a.ui.labels .label:hover { 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 { border-bottom: 1px dashed #4c505c; } @@ -1166,6 +1224,11 @@ a.ui.labels .label:hover { 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(2), .repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),