From caa2aeaa523ac71fead044a0890310993d7d5308 Mon Sep 17 00:00:00 2001 From: zeripath Date: Fri, 28 Feb 2020 17:18:02 +0000 Subject: [PATCH] Show Signer in commit lists and add basic trust (#10425) (#10524) Backport #10425 Backport #10511 * Show Signer in commit lists and add basic trust (#10425) 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 Fix the signing icon in the view_list.tmpl page (#10511) Co-Authored-By: silverwind Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- 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/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 | 29 ++- web_src/less/_base.less | 14 +- web_src/less/_repository.less | 183 +++++++++++++++++- web_src/less/themes/arc-green.less | 63 ++++++ 15 files changed, 418 insertions(+), 70 deletions(-) diff --git a/docs/content/doc/features/comparison.en-us.md b/docs/content/doc/features/comparison.en-us.md index a5766f96fc..6d5b66a954 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/issues/2770) | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ | | Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | diff --git a/models/gpg_key.go b/models/gpg_key.go index 58eaa61e22..7b747b3118 100644 --- a/models/gpg_key.go +++ b/models/gpg_key.go @@ -369,6 +369,7 @@ type CommitVerification struct { CommittingUser *User SigningEmail string SigningKey *GPGKey + TrustStatus string } // SignCommit represents a commit with validation of signature. @@ -754,18 +755,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 f04507f3e8..f421a68c7f 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -202,3 +202,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 79dd188f28..f26f38ba33 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -797,6 +797,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/repo/commit.go b/routers/repo/commit.go index 6a4b405e0e..a2695d2d4d 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -65,7 +65,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 @@ -134,7 +134,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 @@ -180,7 +180,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 @@ -262,12 +262,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 3fa86a8d9f..92a666891e 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 8167a53209..c8c35ae917 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -477,7 +477,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 8730523d89..c62a78cf48 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -181,7 +181,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 f18625a599..a01498fb0a 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 52bedc75b7..a3873e4738 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}} {{.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 01096f2085..5dc12c642b 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 32b1a0078a..8705862a26 100644 --- a/templates/repo/view_list.tmpl +++ b/templates/repo/view_list.tmpl @@ -15,17 +15,28 @@ {{.LatestCommit.Author.Name}} {{end}} {{end}} - - {{ShortSha .LatestCommit.ID.String}} + + {{ShortSha .LatestCommit.ID.String}} +
{{if .LatestCommit.Signature}} -
- {{if .LatestCommitVerification.Verified}} - - {{else}} - - {{end}} -
+ {{if .LatestCommitVerification.Verified}} +
+ {{if ne .LatestCommitVerification.SigningUser.ID 0}} + + + {{else}} + + + + + + {{end}} +
+ {{else}} + + {{end}} {{end}} +
{{template "repo/commit_status" .LatestCommitStatus}} {{ $commitLink:= printf "%s/commit/%s" .RepoLink .LatestCommit.ID }} diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 068b9e8144..4806cc56a5 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -471,6 +471,10 @@ code, color: #fbbd08 !important; } + &.orange { + color: #f2711c !important; + } + &.gold { color: #a1882b !important; } @@ -668,6 +672,10 @@ code, background-color: #fbbf09 !important; } + &.orange { + background-color: #f2711c !important; + } + &.gold { background-color: #a1882b !important; } @@ -719,6 +727,10 @@ code, border-color: #fbbd08 !important; } + &.orange { + border-color: #f2711c !important; + } + &.gold { border-color: #a1882b !important; } @@ -1041,7 +1053,7 @@ i.icons .icon:first-child { } i.icon.centerlock { - top: 1.5em; + top: 1.45em; } .ui.label > .detail .icons { diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index e75fb0fae7..3fbd467081 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -1222,7 +1222,7 @@ text-align: center; } - width: 140px; + width: 175px; } } @@ -1243,21 +1243,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; } } @@ -1265,14 +1293,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 { @@ -1872,21 +1944,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/arc-green.less b/web_src/less/themes/arc-green.less index c5f4a43f59..1bd644ece8 100644 --- a/web_src/less/themes/arc-green.less +++ b/web_src/less/themes/arc-green.less @@ -1136,6 +1136,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, 0.6); + &.message { + color: #d07d7d; + .ui.text { + color: #d07d7d; + } + .pull-right { + color: #9e9e9e; + } + } +} + .repository .label.list .item { border-bottom: 1px dashed #4c505c; } @@ -1146,6 +1204,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),