Skip to content

Commit 79a2be0

Browse files
committed
Merge remote-tracking branch 'go-gitea/main' into admin-user-list-filter
2 parents 30f7430 + c446901 commit 79a2be0

File tree

14 files changed

+154
-38
lines changed

14 files changed

+154
-38
lines changed

custom/conf/app.example.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ INTERNAL_TOKEN=
392392
;; Enables OAuth2 provider
393393
ENABLE = true
394394
;;
395-
;; Algorithm used to sign OAuth2 tokens. Valid values: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512
395+
;; Algorithm used to sign OAuth2 tokens. Valid values: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, EdDSA
396396
;JWT_SIGNING_ALGORITHM = RS256
397397
;;
398398
;; Private key file path used to sign OAuth2 tokens. The path is relative to APP_DATA_PATH.

models/issue_label.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package models
88
import (
99
"fmt"
1010
"html/template"
11+
"math"
1112
"regexp"
1213
"strconv"
1314
"strings"
@@ -138,19 +139,44 @@ func (label *Label) BelongsToRepo() bool {
138139
return label.RepoID > 0
139140
}
140141

142+
// SrgbToLinear converts a component of an sRGB color to its linear intensity
143+
// See: https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation_(sRGB_to_CIE_XYZ)
144+
func SrgbToLinear(color uint8) float64 {
145+
flt := float64(color) / 255
146+
if flt <= 0.04045 {
147+
return flt / 12.92
148+
}
149+
return math.Pow((flt+0.055)/1.055, 2.4)
150+
}
151+
152+
// Luminance returns the luminance of an sRGB color
153+
func Luminance(color uint32) float64 {
154+
r := SrgbToLinear(uint8(0xFF & (color >> 16)))
155+
g := SrgbToLinear(uint8(0xFF & (color >> 8)))
156+
b := SrgbToLinear(uint8(0xFF & color))
157+
158+
// luminance ratios for sRGB
159+
return 0.2126*r + 0.7152*g + 0.0722*b
160+
}
161+
162+
// LuminanceThreshold is the luminance at which white and black appear to have the same contrast
163+
// i.e. x such that 1.05 / (x + 0.05) = (x + 0.05) / 0.05
164+
// i.e. math.Sqrt(1.05*0.05) - 0.05
165+
const LuminanceThreshold float64 = 0.179
166+
141167
// ForegroundColor calculates the text color for labels based
142168
// on their background color.
143169
func (label *Label) ForegroundColor() template.CSS {
144170
if strings.HasPrefix(label.Color, "#") {
145171
if color, err := strconv.ParseUint(label.Color[1:], 16, 64); err == nil {
146-
r := float32(0xFF & (color >> 16))
147-
g := float32(0xFF & (color >> 8))
148-
b := float32(0xFF & color)
149-
luminance := (0.2126*r + 0.7152*g + 0.0722*b) / 255
172+
// NOTE: see web_src/js/components/ContextPopup.vue for similar implementation
173+
luminance := Luminance(uint32(color))
150174

151-
if luminance < 0.66 {
175+
// prefer white or black based upon contrast
176+
if luminance < LuminanceThreshold {
152177
return template.CSS("#fff")
153178
}
179+
return template.CSS("#000")
154180
}
155181
}
156182

models/user.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,14 +1622,7 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
16221622
}
16231623

16241624
if opts.Actor != nil {
1625-
var exprCond builder.Cond
1626-
if setting.Database.UseMySQL {
1627-
exprCond = builder.Expr("org_user.org_id = user.id")
1628-
} else if setting.Database.UseMSSQL {
1629-
exprCond = builder.Expr("org_user.org_id = [user].id")
1630-
} else {
1631-
exprCond = builder.Expr("org_user.org_id = \"user\".id")
1632-
}
1625+
var exprCond builder.Cond = builder.Expr("org_user.org_id = `user`.id")
16331626

16341627
// If Admin - they see all users!
16351628
if !opts.Actor.IsAdmin {

modules/repository/commits.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type PushCommits struct {
3030
Commits []*PushCommit
3131
HeadCommit *PushCommit
3232
CompareURL string
33+
Len int
3334

3435
avatars map[string]string
3536
emailUsers map[string]*models.User
@@ -180,5 +181,12 @@ func GitToPushCommits(gitCommits []*git.Commit) *PushCommits {
180181
for _, commit := range gitCommits {
181182
commits = append(commits, CommitToPushCommit(commit))
182183
}
183-
return &PushCommits{commits, nil, "", make(map[string]string), make(map[string]*models.User)}
184+
return &PushCommits{
185+
Commits: commits,
186+
HeadCommit: nil,
187+
CompareURL: "",
188+
Len: len(commits),
189+
avatars: make(map[string]string),
190+
emailUsers: make(map[string]*models.User),
191+
}
184192
}

modules/templates/helper.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,11 @@ func ActionContent2Commits(act Actioner) *repository.PushCommits {
819819
if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil {
820820
log.Error("json.Unmarshal:\n%s\nERROR: %v", act.GetContent(), err)
821821
}
822+
823+
if push.Len == 0 {
824+
push.Len = len(push.Commits)
825+
}
826+
822827
return push
823828
}
824829

options/locale/locale_en-US.ini

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -900,12 +900,12 @@ migrate.migrate = Migrate From %s
900900
migrate.migrating = Migrating from <b>%s</b> ...
901901
migrate.migrating_failed = Migrating from <b>%s</b> failed.
902902
migrate.migrating_failed.error = Error: %s
903-
migrate.github.description = Migrating data from Github.com or Github Enterprise.
904-
migrate.git.description = Migrating or Mirroring git data from Git services
905-
migrate.gitlab.description = Migrating data from GitLab.com or Self-Hosted gitlab server.
906-
migrate.gitea.description = Migrating data from Gitea.com or Self-Hosted Gitea server.
907-
migrate.gogs.description = Migrating data from notabug.org or other Self-Hosted Gogs server.
908-
migrate.onedev.description = Migrating data from code.onedev.io or Self-Hosted OneDev server.
903+
migrate.github.description = Migrate data from github.com or other Github instances.
904+
migrate.git.description = Migrate a repository only from any Git service.
905+
migrate.gitlab.description = Migrate data from gitlab.com or other GitLab instances.
906+
migrate.gitea.description = Migrate data from gitea.com or other Gitea instances.
907+
migrate.gogs.description = Migrate data from notabug.org or other Gogs instances.
908+
migrate.onedev.description = Migrate data from code.onedev.io or other OneDev instances.
909909
migrate.migrating_git = Migrating Git Data
910910
migrate.migrating_topics = Migrating Topics
911911
migrate.migrating_milestones = Migrating Milestones

options/locale/locale_pt-BR.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ use_template=Usar este modelo
707707
clone_in_vsc=Clonar no VS Code
708708
download_zip=Baixar ZIP
709709
download_tar=Baixar TAR.GZ
710+
download_bundle=Baixar PACOTE
710711
generate_repo=Gerar repositório
711712
generate_from=Gerar de
712713
repo_desc=Descrição

options/locale/locale_pt-PT.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ use_template=Usar este modelo
771771
clone_in_vsc=Clonar no VS Code
772772
download_zip=Descarregar ZIP
773773
download_tar=Descarregar TAR.GZ
774+
download_bundle=Descarregar PACOTE
774775
generate_repo=Gerar repositório
775776
generate_from=Gerar a partir de
776777
repo_desc=Descrição

routers/web/user/oauth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ func AccessTokenOAuth(ctx *context.Context) {
546546

547547
signingKey := oauth2.DefaultSigningKey
548548
if signingKey.IsSymmetric() {
549-
clientKey, err := oauth2.CreateJWTSingingKey(signingKey.SigningMethod().Alg(), []byte(form.ClientSecret))
549+
clientKey, err := oauth2.CreateJWTSigningKey(signingKey.SigningMethod().Alg(), []byte(form.ClientSecret))
550550
if err != nil {
551551
handleAccessTokenError(ctx, AccessTokenError{
552552
ErrorCode: AccessTokenErrorCodeInvalidRequest,

routers/web/user/oauth_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
)
1616

1717
func createAndParseToken(t *testing.T, grant *models.OAuth2Grant) *oauth2.OIDCToken {
18-
signingKey, err := oauth2.CreateJWTSingingKey("HS256", make([]byte, 32))
18+
signingKey, err := oauth2.CreateJWTSigningKey("HS256", make([]byte, 32))
1919
assert.NoError(t, err)
2020
assert.NotNil(t, signingKey)
2121
oauth2.DefaultSigningKey = signingKey

services/auth/source/oauth2/jwtsigningkey.go

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package oauth2
66

77
import (
88
"crypto/ecdsa"
9+
"crypto/ed25519"
910
"crypto/elliptic"
1011
"crypto/rand"
1112
"crypto/rsa"
@@ -129,6 +130,57 @@ func (key rsaSingingKey) PreProcessToken(token *jwt.Token) {
129130
token.Header["kid"] = key.id
130131
}
131132

133+
type eddsaSigningKey struct {
134+
signingMethod jwt.SigningMethod
135+
key ed25519.PrivateKey
136+
id string
137+
}
138+
139+
func newEdDSASingingKey(signingMethod jwt.SigningMethod, key ed25519.PrivateKey) (eddsaSigningKey, error) {
140+
kid, err := createPublicKeyFingerprint(key.Public().(ed25519.PublicKey))
141+
if err != nil {
142+
return eddsaSigningKey{}, err
143+
}
144+
145+
return eddsaSigningKey{
146+
signingMethod,
147+
key,
148+
base64.RawURLEncoding.EncodeToString(kid),
149+
}, nil
150+
}
151+
152+
func (key eddsaSigningKey) IsSymmetric() bool {
153+
return false
154+
}
155+
156+
func (key eddsaSigningKey) SigningMethod() jwt.SigningMethod {
157+
return key.signingMethod
158+
}
159+
160+
func (key eddsaSigningKey) SignKey() interface{} {
161+
return key.key
162+
}
163+
164+
func (key eddsaSigningKey) VerifyKey() interface{} {
165+
return key.key.Public()
166+
}
167+
168+
func (key eddsaSigningKey) ToJWK() (map[string]string, error) {
169+
pubKey := key.key.Public().(ed25519.PublicKey)
170+
171+
return map[string]string{
172+
"alg": key.SigningMethod().Alg(),
173+
"kid": key.id,
174+
"kty": "OKP",
175+
"crv": "Ed25519",
176+
"x": base64.RawURLEncoding.EncodeToString(pubKey),
177+
}, nil
178+
}
179+
180+
func (key eddsaSigningKey) PreProcessToken(token *jwt.Token) {
181+
token.Header["kid"] = key.id
182+
}
183+
132184
type ecdsaSingingKey struct {
133185
signingMethod jwt.SigningMethod
134186
key *ecdsa.PrivateKey
@@ -194,8 +246,8 @@ func createPublicKeyFingerprint(key interface{}) ([]byte, error) {
194246
return checksum[:], nil
195247
}
196248

197-
// CreateJWTSingingKey creates a signing key from an algorithm / key pair.
198-
func CreateJWTSingingKey(algorithm string, key interface{}) (JWTSigningKey, error) {
249+
// CreateJWTSigningKey creates a signing key from an algorithm / key pair.
250+
func CreateJWTSigningKey(algorithm string, key interface{}) (JWTSigningKey, error) {
199251
var signingMethod jwt.SigningMethod
200252
switch algorithm {
201253
case "HS256":
@@ -218,11 +270,19 @@ func CreateJWTSingingKey(algorithm string, key interface{}) (JWTSigningKey, erro
218270
signingMethod = jwt.SigningMethodES384
219271
case "ES512":
220272
signingMethod = jwt.SigningMethodES512
273+
case "EdDSA":
274+
signingMethod = jwt.SigningMethodEdDSA
221275
default:
222276
return nil, ErrInvalidAlgorithmType{algorithm}
223277
}
224278

225279
switch signingMethod.(type) {
280+
case *jwt.SigningMethodEd25519:
281+
privateKey, ok := key.(ed25519.PrivateKey)
282+
if !ok {
283+
return nil, jwt.ErrInvalidKeyType
284+
}
285+
return newEdDSASingingKey(signingMethod, privateKey)
226286
case *jwt.SigningMethodECDSA:
227287
privateKey, ok := key.(*ecdsa.PrivateKey)
228288
if !ok {
@@ -271,17 +331,19 @@ func InitSigningKey() error {
271331
case "ES384":
272332
fallthrough
273333
case "ES512":
334+
fallthrough
335+
case "EdDSA":
274336
key, err = loadOrCreateAsymmetricKey()
275337

276338
default:
277339
return ErrInvalidAlgorithmType{setting.OAuth2.JWTSigningAlgorithm}
278340
}
279341

280342
if err != nil {
281-
return fmt.Errorf("Error while loading or creating symmetric key: %v", err)
343+
return fmt.Errorf("Error while loading or creating JWT key: %v", err)
282344
}
283345

284-
signingKey, err := CreateJWTSingingKey(setting.OAuth2.JWTSigningAlgorithm, key)
346+
signingKey, err := CreateJWTSigningKey(setting.OAuth2.JWTSigningAlgorithm, key)
285347
if err != nil {
286348
return err
287349
}
@@ -324,10 +386,15 @@ func loadOrCreateAsymmetricKey() (interface{}, error) {
324386
if !isExist {
325387
err := func() error {
326388
key, err := func() (interface{}, error) {
327-
if strings.HasPrefix(setting.OAuth2.JWTSigningAlgorithm, "RS") {
389+
switch {
390+
case strings.HasPrefix(setting.OAuth2.JWTSigningAlgorithm, "RS"):
328391
return rsa.GenerateKey(rand.Reader, 4096)
392+
case setting.OAuth2.JWTSigningAlgorithm == "EdDSA":
393+
_, pk, err := ed25519.GenerateKey(rand.Reader)
394+
return pk, err
395+
default:
396+
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
329397
}
330-
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
331398
}()
332399
if err != nil {
333400
return err

templates/repo/migrate/gitea.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
<label></label>
5555
<div class="ui checkbox">
5656
<input name="pull_requests" type="checkbox" {{if .pull_requests}} checked{{end}}>
57-
<label>{{.i18n.Tr "repo.migrate_items_merge_requests" | Safe}}</label>
57+
<label>{{.i18n.Tr "repo.migrate_items_pullrequests" | Safe}}</label>
5858
</div>
5959
<div class="ui checkbox">
6060
<input name="releases" type="checkbox" {{if .releases}} checked{{end}}>

templates/user/dashboard/feeds.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
</span>
100100
</li>
101101
{{end}}
102-
{{if and (gt (len $push.Commits) 1) $push.CompareURL}}<li><a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{$.i18n.Tr "action.compare_commits" (len $push.Commits)}} »</a></li>{{end}}
102+
{{if and (gt $push.Len 1) $push.CompareURL}}<li><a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{$.i18n.Tr "action.compare_commits" $push.Len}} »</a></li>{{end}}
103103
</ul>
104104
</div>
105105
{{else if eq .GetOpType 6}}

web_src/js/components/ContextPopup.vue

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ import {SvgIcon} from '../svg.js';
2424
2525
const {AppSubUrl} = window.config;
2626
27+
// NOTE: see models/issue_label.go for similar implementation
28+
const srgbToLinear = (color) => {
29+
color /= 255;
30+
if (color <= 0.04045) {
31+
return color / 12.92;
32+
}
33+
return ((color + 0.055) / 1.055) ** 2.4;
34+
};
35+
const luminance = (colorString) => {
36+
const r = srgbToLinear(parseInt(colorString.substring(0, 2), 16));
37+
const g = srgbToLinear(parseInt(colorString.substring(2, 4), 16));
38+
const b = srgbToLinear(parseInt(colorString.substring(4, 6), 16));
39+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
40+
};
41+
const luminanceThreshold = 0.179;
42+
2743
export default {
2844
name: 'ContextPopup',
2945
@@ -74,14 +90,13 @@ export default {
7490
7591
labels() {
7692
return this.issue.labels.map((label) => {
77-
const red = parseInt(label.color.substring(0, 2), 16);
78-
const green = parseInt(label.color.substring(2, 4), 16);
79-
const blue = parseInt(label.color.substring(4, 6), 16);
80-
let color = '#ffffff';
81-
if ((red * 0.299 + green * 0.587 + blue * 0.114) > 125) {
82-
color = '#000000';
93+
let textColor;
94+
if (luminance(label.color) < luminanceThreshold) {
95+
textColor = '#ffffff';
96+
} else {
97+
textColor = '#000000';
8398
}
84-
return {name: label.name, color: `#${label.color}`, textColor: color};
99+
return {name: label.name, color: `#${label.color}`, textColor};
85100
});
86101
}
87102
},

0 commit comments

Comments
 (0)