mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-04-21 07:16:41 +02:00
Merge branch 'forgejo' into landingpagedetails
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
This commit is contained in:
commit
20c03184be
44 changed files with 4415 additions and 1056 deletions
|
@ -28,7 +28,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: data.forgejo.org/renovate/renovate:39.164.1
|
||||
image: data.forgejo.org/renovate/renovate:39.171.2
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
13
Makefile
13
Makefile
|
@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour
|
|||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.29.0 # renovate: datasource=go
|
||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.1 # renovate: datasource=go
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.164.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.171.2 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
|
||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||
|
@ -127,6 +127,11 @@ FORGEJO_VERSION_API ?= ${FORGEJO_VERSION}
|
|||
show-version-api:
|
||||
@echo ${FORGEJO_VERSION_API}
|
||||
|
||||
# Strip binaries by default to reduce size, allow overriding for debugging
|
||||
STRIP ?= 1
|
||||
ifeq ($(STRIP),1)
|
||||
LDFLAGS := $(LDFLAGS) -s -w
|
||||
endif
|
||||
LDFLAGS := $(LDFLAGS) -X "main.ReleaseVersion=$(RELEASE_VERSION)" -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(FORGEJO_VERSION)" -X "main.Tags=$(TAGS)" -X "main.ForgejoVersion=$(FORGEJO_VERSION_API)"
|
||||
|
||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||
|
@ -827,7 +832,7 @@ check: test
|
|||
|
||||
.PHONY: install $(TAGS_PREREQ)
|
||||
install: $(wildcard *.go)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '$(LDFLAGS)'
|
||||
|
||||
.PHONY: build
|
||||
build: frontend backend
|
||||
|
@ -855,13 +860,13 @@ merge-locales:
|
|||
@echo "NOT NEEDED: THIS IS A NOOP AS OF Forgejo 7.0 BUT KEPT FOR BACKWARD COMPATIBILITY"
|
||||
|
||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $@
|
||||
|
||||
forgejo: $(EXECUTABLE)
|
||||
ln -f $(EXECUTABLE) forgejo
|
||||
|
||||
static-executable: $(GO_SOURCES) $(TAGS_PREREQ)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -o $(EXECUTABLE)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -o $(EXECUTABLE)
|
||||
|
||||
.PHONY: release
|
||||
release: frontend generate release-linux release-copy release-compress vendor release-sources release-check
|
||||
|
|
|
@ -219,8 +219,13 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
|
|||
return "", 0, fmt.Errorf("ParsePublicKey: %w", err)
|
||||
}
|
||||
|
||||
pkeyType := pkey.Type()
|
||||
if certPkey, ok := pkey.(*ssh.Certificate); ok {
|
||||
pkeyType = certPkey.Key.Type()
|
||||
}
|
||||
|
||||
// The ssh library can parse the key, so next we find out what key exactly we have.
|
||||
switch pkey.Type() {
|
||||
switch pkeyType {
|
||||
case ssh.KeyAlgoDSA:
|
||||
rawPub := struct {
|
||||
Name string
|
||||
|
|
|
@ -35,6 +35,7 @@ func Test_SSHParsePublicKey(t *testing.T) {
|
|||
{"ecdsa-384", false, "ecdsa", 384, "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBINmioV+XRX1Fm9Qk2ehHXJ2tfVxW30ypUWZw670Zyq5GQfBAH6xjygRsJ5wWsHXBsGYgFUXIHvMKVAG1tpw7s6ax9oA+dJOJ7tj+vhn8joFqT+sg3LYHgZkHrfqryRasQ== nocomment"},
|
||||
{"ecdsa-sk", true, "ecdsa-sk", 256, "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGXEEzWmm1dxb+57RoK5KVCL0w2eNv9cqJX2AGGVlkFsVDhOXHzsadS3LTK4VlEbbrDMJdoti9yM8vclA8IeRacAAAAEc3NoOg== nocomment"},
|
||||
{"ed25519-sk", true, "ed25519-sk", 256, "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIE7kM1R02+4ertDKGKEDcKG0s+2vyDDcIvceJ0Gqv5f1AAAABHNzaDo= nocomment"},
|
||||
{"ed25519-cert-v01", true, "ed25519", 256, "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIAlIAPlEj0mYQzQo8Ks0Nm/Ct8ceNkyJSf4DLuF5l7+5AAAAIEuWAoaBo2tT29/oMNnoDfdAPRCIdM2RGapKUhY4nDfLRgPQwfnRoc0AAAABAAAAcHZhdWx0LW9pZGMtNmRhYjdiZDgtNDg5YS00MDFkLTg3ZmItNjdjNTlhMDZkZDkxLTNjNTk2M2YyMGRmMDM3MDkyMzc1YmNiYmNiNzkxY2EyZWIxM2I0NGZhMzc2NTcwMWI0MjMwODU0MWFmNjhkNTgAAAALAAAAB2Zvcmdlam8AAAAAZ6/RUQAAAABn115vAAAAAAAAAAAAAAAAAAACFwAAAAdzc2gtcnNhAAAAAwEAAQAAAgEAySnM/TvD117GyKgOgMatDB2t+fCHORFaWVmH5SaadAzNJ2DfDAauRSLfnim1xdgAOMTzsPEEHH47zyYMjE85o2AiJxrfUBMw3O/7AbNc6+HyLr/txH4+vD9tWQknKnpVWM+3Z9wiHDcOdKRoXCmFZKJH1vxs16GNWjwbrfNiimv7Oi0fadgvTDKX603gpLTuVDXqs9eQFLCONptei86JYBAJqaHvg51k8YUCKt9WFqKAj7BJUWmrDvhv5VFMOsnZieJjqxkoxnpsQNlXfPzxK0vIpJofbYfWwscv/g9WZypHwO1ZR2PqzKm99YrSdr8w5256l0f44vsF0NSP0N7bDQEfYYnRGj8zWTYCBFD+uYF7AxIeaRUpZoTQO8MvCHOLMIDinNgEeCUvNA2v9zHl4BGq+PQjzUKAgJiKj0MZeiCDAmQ22g83ggQlB6BOrBb1fNa/S1cmTbGHQ2oAN358aqkmHVCBhPOyA2Rf65D2M2vzDlUdOsNDUIWAHk7GbwSNGDgcYfTWqtR5fTzp2MJovMh1dDUDXjOvojbhzjJtSy9+rzUYIv18aXdOitzVBgPMWdeVCZFZv4OKF+5MiqxQvedUvfiSjsdxZWLxyT1CJ88G3MzxNMS/Djm86T8h/Oa55bdvFtqpsLfvpIqq0pnXq1V/vF2j1MWwRB5z5Xh/HtEAAAIUAAAADHJzYS1zaGEyLTI1NgAAAgB2I2gzqemQl8/ETxtakALlm/2BpUcbhADcFWuoH6BCPnWHuTSwf3OayM6KXv1PQfL3YFRoi9Afrp8kVFL6DePsmKH+0BUEMz71sZ7v1ty7pwfzibItGnpTbQXhzbEiNYAFoz77rl7oaXF7pV6JNZhj3DVAB5gVA2oN5KRNVxijz+6uyuFJEw1HIl1C7GworvGwZcN7BThTEh3i72/Vntejy9Z8uGVjSFjS0rjRo2oXK1LKN0rVt66p3TmCWHouLkVnOTk0qrhLGlL2HVyo24OYHbkAAObD9b6aMDYlmluk6NsaiTKsSTsvMrbIbjtFQlh7nNyoPhZ0VMwaT1l10pDQ5uxWWZjKGIkz4xM1ZfpBszjJNPo+ivYQnTSjj9LwkbLAT9a/5LawSj80TGcLEMO+0eyPdJsP0wYmOVRFAZeRiBgwb3HrzcF6Wqr8icj1EjYkKSy9YFHGTnFBGknpdh3HGwghRXrCUwAnSM76db9pv4/qowT8LthtJ3dY5Epe0OJ1Tqm+q8bkGH4gB+7uqLSqM5pIHSKLp7lfHQBt1J6xa7H2saiweaWjU+QGTgQ2Lg+uUC5DXJrmm60CeFJ4BoGhUenDlgijbQpjH/l6330PbwefgjWtUK/pqaEA4lCoPyvJ+eF2DbYfPiAIBAFQnhVJJae4AH+XoCt29nb2j30ztg== nocomment"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
full_name: ' < U<se>r Tw<o > >< '
|
||||
email: user2@example.com
|
||||
keep_email_private: true
|
||||
keep_pronouns_private: true
|
||||
email_notifications_preference: enabled
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
|
@ -350,6 +351,7 @@
|
|||
full_name: User Ten
|
||||
email: user10@example.com
|
||||
keep_email_private: false
|
||||
keep_pronouns_private: true
|
||||
email_notifications_preference: enabled
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
|
|
|
@ -58,40 +58,42 @@ var migrations = []*Migration{
|
|||
NewMigration("Add the `apply_to_admins` column to the `protected_branch` table", forgejo_v1_22.AddApplyToAdminsSetting),
|
||||
// v9 -> v10
|
||||
NewMigration("Add pronouns to user", forgejo_v1_22.AddPronounsToUser),
|
||||
// v11 -> v12
|
||||
// v10 -> v11
|
||||
NewMigration("Add the `created` column to the `issue` table", forgejo_v1_22.AddCreatedToIssue),
|
||||
// v12 -> v13
|
||||
// v11 -> v12
|
||||
NewMigration("Add repo_archive_download_count table", forgejo_v1_22.AddRepoArchiveDownloadCount),
|
||||
// v13 -> v14
|
||||
// v12 -> v13
|
||||
NewMigration("Add `hide_archive_links` column to `release` table", AddHideArchiveLinksToRelease),
|
||||
// v14 -> v15
|
||||
// v13 -> v14
|
||||
NewMigration("Remove Gitea-specific columns from the repository and badge tables", RemoveGiteaSpecificColumnsFromRepositoryAndBadge),
|
||||
// v15 -> v16
|
||||
// v14 -> v15
|
||||
NewMigration("Create the `federation_host` table", CreateFederationHostTable),
|
||||
// v16 -> v17
|
||||
// v15 -> v16
|
||||
NewMigration("Create the `federated_user` table", CreateFederatedUserTable),
|
||||
// v17 -> v18
|
||||
// v16 -> v17
|
||||
NewMigration("Add `normalized_federated_uri` column to `user` table", AddNormalizedFederatedURIToUser),
|
||||
// v18 -> v19
|
||||
// v17 -> v18
|
||||
NewMigration("Create the `following_repo` table", CreateFollowingRepoTable),
|
||||
// v19 -> v20
|
||||
// v18 -> v19
|
||||
NewMigration("Add external_url to attachment table", AddExternalURLColumnToAttachmentTable),
|
||||
// v20 -> v21
|
||||
// v19 -> v20
|
||||
NewMigration("Creating Quota-related tables", CreateQuotaTables),
|
||||
// v21 -> v22
|
||||
// v20 -> v21
|
||||
NewMigration("Add SSH keypair to `pull_mirror` table", AddSSHKeypairToPushMirror),
|
||||
// v22 -> v23
|
||||
// v21 -> v22
|
||||
NewMigration("Add `legacy` to `web_authn_credential` table", AddLegacyToWebAuthnCredential),
|
||||
// v23 -> v24
|
||||
// v22 -> v23
|
||||
NewMigration("Add `delete_branch_after_merge` to `auto_merge` table", AddDeleteBranchAfterMergeToAutoMerge),
|
||||
// v24 -> v25
|
||||
// v23 -> v24
|
||||
NewMigration("Add `purpose` column to `forgejo_auth_token` table", AddPurposeToForgejoAuthToken),
|
||||
// v25 -> v26
|
||||
// v24 -> v25
|
||||
NewMigration("Migrate `secret` column to store keying material", MigrateTwoFactorToKeying),
|
||||
// v26 -> v27
|
||||
// v25 -> v26
|
||||
NewMigration("Add `hash_blake2b` column to `package_blob` table", AddHashBlake2bToPackageBlob),
|
||||
// v27 -> v28
|
||||
// v26 -> v27
|
||||
NewMigration("Add `created_unix` column to `user_redirect` table", AddCreatedUnixToRedirect),
|
||||
// v27 -> v28
|
||||
NewMigration("Add pronoun privacy settings to user", AddHidePronounsOptionToUser),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||
|
|
15
models/forgejo_migrations/v28.go
Normal file
15
models/forgejo_migrations/v28.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
func AddHidePronounsOptionToUser(x *xorm.Engine) error {
|
||||
type User struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
KeepPronounsPrivate bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
return x.Sync(&User{})
|
||||
}
|
|
@ -154,6 +154,7 @@ type User struct {
|
|||
DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
|
||||
Theme string `xorm:"NOT NULL DEFAULT ''"`
|
||||
KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"`
|
||||
KeepPronounsPrivate bool `xorm:"NOT NULL DEFAULT false"`
|
||||
EnableRepoUnitHints bool `xorm:"NOT NULL DEFAULT true"`
|
||||
}
|
||||
|
||||
|
@ -500,6 +501,16 @@ func (u *User) GetCompleteName() string {
|
|||
return u.Name
|
||||
}
|
||||
|
||||
// GetPronouns returns an empty string, if the user has set to keep his
|
||||
// pronouns private from non-logged in users, otherwise the pronouns
|
||||
// are returned.
|
||||
func (u *User) GetPronouns(signed bool) string {
|
||||
if u.KeepPronounsPrivate && !signed {
|
||||
return ""
|
||||
}
|
||||
return u.Pronouns
|
||||
}
|
||||
|
||||
func gitSafeName(name string) string {
|
||||
return strings.TrimSpace(strings.NewReplacer("\n", "", "<", "", ">", "").Replace(name))
|
||||
}
|
||||
|
@ -854,48 +865,46 @@ func countUsers(ctx context.Context, opts *CountUserFilter) int64 {
|
|||
|
||||
// VerifyUserActiveCode verifies that the code is valid for the given purpose for this user.
|
||||
// If delete is specified, the token will be deleted.
|
||||
func VerifyUserAuthorizationToken(ctx context.Context, code string, purpose auth.AuthorizationPurpose, delete bool) (*User, error) {
|
||||
func VerifyUserAuthorizationToken(ctx context.Context, code string, purpose auth.AuthorizationPurpose) (user *User, deleteToken func() error, err error) {
|
||||
lookupKey, validator, found := strings.Cut(code, ":")
|
||||
if !found {
|
||||
return nil, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
authToken, err := auth.FindAuthToken(ctx, lookupKey, purpose)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
return nil, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if authToken.IsExpired() {
|
||||
return nil, auth.DeleteAuthToken(ctx, authToken)
|
||||
return nil, nil, auth.DeleteAuthToken(ctx, authToken)
|
||||
}
|
||||
|
||||
rawValidator, err := hex.DecodeString(validator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if subtle.ConstantTimeCompare([]byte(authToken.HashedValidator), []byte(auth.HashValidator(rawValidator))) == 0 {
|
||||
return nil, errors.New("validator doesn't match")
|
||||
return nil, nil, errors.New("validator doesn't match")
|
||||
}
|
||||
|
||||
u, err := GetUserByID(ctx, authToken.UID)
|
||||
if err != nil {
|
||||
if IsErrUserNotExist(err) {
|
||||
return nil, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if delete {
|
||||
if err := auth.DeleteAuthToken(ctx, authToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deleteToken = func() error {
|
||||
return auth.DeleteAuthToken(ctx, authToken)
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return u, deleteToken, nil
|
||||
}
|
||||
|
||||
// ValidateUser check if user is valid to insert / update into database
|
||||
|
|
|
@ -756,13 +756,13 @@ func TestVerifyUserAuthorizationToken(t *testing.T) {
|
|||
assert.True(t, ok)
|
||||
|
||||
t.Run("Wrong purpose", func(t *testing.T) {
|
||||
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.PasswordReset, false)
|
||||
u, _, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.PasswordReset)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, u)
|
||||
})
|
||||
|
||||
t.Run("No delete", func(t *testing.T) {
|
||||
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation, false)
|
||||
u, _, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, user.ID, u.ID)
|
||||
|
||||
|
@ -772,9 +772,10 @@ func TestVerifyUserAuthorizationToken(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Delete", func(t *testing.T) {
|
||||
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation, true)
|
||||
u, deleteToken, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, user.ID, u.ID)
|
||||
require.NoError(t, deleteToken())
|
||||
|
||||
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
||||
require.ErrorIs(t, err, util.ErrNotExist)
|
||||
|
@ -795,3 +796,42 @@ func TestGetInactiveUsers(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
require.Empty(t, users)
|
||||
}
|
||||
|
||||
func TestPronounsPrivacy(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
t.Run("EmptyPronounsIfNoneSet", func(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
user.Pronouns = ""
|
||||
user.KeepPronounsPrivate = false
|
||||
|
||||
assert.Equal(t, "", user.GetPronouns(false))
|
||||
})
|
||||
t.Run("EmptyPronounsIfSetButPrivateAndNotLoggedIn", func(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
user.Pronouns = "any"
|
||||
user.KeepPronounsPrivate = true
|
||||
|
||||
assert.Equal(t, "", user.GetPronouns(false))
|
||||
})
|
||||
t.Run("ReturnPronounsIfSetAndNotPrivateAndNotLoggedIn", func(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
user.Pronouns = "any"
|
||||
user.KeepPronounsPrivate = false
|
||||
|
||||
assert.Equal(t, "any", user.GetPronouns(false))
|
||||
})
|
||||
t.Run("ReturnPronounsIfSetAndPrivateAndLoggedIn", func(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
user.Pronouns = "any"
|
||||
user.KeepPronounsPrivate = false
|
||||
|
||||
assert.Equal(t, "any", user.GetPronouns(true))
|
||||
})
|
||||
t.Run("ReturnPronounsIfSetAndNotPrivateAndLoggedIn", func(t *testing.T) {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
user.Pronouns = "any"
|
||||
user.KeepPronounsPrivate = true
|
||||
|
||||
assert.Equal(t, "any", user.GetPronouns(true))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repository
|
||||
|
@ -107,6 +108,9 @@ func getLicensePlaceholder(name string) *licensePlaceholder {
|
|||
}
|
||||
|
||||
// Other special placeholders can be added here.
|
||||
} else if name == "BSD-4-Clause" {
|
||||
ret.Owner = append(ret.Owner, "COPYRIGHT HOLDER")
|
||||
ret.Owner = append(ret.Owner, "the organization")
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repository
|
||||
|
@ -170,6 +171,31 @@ Copyright (C) 2023 by Gitea teabot@gitea.io
|
|||
...
|
||||
|
||||
... THE AUTHOR BE LIABLE FOR ...
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "BSD-4-Clause",
|
||||
args: args{
|
||||
name: "BSD-4-Clause",
|
||||
values: &LicenseValues{Year: "2025", Owner: "Forgejo", Email: "hello@forgejo.org", Repo: "forgejo"},
|
||||
origin: `
|
||||
Copyright (c) <year> <owner>. All rights reserved.
|
||||
|
||||
... includes software developed by the organization.
|
||||
|
||||
... Neither the name of the copyright holder nor
|
||||
|
||||
... PROVIDED BY COPYRIGHT HOLDER "AS IS" ... NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE ...
|
||||
`,
|
||||
},
|
||||
want: `
|
||||
Copyright (c) 2025 Forgejo. All rights reserved.
|
||||
|
||||
... includes software developed by Forgejo.
|
||||
|
||||
... Neither the name of the copyright holder nor
|
||||
|
||||
... PROVIDED BY Forgejo "AS IS" ... NO EVENT SHALL Forgejo BE LIABLE ...
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ type UserSettings struct {
|
|||
EnableRepoUnitHints bool `json:"enable_repo_unit_hints"`
|
||||
// Privacy
|
||||
HideEmail bool `json:"hide_email"`
|
||||
HidePronouns bool `json:"hide_pronouns"`
|
||||
HideActivity bool `json:"hide_activity"`
|
||||
}
|
||||
|
||||
|
@ -101,6 +102,7 @@ type UserSettingsOptions struct {
|
|||
EnableRepoUnitHints *bool `json:"enable_repo_unit_hints"`
|
||||
// Privacy
|
||||
HideEmail *bool `json:"hide_email"`
|
||||
HidePronouns *bool `json:"hide_pronouns"`
|
||||
HideActivity *bool `json:"hide_activity"`
|
||||
}
|
||||
|
||||
|
|
|
@ -853,6 +853,8 @@ email_preference_set_success = Email preference has been set successfully.
|
|||
add_openid_success = The new OpenID address has been added.
|
||||
keep_email_private = Hide email address
|
||||
keep_email_private_popup = Your email address will not be shown on your profile and will not be the default for commits made via the web interface, like file uploads, edits, and merge commits. Instead, a special address %s can be used to link commits to your account. This option will not affect existing commits.
|
||||
keep_pronouns_private = Only show pronouns to authenticated users
|
||||
keep_pronouns_private.description = This will hide your pronouns from visitors that are not logged in.
|
||||
openid_desc = OpenID lets you delegate authentication to an external provider.
|
||||
|
||||
manage_ssh_keys = Manage SSH keys
|
||||
|
@ -3935,4 +3937,4 @@ filepreview.lines = Lines %[1]d to %[2]d in %[3]s
|
|||
filepreview.truncated = Preview has been truncated
|
||||
|
||||
[translation_meta]
|
||||
test = This is a test string. It is not displayed in Forgejo UI but is used for testing purposes. Feel free to enter "ok" to save time (or a fun fact of your choice) to hit that sweet 100% completion mark :)
|
||||
test = This is a test string. It is not displayed in Forgejo UI but is used for testing purposes. Feel free to enter "ok" to save time (or a fun fact of your choice) to hit that sweet 100% completion mark :)
|
||||
|
|
|
@ -134,6 +134,11 @@ new_repo.title = مخزن جدید
|
|||
new_migrate.title = مهاجرت جدید
|
||||
new_repo.link = مخزن جدید
|
||||
|
||||
filter = فیلتر
|
||||
filter.is_archived = بایگانی شده
|
||||
filter.public = عمومی
|
||||
filter.private = خصوصی
|
||||
|
||||
[aria]
|
||||
|
||||
[heatmap]
|
||||
|
@ -1987,6 +1992,8 @@ error.csv.too_large=نمی توان این فایل را رندر کرد زیر
|
|||
error.csv.unexpected=نمی توان این فایل را رندر کرد زیرا حاوی یک کاراکتر غیرمنتظره در خط %d و ستون %d است.
|
||||
error.csv.invalid_field_count=نمی توان این فایل را رندر کرد زیرا تعداد فیلدهای آن در خط %d اشتباه است.
|
||||
|
||||
milestones.filter_sort.name = نام
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -2540,6 +2547,9 @@ notices.op=عملیات.
|
|||
notices.delete_success=گزارش سیستم حذف شده است.
|
||||
|
||||
|
||||
config_summary = چکیده
|
||||
config_settings = تنظيمات
|
||||
|
||||
[action]
|
||||
create_repo=مخزن ایجاد شده <a href="%s"> %s</a>
|
||||
rename_repo=مخزن تغییر نام داد از <code>%[1]s</code> به <a href="%[2]s">%[3]s</a>
|
||||
|
@ -2669,3 +2679,5 @@ executable_file = فایل اجرایی
|
|||
normal_file = فایل معمولی
|
||||
changed_filemode = %[1] ها ← %[2] ها
|
||||
directory = پوشه
|
||||
|
||||
[search]
|
||||
|
|
2996
options/locale/locale_ga-IE.ini
Normal file
2996
options/locale/locale_ga-IE.ini
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1270,6 +1270,8 @@ topic.done=Kész
|
|||
|
||||
|
||||
|
||||
milestones.filter_sort.name = Név
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -1684,6 +1686,9 @@ config.cache_item_ttl = Gyorsítótárelem TTL értéke
|
|||
config.app_data_path = Alkalmazásadatok elérési útja
|
||||
|
||||
|
||||
config_summary = Összefoglaló
|
||||
config_settings = Beállítások
|
||||
|
||||
[action]
|
||||
create_repo=létrehozott tárolót: <a href="%s"> %s</a>
|
||||
rename_repo=átnevezte a(z) <code>%[1]s</code> tárolót <a href="%[2]s">%[3]s</a>-ra/re
|
||||
|
|
|
@ -84,15 +84,93 @@ concept_code_repository=Repositori
|
|||
|
||||
name=Nama
|
||||
|
||||
re_type = Konfirmasi Kata Sandi
|
||||
webauthn_insert_key = Masukkan kunci keamanan anda
|
||||
webauthn_sign_in = Tekan tombol pada kunci keamanan Anda. Jika kunci keamanan Anda tidak memiliki tombol, masukkan kembali.
|
||||
webauthn_press_button = Silakan tekan tombol pada kunci keamanan Anda…
|
||||
webauthn_use_twofa = Gunakan kode dua faktor dari telepon Anda
|
||||
webauthn_error = Tidak dapat membaca kunci keamanan Anda.
|
||||
webauthn_unsupported_browser = Browser Anda saat ini tidak mendukung WebAuthn.
|
||||
webauthn_error_unknown = Terdapat kesalahan yang tidak diketahui. Mohon coba lagi.
|
||||
webauthn_error_insecure = `WebAuthn hanya mendukung koneksi aman. Untuk pengujian melalui HTTP, Anda dapat menggunakan "localhost" atau "127.0.0.1"`
|
||||
webauthn_error_unable_to_process = Server tidak dapat memproses permintaan Anda.
|
||||
webauthn_error_duplicated = Kunci keamanan tidak diperbolehkan untuk permintaan ini. Pastikan bahwa kunci ini belum terdaftar sebelumnya.
|
||||
webauthn_error_empty = Anda harus menetapkan nama untuk kunci ini.
|
||||
webauthn_error_timeout = Waktu habis sebelum kunci Anda dapat dibaca. Mohon muat ulang halaman ini dan coba lagi.
|
||||
new_project = Proyek Baru
|
||||
new_project_column = Kolom Baru
|
||||
ok = Oke
|
||||
retry = Coba lagi
|
||||
rerun = Jalankan ulang
|
||||
rerun_all = Jalankan ulang semua job
|
||||
remove_label_str = `Hapus item "%s"`
|
||||
view = Tampilan
|
||||
test = Pengujian
|
||||
locked = Terkunci
|
||||
copy = Salin
|
||||
copy_url = Salin URL
|
||||
copy_hash = Salin hash
|
||||
copy_content = Salin konten
|
||||
copy_branch = Salin nama branch
|
||||
copy_success = Tersalin!
|
||||
copy_error = Gagal menyalin
|
||||
copy_type_unsupported = Tipe berkas ini tidak dapat disalin
|
||||
error = Gangguan
|
||||
error404 = Halaman yang akan kamu akses <strong>tidak dapat ditemukan</strong> atau <strong>kamu tidak memiliki akses </strong> untuk melihatnya.
|
||||
go_back = Kembali
|
||||
invalid_data = Data invalid: %v
|
||||
never = Tidak Pernah
|
||||
unknown = Tidak diketahui
|
||||
rss_feed = Umpan Berita
|
||||
pin = Sematkan
|
||||
unpin = Lepas sematan
|
||||
artifacts = Artefak
|
||||
archived = Diarsipkan
|
||||
concept_system_global = Global
|
||||
concept_user_individual = Perorangan
|
||||
show_full_screen = Tampilkan layar penuh
|
||||
download_logs = Unduh Logs
|
||||
confirm_delete_selected = Konfirmasi untuk menghapus semua item yang dipilih?
|
||||
value = Nilai
|
||||
filter = Saring
|
||||
filter.is_archived = Diarsipkan
|
||||
filter.not_archived = Tidak Diarsipkan
|
||||
filter.public = Publik
|
||||
filter.private = Pribadi
|
||||
|
||||
[aria]
|
||||
navbar = Bar Navigasi
|
||||
footer = Footer
|
||||
footer.links = Tautan
|
||||
|
||||
[heatmap]
|
||||
number_of_contributions_in_the_last_12_months = %s Kontribusi pada 12 bulan terakhir
|
||||
less = Lebih sedikit
|
||||
more = Lebih banyak
|
||||
|
||||
[editor]
|
||||
buttons.heading.tooltip = Tambahkan heading
|
||||
buttons.bold.tooltip = Tambahkan teks Tebal
|
||||
buttons.italic.tooltip = Tambahkan teks Miring
|
||||
buttons.quote.tooltip = Kutip teks
|
||||
buttons.code.tooltip = Tambah Kode
|
||||
buttons.link.tooltip = Tambahkan tautan
|
||||
buttons.list.unordered.tooltip = Tambah daftar titik
|
||||
buttons.list.ordered.tooltip = Tambah daftar angka
|
||||
buttons.list.task.tooltip = Tambahkan daftar tugas
|
||||
buttons.mention.tooltip = Tandai pengguna atau tim
|
||||
buttons.ref.tooltip = Merujuk pada isu atau permintaan tarik
|
||||
buttons.switch_to_legacy.tooltip = Gunakan editor versi lama
|
||||
buttons.enable_monospace_font = Aktifkan font monospace
|
||||
buttons.disable_monospace_font = Non-Aktifkan font monospace
|
||||
|
||||
[filter]
|
||||
string.asc = A - Z
|
||||
string.desc = Z - A
|
||||
|
||||
[error]
|
||||
occurred = Terjadi kesalahan
|
||||
not_found = Target tidak dapat ditemukan.
|
||||
|
||||
[startpage]
|
||||
app_desc=Sebuah layanan hosting Git sendiri yang tanpa kesulitan
|
||||
|
@ -124,6 +202,9 @@ require_sign_in_view=Harus Login Untuk Melihat Halaman
|
|||
admin_password=Kata Sandi
|
||||
admin_email=Alamat Email
|
||||
|
||||
email_title = Pengaturan email
|
||||
smtp_from = Kirim Email Sebagai
|
||||
|
||||
[home]
|
||||
uname_holder=Nama Pengguna atau Alamat Surel
|
||||
password_holder=Kata Sandi
|
||||
|
@ -141,6 +222,8 @@ show_private=Pribadi
|
|||
|
||||
issues.in_your_repos=Dalam repositori anda
|
||||
|
||||
show_archived = Diarsipkan
|
||||
|
||||
[explore]
|
||||
repos=Repositori
|
||||
users=Pengguna
|
||||
|
@ -492,6 +575,8 @@ email_notifications.submit=Pasang Pengaturan Email
|
|||
|
||||
visibility.private=Pribadi
|
||||
|
||||
visibility.public = Publik
|
||||
|
||||
[repo]
|
||||
owner=Pemilik
|
||||
repo_name=Nama Repositori
|
||||
|
@ -955,6 +1040,12 @@ branch.deleted_by=Dihapus oleh %s
|
|||
|
||||
|
||||
|
||||
desc.public = Publik
|
||||
desc.archived = Diarsipkan
|
||||
commitstatus.error = Gangguan
|
||||
projects.new = Proyek Baru
|
||||
milestones.filter_sort.name = Nama
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -1009,6 +1100,8 @@ teams.delete_team_success=Tim sudah di hapus.
|
|||
teams.repositories=Tim repositori
|
||||
teams.search_repo_placeholder=Cari repositori…
|
||||
|
||||
settings.visibility.public = Publik
|
||||
|
||||
[admin]
|
||||
dashboard=Dasbor
|
||||
organizations=Organisasi
|
||||
|
@ -1267,6 +1360,9 @@ notices.op=Op.
|
|||
notices.delete_success=Laporan sistem telah dihapus.
|
||||
|
||||
|
||||
config_settings = Pengaturan
|
||||
users.list_status_filter.menu_text = Saring
|
||||
|
||||
[action]
|
||||
create_repo=repositori dibuat <a href="%s">%s</a>
|
||||
rename_repo=ganti nama gudang penyimpanan dari <code>%[1]s</code> ke <a href="%[2]s">%[3]s</a>
|
||||
|
@ -1342,6 +1438,56 @@ runs.commit=Memperbuat
|
|||
|
||||
|
||||
|
||||
runs.no_matching_online_runner_helper = Tidak ada runner online yang cocok dengan label: %s
|
||||
runs.actor = Aktor
|
||||
runs.status = Status
|
||||
runs.actors_no_select = Semua aktor
|
||||
runs.status_no_select = Semua status
|
||||
runs.no_results = Tidak ada hasil yang cocok.
|
||||
runs.no_workflows = Belum ada alur kerja.
|
||||
runs.no_runs = Alur kerja belum berjalan.
|
||||
runs.empty_commit_message = (pesan commit kosong)
|
||||
workflow.disable = Nonaktifkan Alur Kerja
|
||||
workflow.enable = Aktifkan Alur Kerja
|
||||
workflow.disabled = Alur kerja dinonaktifkan.
|
||||
need_approval_desc = Butuh persetujuan untuk menjalankan alur kerja untuk pull request fork.
|
||||
variables = Variabel
|
||||
variables.creation = Tambah Variabel
|
||||
variables.none = Belum ada variabel.
|
||||
variables.deletion = Hapus variabel
|
||||
variables.deletion.description = Menghapus variabel bersifat permanen dan tidak dapat dibatalkan. Lanjutkan?
|
||||
variables.description = Variabel akan diteruskan ke beberapa tindakan dan tidak dapat dibaca sebaliknya.
|
||||
variables.id_not_exist = Variabel dengan ID %d tidak ada.
|
||||
variables.edit = Edit Variabel
|
||||
variables.deletion.failed = Gagal menghapus variabel.
|
||||
variables.deletion.success = Variabel telah dihapus.
|
||||
variables.creation.failed = Gagal menambahkan variabel.
|
||||
variables.creation.success = Variabel "%s" telah ditambahkan.
|
||||
variables.update.failed = Gagal mengedit variabel.
|
||||
variables.update.success = Variabel telah diedit.
|
||||
|
||||
[projects]
|
||||
type-1.display_name = Proyek Individu
|
||||
type-2.display_name = Proyek Repositori
|
||||
type-3.display_name = Proyek Organisasi
|
||||
|
||||
[git.filemode]
|
||||
changed_filemode = %[1]s → %[2]s
|
||||
directory = Directory
|
||||
normal_file = Normal file
|
||||
executable_file = Executable file
|
||||
symbolic_link = Symbolic link
|
||||
submodule = Submodule
|
||||
|
||||
[search]
|
||||
search = Cari...
|
||||
type_tooltip = Tipe pencarian
|
||||
fuzzy_tooltip = Termasuk juga hasil yang mendekati kata pencarian
|
||||
exact_tooltip = Hanya menampilkan hasil yang cocok dengan istilah pencarian
|
||||
repo_kind = Cari repo...
|
||||
user_kind = Telusuri pengguna...
|
||||
org_kind = Cari organisasi...
|
||||
team_kind = Cari tim...
|
||||
code_kind = Cari kode...
|
||||
code_search_unavailable = Pencarian kode saat ini tidak tersedia. Silahkan hubungi administrator.
|
||||
branch_kind = Cari cabang...
|
||||
|
|
|
@ -114,6 +114,10 @@ value=Gildi
|
|||
sign_in_with_provider = Skrá inn með %s
|
||||
enable_javascript = Þessi síða krefst JavaScript.
|
||||
|
||||
filter = Sía
|
||||
filter.is_archived = Safnvistað
|
||||
filter.public = Opinbert
|
||||
|
||||
[aria]
|
||||
|
||||
[heatmap]
|
||||
|
@ -1118,6 +1122,8 @@ topic.done=Í lagi
|
|||
|
||||
|
||||
|
||||
milestones.filter_sort.name = Heiti
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -1287,6 +1293,9 @@ notices.type_2=Verkefni
|
|||
notices.desc=Lýsing
|
||||
|
||||
|
||||
config_summary = Yfirlit
|
||||
config_settings = Stillingar
|
||||
|
||||
[action]
|
||||
create_issue=`opnaði vandamál <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reopen_issue=`enduropnaði vandamál <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
|
@ -1371,3 +1380,5 @@ runs.commit=Framlag
|
|||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
[search]
|
||||
|
|
|
@ -167,6 +167,8 @@ new_org.link = 新しい組織
|
|||
test = テスト
|
||||
error413 = 割り当て量を使い切りしました。
|
||||
|
||||
copy_path = パスをコピー
|
||||
|
||||
[aria]
|
||||
navbar=ナビゲーションバー
|
||||
footer=フッター
|
||||
|
@ -3515,6 +3517,8 @@ config.app_slogan = インスタンスのスローガン
|
|||
config.cache_test = テストキャッシュ
|
||||
|
||||
|
||||
config.cache_test_failed = キャッシュの調査に失敗しました: %v.
|
||||
|
||||
[action]
|
||||
create_repo=がリポジトリ <a href="%s">%s</a> を作成しました
|
||||
rename_repo=がリポジトリ名を <code>%[1]s</code> から <a href="%[2]s">%[3]s</a> へ変更しました
|
||||
|
@ -3758,6 +3762,8 @@ rpm.repository.multiple_groups = このパッケージは複数のグループ
|
|||
owner.settings.cargo.rebuild.no_index = 再構築できません、インデックスが初期化されていません。
|
||||
npm.dependencies.bundle = バンドルされた依存関係
|
||||
|
||||
search_in_external_registry = %s で検索
|
||||
|
||||
[secrets]
|
||||
secrets=シークレット
|
||||
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
||||
|
@ -3875,11 +3881,15 @@ workflow.dispatch.invalid_input_type = 入力タイプ「%s」が無効です。
|
|||
workflow.dispatch.warn_input_limit = 最初の %d 個の入力のみを表示します。
|
||||
runs.no_job = ワークフローには少なくとも1つのジョブが含まれている必要があります
|
||||
|
||||
runs.expire_log_message = ログは古すぎるため消去されています。
|
||||
|
||||
[projects]
|
||||
type-1.display_name=個人プロジェクト
|
||||
type-2.display_name=リポジトリ プロジェクト
|
||||
type-3.display_name=組織プロジェクト
|
||||
|
||||
deleted.display_name = 削除されたプロジェクト
|
||||
|
||||
[git.filemode]
|
||||
changed_filemode=%[1]s → %[2]s
|
||||
directory=ディレクトリ
|
||||
|
|
|
@ -376,7 +376,7 @@ allow_password_change=사용자에게 비밀번호 변경을 요청 (권장됨)
|
|||
reset_password_mail_sent_prompt=확인 메일이 <b>%s</b>로 전송되었습니다. 받은 편지함으로 도착한 메일을 %s 안에 확인해서 비밀번호 찾기 절차를 완료하십시오.
|
||||
active_your_account=계정 활성화
|
||||
account_activated=계정이 활성화 되었습니다
|
||||
prohibit_login =
|
||||
prohibit_login =
|
||||
resent_limit_prompt=활성화를 위한 이메일을 이미 전송했습니다. 3분 내로 이메일을 받지 못한 경우 재시도해주세요.
|
||||
has_unconfirmed_mail=안녕하세요 %s, 이메일 주소(<b>%s</b>)가 확인되지 않았습니다. 확인 메일을 받으시지 못하겼거나 새로운 확인 메일이 필요하다면, 아래 버튼을 클릭해 재발송하실 수 있습니다.
|
||||
resend_mail=여기를 눌러 확인 메일 재전송
|
||||
|
@ -1425,6 +1425,8 @@ archive.title_date = 이 저장소는 %s에 보관처리되었습니다. 파일
|
|||
|
||||
|
||||
|
||||
milestones.filter_sort.name = 이름
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -1797,6 +1799,9 @@ emails.filter_sort.name_reverse = 사용자명 (예약됨)
|
|||
config.allow_dots_in_usernames = 사용자들이 마침표를 사용자명에 사용할 수 있도록 허가합니다. 이미 존재하는 계정에는 영향을 주지 않습니다.
|
||||
|
||||
|
||||
config_summary = 요약
|
||||
config_settings = 설정
|
||||
|
||||
[action]
|
||||
create_repo=저장소를 만들었습니다. <a href="%s">%s</a>
|
||||
rename_repo=저장소 이름을 <code>%[1]s에서</code>에서 <a href="%[2]s"> %[3]s</a>으로 변경함
|
||||
|
|
|
@ -101,6 +101,11 @@ concept_user_organization=සංවිධානය
|
|||
|
||||
name=නම
|
||||
|
||||
filter = පෙරහන
|
||||
filter.is_archived = සංරක්ෂිත
|
||||
filter.public = ප්රසිද්ධ
|
||||
filter.private = පෞද්ගලික
|
||||
|
||||
[aria]
|
||||
|
||||
[heatmap]
|
||||
|
@ -1913,6 +1918,8 @@ error.csv.too_large=එය ඉතා විශාල නිසා මෙම ග
|
|||
error.csv.unexpected=%d පේළියේ සහ %dතීරුවේ අනපේක්ෂිත චරිතයක් අඩංගු බැවින් මෙම ගොනුව විදැහුම්කරණය කළ නොහැක.
|
||||
error.csv.invalid_field_count=මෙම ගොනුව රේඛාවේ වැරදි ක්ෂේත්ර සංඛ්යාවක් ඇති බැවින් එය විදැහුම්කරණය කළ නොහැක %d.
|
||||
|
||||
milestones.filter_sort.name = නම
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -2462,6 +2469,9 @@ notices.op=ඔප්.
|
|||
notices.delete_success=පද්ධති දැන්වීම් මකා දමා ඇත.
|
||||
|
||||
|
||||
config_summary = සාරාංශය
|
||||
config_settings = සැකසුම්
|
||||
|
||||
[action]
|
||||
create_repo=නිර්මිත ගබඩාව <a href="%s">%s</a>
|
||||
rename_repo=<code>%[1]s</code> සිට <a href="%[2]s">%[3]s</a>දක්වා නම් කරන ලද ගබඩාව
|
||||
|
@ -2554,3 +2564,5 @@ runs.commit=කැප
|
|||
|
||||
[git.filemode]
|
||||
symbolic_link=සංකේතාත්මක සබැඳිය
|
||||
|
||||
[search]
|
||||
|
|
|
@ -142,6 +142,9 @@ name=Meno
|
|||
value=Hodnota
|
||||
issues = Problémy
|
||||
|
||||
filter.is_archived = Archivované
|
||||
filter.private = Súkromný
|
||||
|
||||
[aria]
|
||||
navbar=Navigačná lišta
|
||||
footer=Päta
|
||||
|
@ -1370,4 +1373,6 @@ runners.labels=Štítky
|
|||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
symbolic_link=Symbolický odkaz
|
||||
symbolic_link=Symbolický odkaz
|
||||
|
||||
[search]
|
|
@ -342,6 +342,8 @@ app_slogan_helper = Oluşum sloganınızı giriniz. Devre dışı bırakmak içi
|
|||
enable_update_checker_helper_forgejo = release.forgejo.org adresindeki TXT DNS kayıdı kullanılarak yeni Forgejo sürümleri düzenli olarak kontrol edilecektir.
|
||||
allow_dots_in_usernames = Kullanıcı isimlerinde noktaya izin ver. Var olan kullanıcıları etkilemez.
|
||||
|
||||
smtp_from_invalid = `"E-posta Olarak Gönder" adresi geçersiz`
|
||||
|
||||
[home]
|
||||
uname_holder=Kullanıcı adı veya e-posta adresi
|
||||
password_holder=Parola
|
||||
|
@ -663,6 +665,9 @@ admin_cannot_delete_self = Yöneticiyken kullanıcınızı silemezsiniz. Lütfen
|
|||
username_error_no_dots = ` sadece alfanumerik karakterler ("0-9","a-z","A-Z"), tire ("-") ve alt tire ("-") içerebilir. Alfanumerik olmayan karakterlerle başlayamaz ve bitemez, ayrıca ardışık alfanumerik olmayan karakterler de kullanılamaz.`
|
||||
|
||||
|
||||
unset_password = Oturum açma kullanıcısı parola belirlemedi.
|
||||
unsupported_login_type = Oturum açma türü hesap silmeyi desteklemiyor.
|
||||
|
||||
[user]
|
||||
change_avatar=Profil resmini değiştir…
|
||||
joined_on=%s tarihinde katıldı
|
||||
|
@ -2692,7 +2697,37 @@ activity.navbar.contributors = Katılımcılar
|
|||
contributors.contribution_type.deletions = Çıkarmalar
|
||||
settings.new_owner_blocked_doer = Yeni sahip sizi engelledi.
|
||||
|
||||
open_with_editor = %s ile aç
|
||||
object_format = Nesne Biçimi
|
||||
mirror_sync = eşitlendi
|
||||
stars = Yıldızlar
|
||||
desc.sha256 = SHA256
|
||||
vendored = Sağlanmış
|
||||
generated = Üretilmiş
|
||||
editor.push_out_of_date = İtme eskimiş.
|
||||
commits.search_branch = Bu Dal
|
||||
issues.edit.already_changed = Konuya yapılan değişiklikler kaydedilemiyor. İçerik başka kullanıcı tarafından değiştirilmiş gözüküyor. Diğerlerinin değişikliklerinin üzerine yazmamak için lütfen sayfayı yenileyin ve tekrar düzenlemeye çalışın
|
||||
pulls.edit.already_changed = Değişiklik isteğine yapılan değişiklikler kaydedilemiyor. İçerik başka kullanıcı tarafından değiştirilmiş gözüküyor. Diğerlerinin değişikliklerinin üzerine yazmamak için lütfen sayfayı yenileyin ve tekrar düzenlemeye çalışın
|
||||
pulls.nothing_to_compare_have_tag = Seçili dal/etiket aynı.
|
||||
pulls.fast_forward_only_merge_pull_request = Sadece ileri sarma
|
||||
comments.edit.already_changed = Yoruma yapılan değişiklikler kaydedilemiyor. İçerik başka kullanıcı tarafından değiştirilmiş gözüküyor. Diğerlerinin değişikliklerinin üzerine yazmamak için lütfen sayfayı yenileyin ve tekrar düzenlemeye çalışın
|
||||
milestones.filter_sort.name = Ad
|
||||
activity.navbar.pulse = Eğilim
|
||||
activity.navbar.code_frequency = Kod Frekansı
|
||||
activity.navbar.recent_commits = Son İşlemeler
|
||||
settings.mirror_settings.pushed_repository = İtilmiş depo
|
||||
settings.ignore_stale_approvals = Eskimiş onayları yoksay
|
||||
settings.ignore_stale_approvals_desc = Daha eski işlemelere (eski incelemelere) yapılmış olan onayları, Dİ'nin kaç onayı olduğunu belirlerken sayma. Eskimiş incelemeler atıldıysa bu ilgisizdir.
|
||||
error.broken_git_hook = Bu deponun Git İstemcileri bozuk gibi gözüküyor. Onarmak için lütfen <a target="_blank" rel="noreferrer" href="%s">belgelere</a> bakın, daha sonra durumu yenilemek için bazı işlemeler itin.
|
||||
|
||||
[graphs]
|
||||
component_loading = %s yükleniyor...
|
||||
component_loading_failed = %s yüklenemedi
|
||||
component_loading_info = Bu biraz sürebilir…
|
||||
component_failed_to_load = Beklenmedik bir hata oluştu.
|
||||
code_frequency.what = kod frekansı
|
||||
contributors.what = katkılar
|
||||
recent_commits.what = son işlemeler
|
||||
|
||||
[org]
|
||||
org_name_holder=Organizasyon Adı
|
||||
|
@ -3346,6 +3381,23 @@ notices.op=İşlem
|
|||
notices.delete_success=Sistem bildirimleri silindi.
|
||||
|
||||
|
||||
self_check = Öz Denetim
|
||||
config_summary = Özet
|
||||
config_settings = Ayarlar
|
||||
dashboard.sync_repo_tags = Etiketleri git verisinden veritabanına eşitle
|
||||
emails.delete = E-postayı Sil
|
||||
emails.delete_desc = Bu e-posta adresini silmek istediğinizden emin misiniz?
|
||||
emails.deletion_success = E-posta adresi silindi.
|
||||
emails.delete_primary_email_error = Ana e-posta adresini silemezsiniz.
|
||||
config.cache_test = Önbelleği Sına
|
||||
config.cache_test_failed = Önbelleğin incelenmesi başarısız oldu: %v.
|
||||
config.cache_test_slow = Önbellek sınaması başarılı, ancak yanıt yavaş: %s.
|
||||
config.cache_test_succeeded = Önbellek sınaması başarılı, %s sürede bir yanıt alındı.
|
||||
config.open_with_editor_app_help = Klon menüsü için "Birlikte aç" düzenleyicileri. Boş bırakılırsa, varsayılan kullanılacaktır. Varsayılanı görmek için genişletin.
|
||||
self_check.no_problem_found = Henüz bir sorun bulunmadı.
|
||||
self_check.database_collation_mismatch = Veritabanının şu harmanlamayı kullanmasını bekle: %s
|
||||
self_check.database_inconsistent_collation_columns = Veritabanı %s harmanlamasını kullanıyor, ancak bu sütunlar uyumsuz harmanlamalar kullanıyor. Bu beklenmedik sorunlar oluşturabilir.
|
||||
|
||||
[action]
|
||||
create_repo=depo <a href="%s">%s</a> oluşturuldu
|
||||
rename_repo=<code>%[1]s</code> olan depo adını <a href="%[2]s">%[3]s</a> buna çevirdi
|
||||
|
@ -3586,6 +3638,9 @@ owner.settings.chef.title=Chef Kütüğü
|
|||
owner.settings.chef.keypair=Anahtar çifti üret
|
||||
owner.settings.chef.keypair.description=Chef kütüğünde kimlik doğrulaması için bir anahtar çifti gereklidir. Eğer daha önce bir anahtar çifti ürettiyseniz, yeni bir anahtar çifti üretmek eski anahtar çiftini ıskartaya çıkartacaktır.
|
||||
|
||||
npm.dependencies.bundle = Paketlenmiş Bağımlılıklar
|
||||
rpm.repository.multiple_groups = Bu paket birçok grupta mevcut.
|
||||
|
||||
[secrets]
|
||||
secrets=Gizlilikler
|
||||
description=Gizlilikler belirli işlemlere aktarılacaktır, bunun dışında okunamaz.
|
||||
|
@ -3693,6 +3748,10 @@ runs.no_workflows.documentation = Gitea İşlem'i hakkında daha fazla bilgi iç
|
|||
variables.id_not_exist = %d kimlikli değişken mevcut değil.
|
||||
runs.no_workflows.quick_start = Gitea İşlem'i nasıl başlatacağınızı bilmiyor musunuz? <a target="_blank" rel="noopener noreferrer" href="%s">Hızlı başlangıç rehberine</a> bakabilirsiniz.
|
||||
|
||||
runs.no_job_without_needs = İş akışı en azından bağımlılığı olmayan bir görev içermelidir.
|
||||
runs.no_job = İş akışı en azından bir görev içermelidir
|
||||
runs.expire_log_message = Günlükler, çok eski oldukları için temizlendiler.
|
||||
|
||||
[projects]
|
||||
type-1.display_name=Kişisel Proje
|
||||
type-2.display_name=Depo Projesi
|
||||
|
@ -3732,3 +3791,5 @@ keyword_search_unavailable = Anahtar kelime ile arama şu anda kullanıma açık
|
|||
fuzzy_tooltip = Arama terimine yakın olan eşleşmeleri dahil et
|
||||
union_tooltip = Boşlukla ayrılmış anahtar kelime eşleşmelerini dahil et
|
||||
exact_tooltip = Sadece arama terimiyle tam uyuşan sonuçları dahit et.
|
||||
fuzzy = Bulanık
|
||||
exact = Tam
|
||||
|
|
|
@ -134,6 +134,8 @@ copy_generic = 複製到剪貼簿
|
|||
copy_url = 複製網址
|
||||
copy_hash = 複製雜湊值
|
||||
|
||||
filter.private = 私有庫
|
||||
|
||||
[aria]
|
||||
footer = 頁尾
|
||||
footer.links = 連結
|
||||
|
@ -791,6 +793,8 @@ settings.branches.update_default_branch = 更新預設分支
|
|||
|
||||
|
||||
|
||||
milestones.filter_sort.name = 組織名稱
|
||||
|
||||
[graphs]
|
||||
|
||||
[org]
|
||||
|
@ -1076,6 +1080,8 @@ users = 使用者帳戶
|
|||
defaulthooks = 預設 Webhook
|
||||
|
||||
|
||||
config_settings = 組織設定
|
||||
|
||||
[action]
|
||||
create_repo=建立了儲存庫 <a href="%s">%s</a>
|
||||
rename_repo=重新命名儲存庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
|
||||
|
@ -1146,4 +1152,6 @@ runners.labels = 標籤
|
|||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
[git.filemode]
|
||||
|
||||
[search]
|
|
@ -2842,6 +2842,17 @@ release.summary_card_alt = 儲存庫 %[2]s 中名為「%[1]s」的發行摘要
|
|||
error.broken_git_hook = 此儲存庫的 Git 鉤子似乎已損壞。請按照<a target="_blank" rel="noreferrer" href="%s">文件</a>修復它們,然後推送一些提交以重新整理狀態。
|
||||
issues.reaction.alt_remove = 從留言中移除 %[1]s 的反應。
|
||||
|
||||
vendored = 已供應
|
||||
settings.mirror_settings.docs.doc_link_pull_section = 文件中的「從遠端儲存庫拉取」部分。
|
||||
settings.event_pull_request_review_request_desc = 合併請求審核請求或審核請求已移除。
|
||||
settings.protect_status_check_patterns_desc = 輸入模式以指定其他分支在合併到受此規則保護的分支前必須通過的狀態檢查。每行指定一個模式,模式不得為空白。
|
||||
settings.protect_invalid_status_check_pattern = 狀態檢查模式無效: 「%s」。
|
||||
settings.ignore_stale_approvals_desc = 不計算在較舊提交上進行的核可(過時的審核)作為合併請求的核可數量。如果過時的審核已經被捨棄,則無關緊要。
|
||||
settings.tags.protection.pattern.description = 您可以使用單一名稱或 glob 模式或正則表達式來匹配多個標籤。詳情請參閱 <a target="_blank" rel="noopener" href="%s">受保護標籤指南</a>。
|
||||
settings.thread_id = 線程 ID
|
||||
settings.archive.text = 封存儲存庫將使其完全變為唯讀。它將從儀表板中隱藏。沒有人(甚至包括您!)將能夠進行新的提交,或打開任何問題或合併請求。
|
||||
diff.comment.add_line_comment = 新增行評論
|
||||
|
||||
[graphs]
|
||||
component_loading = 載入中 %s…
|
||||
code_frequency.what = 寫程式頻率
|
||||
|
@ -3536,6 +3547,9 @@ users.admin.description = 授予此使用者透過網頁介面和 API 提供的
|
|||
auths.tip.gitea = 註冊一個新的 OAuth2 應用程式。指南可在 %s 找到
|
||||
|
||||
|
||||
monitor.queue.activeworkers = 活躍工作者
|
||||
monitor.queue.settings.desc = 集區會根據工作者佇列的阻塞情況動態增長。
|
||||
|
||||
[action]
|
||||
create_repo=建立了儲存庫 <a href="%s">%s</a>
|
||||
rename_repo=重新命名儲存庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
|
||||
|
|
1629
package-lock.json
generated
1629
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -85,7 +85,7 @@
|
|||
"eslint-plugin-vue-scoped-css": "2.9.0",
|
||||
"eslint-plugin-wc": "2.2.0",
|
||||
"globals": "15.15.0",
|
||||
"happy-dom": "16.8.1",
|
||||
"happy-dom": "17.1.0",
|
||||
"license-checker-rseidelsohn": "4.4.2",
|
||||
"markdownlint-cli": "0.44.0",
|
||||
"postcss-html": "1.8.0",
|
||||
|
|
12
poetry.lock
generated
12
poetry.lock
generated
|
@ -44,13 +44,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "cssbeautifier"
|
||||
version = "1.15.2"
|
||||
version = "1.15.3"
|
||||
description = "CSS unobfuscator and beautifier."
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "cssbeautifier-1.15.2-py3-none-any.whl", hash = "sha256:6daf7f6012ff2914092d675793a5a7f602ca36a10159d0cf5c119183004306e0"},
|
||||
{file = "cssbeautifier-1.15.2.tar.gz", hash = "sha256:02d42ffa6aefaa87f18452b437dbb73f6b98f42e9a84759810dc58f7a6bfc26c"},
|
||||
{file = "cssbeautifier-1.15.3-py3-none-any.whl", hash = "sha256:0dcaf5ce197743a79b3a160b84ea58fcbd9e3e767c96df1171e428125b16d410"},
|
||||
{file = "cssbeautifier-1.15.3.tar.gz", hash = "sha256:406b04d09e7d62c0be084fbfa2cba5126fe37359ea0d8d9f7b963a6354fc8303"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -115,13 +115,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "jsbeautifier"
|
||||
version = "1.15.2"
|
||||
version = "1.15.3"
|
||||
description = "JavaScript unobfuscator and beautifier."
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "jsbeautifier-1.15.2-py3-none-any.whl", hash = "sha256:d599aed6dcb0d5431190e5ad7335900d5fdc67236082fe6b6d3fb61d568d7417"},
|
||||
{file = "jsbeautifier-1.15.2.tar.gz", hash = "sha256:6aff11af2c6cb9a2ce135f33a5b223cf5ee676ab7ff5da0edac01e23734f5755"},
|
||||
{file = "jsbeautifier-1.15.3-py3-none-any.whl", hash = "sha256:b207a15ab7529eee4a35ae7790e9ec4e32a2b5026d51e2d0386c3a65e6ecfc91"},
|
||||
{file = "jsbeautifier-1.15.3.tar.gz", hash = "sha256:5f1baf3d4ca6a615bb5417ee861b34b77609eeb12875555f8bbfabd9bf2f3457"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
|
@ -63,6 +63,7 @@ func UpdateUserSettings(ctx *context.APIContext) {
|
|||
Theme: optional.FromPtr(form.Theme),
|
||||
DiffViewStyle: optional.FromPtr(form.DiffViewStyle),
|
||||
KeepEmailPrivate: optional.FromPtr(form.HideEmail),
|
||||
KeepPronounsPrivate: optional.FromPtr(form.HidePronouns),
|
||||
KeepActivityPrivate: optional.FromPtr(form.HideActivity),
|
||||
EnableRepoUnitHints: optional.FromPtr(form.EnableRepoUnitHints),
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ func AuthShared(ctx *context.Base, sessionStore auth_service.SessionStore, authM
|
|||
ctx.Data["SignedUserID"] = ar.Doer.ID
|
||||
ctx.Data["IsAdmin"] = ar.Doer.IsAdmin
|
||||
} else {
|
||||
ctx.Data["IsSigned"] = false
|
||||
ctx.Data["SignedUserID"] = int64(0)
|
||||
}
|
||||
return ar, nil
|
||||
|
|
|
@ -62,7 +62,7 @@ func autoSignIn(ctx *context.Context) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
u, err := user_model.VerifyUserAuthorizationToken(ctx, authCookie, auth.LongTermAuthorization, false)
|
||||
u, _, err := user_model.VerifyUserAuthorizationToken(ctx, authCookie, auth.LongTermAuthorization)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("VerifyUserAuthorizationToken: %w", err)
|
||||
}
|
||||
|
@ -672,7 +672,7 @@ func Activate(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.UserActivation, false)
|
||||
user, deleteToken, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.UserActivation)
|
||||
if err != nil {
|
||||
ctx.ServerError("VerifyUserAuthorizationToken", err)
|
||||
return
|
||||
|
@ -693,6 +693,11 @@ func Activate(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := deleteToken(); err != nil {
|
||||
ctx.ServerError("deleteToken", err)
|
||||
return
|
||||
}
|
||||
|
||||
handleAccountActivation(ctx, user)
|
||||
}
|
||||
|
||||
|
@ -741,7 +746,7 @@ func ActivatePost(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.UserActivation, true)
|
||||
user, deleteToken, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.UserActivation)
|
||||
if err != nil {
|
||||
ctx.ServerError("VerifyUserAuthorizationToken", err)
|
||||
return
|
||||
|
@ -770,6 +775,11 @@ func ActivatePost(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if err := deleteToken(); err != nil {
|
||||
ctx.ServerError("deleteToken", err)
|
||||
return
|
||||
}
|
||||
|
||||
handleAccountActivation(ctx, user)
|
||||
}
|
||||
|
||||
|
@ -830,7 +840,7 @@ func ActivateEmail(ctx *context.Context) {
|
|||
code := ctx.FormString("code")
|
||||
emailStr := ctx.FormString("email")
|
||||
|
||||
u, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.EmailActivation(emailStr), true)
|
||||
u, deleteToken, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.EmailActivation(emailStr))
|
||||
if err != nil {
|
||||
ctx.ServerError("VerifyUserAuthorizationToken", err)
|
||||
return
|
||||
|
@ -840,6 +850,11 @@ func ActivateEmail(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := deleteToken(); err != nil {
|
||||
ctx.ServerError("deleteToken", err)
|
||||
return
|
||||
}
|
||||
|
||||
email, err := user_model.GetEmailAddressOfUser(ctx, emailStr, u.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetEmailAddressOfUser", err)
|
||||
|
|
|
@ -116,7 +116,7 @@ func commonResetPassword(ctx *context.Context, shouldDeleteToken bool) (*user_mo
|
|||
}
|
||||
|
||||
// Fail early, don't frustrate the user
|
||||
u, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.PasswordReset, shouldDeleteToken)
|
||||
u, deleteToken, err := user_model.VerifyUserAuthorizationToken(ctx, code, auth.PasswordReset)
|
||||
if err != nil {
|
||||
ctx.ServerError("VerifyUserAuthorizationToken", err)
|
||||
return nil, nil
|
||||
|
@ -127,6 +127,13 @@ func commonResetPassword(ctx *context.Context, shouldDeleteToken bool) (*user_mo
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
if shouldDeleteToken {
|
||||
if err := deleteToken(); err != nil {
|
||||
ctx.ServerError("deleteToken", err)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
twofa, err := auth.GetTwoFactorByUID(ctx, u.ID)
|
||||
if err != nil {
|
||||
if !auth.IsErrTwoFactorNotEnrolled(err) {
|
||||
|
|
|
@ -106,6 +106,7 @@ func ProfilePost(ctx *context.Context) {
|
|||
Location: optional.Some(form.Location),
|
||||
Visibility: optional.Some(form.Visibility),
|
||||
KeepActivityPrivate: optional.Some(form.KeepActivityPrivate),
|
||||
KeepPronounsPrivate: optional.Some(form.KeepPronounsPrivate),
|
||||
}
|
||||
if err := user_service.UpdateUser(ctx, ctx.Doer, opts); err != nil {
|
||||
ctx.ServerError("UpdateUser", err)
|
||||
|
|
|
@ -57,7 +57,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap
|
|||
Created: user.CreatedUnix.AsTime(),
|
||||
Restricted: user.IsRestricted,
|
||||
Location: user.Location,
|
||||
Pronouns: user.Pronouns,
|
||||
Pronouns: user.GetPronouns(signed),
|
||||
Website: user.Website,
|
||||
Description: user.Description,
|
||||
// counter's
|
||||
|
@ -97,6 +97,7 @@ func User2UserSettings(user *user_model.User) api.UserSettings {
|
|||
Description: user.Description,
|
||||
Theme: user.Theme,
|
||||
HideEmail: user.KeepEmailPrivate,
|
||||
HidePronouns: user.KeepPronounsPrivate,
|
||||
HideActivity: user.KeepActivityPrivate,
|
||||
DiffViewStyle: user.DiffViewStyle,
|
||||
EnableRepoUnitHints: user.EnableRepoUnitHints,
|
||||
|
|
|
@ -224,6 +224,7 @@ type UpdateProfileForm struct {
|
|||
Biography string `binding:"MaxSize(255)"`
|
||||
Visibility structs.VisibleType
|
||||
KeepActivityPrivate bool
|
||||
KeepPronounsPrivate bool
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
|
|
@ -40,6 +40,7 @@ type UpdateOptions struct {
|
|||
SetLastLogin bool
|
||||
RepoAdminChangeTeamAccess optional.Option[bool]
|
||||
EnableRepoUnitHints optional.Option[bool]
|
||||
KeepPronounsPrivate optional.Option[bool]
|
||||
}
|
||||
|
||||
func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) error {
|
||||
|
@ -97,6 +98,12 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er
|
|||
cols = append(cols, "enable_repo_unit_hints")
|
||||
}
|
||||
|
||||
if opts.KeepPronounsPrivate.Has() {
|
||||
u.KeepPronounsPrivate = opts.KeepPronounsPrivate.Value()
|
||||
|
||||
cols = append(cols, "keep_pronouns_private")
|
||||
}
|
||||
|
||||
if opts.AllowGitHook.Has() {
|
||||
u.AllowGitHook = opts.AllowGitHook.Value()
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<ul class="list">
|
||||
{{if $hasArchiveLinks}}
|
||||
<li>
|
||||
<a class="archive-link tw-flex-1 flex-text-inline tw-font-bold" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.zip" rel="nofollow">
|
||||
<a class="archive-link tw-flex-1 flex-text-inline tw-font-bold" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.zip" rel="nofollow" type="application/zip">
|
||||
{{svg "octicon-file-zip" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.source_code"}} (ZIP)
|
||||
</a>
|
||||
<div class="tw-mr-1">
|
||||
|
@ -83,7 +83,7 @@
|
|||
</span>
|
||||
</li>
|
||||
<li class="{{if $hasReleaseAttachment}}start-gap{{end}}">
|
||||
<a class="archive-link tw-flex-1 flex-text-inline tw-font-bold" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.tar.gz" rel="nofollow">
|
||||
<a class="archive-link tw-flex-1 flex-text-inline tw-font-bold" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.tar.gz" rel="nofollow" type="application/gzip">
|
||||
{{svg "octicon-file-zip" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.source_code"}} (TAR.GZ)
|
||||
</a>
|
||||
<div class="tw-mr-1">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
<div class="content tw-break-anywhere profile-avatar-name">
|
||||
{{if .ContextUser.FullName}}<span class="header text center">{{.ContextUser.FullName}}</span>{{end}}
|
||||
<span class="username text center">{{.ContextUser.Name}}{{if .ContextUser.Pronouns}} · {{.ContextUser.Pronouns}}{{end}} {{if .IsAdmin}}
|
||||
<span class="username text center">{{.ContextUser.Name}} {{if .ContextUser.GetPronouns .IsSigned}} · {{.ContextUser.GetPronouns .IsSigned}}{{end}} {{if .IsAdmin}}
|
||||
<a class="muted" href="{{AppSubUrl}}/admin/users/{{.ContextUser.ID}}" data-tooltip-content="{{ctx.Locale.Tr "admin.users.details"}}">
|
||||
{{svg "octicon-gear" 18}}
|
||||
</a>
|
||||
|
|
8
templates/swagger/v1_json.tmpl
generated
8
templates/swagger/v1_json.tmpl
generated
|
@ -27954,6 +27954,10 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "HideEmail"
|
||||
},
|
||||
"hide_pronouns": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "HidePronouns"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"x-go-name": "Language"
|
||||
|
@ -28006,6 +28010,10 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "HideEmail"
|
||||
},
|
||||
"hide_pronouns": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "HidePronouns"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"x-go-name": "Language"
|
||||
|
|
|
@ -120,6 +120,12 @@
|
|||
{{ctx.Locale.Tr "settings.keep_activity_private"}}
|
||||
<span class="help">{{ctx.Locale.Tr "settings.keep_activity_private.description" (printf "/%s?tab=activity" .SignedUser.Name)}}</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input name="keep_pronouns_private" type="checkbox" {{if .SignedUser.KeepPronounsPrivate}}checked{{end}}>
|
||||
{{ctx.Locale.Tr "settings.keep_pronouns_private"}}
|
||||
<span class="help">{{ctx.Locale.Tr "settings.keep_pronouns_private.description"}}</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_profile"}}</button>
|
||||
|
|
|
@ -43,10 +43,17 @@ test('External Release Attachments', async ({page, isMobile}) => {
|
|||
// Validate release page and click edit
|
||||
await expect(page).toHaveURL('/user2/repo2/releases');
|
||||
await expect(page.locator('.download[open] li')).toHaveCount(3);
|
||||
|
||||
await expect(page.locator('.download[open] li:nth-of-type(1)')).toContainText('Source code (ZIP)');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(1) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.zip');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('type', 'application/zip');
|
||||
|
||||
await expect(page.locator('.download[open] li:nth-of-type(2)')).toContainText('Source code (TAR.GZ)');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(2) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.tar.gz');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('type', 'application/gzip');
|
||||
|
||||
await expect(page.locator('.download[open] li:nth-of-type(3)')).toContainText('Test');
|
||||
await expect(page.locator('.download[open] li:nth-of-type(3) a')).toHaveAttribute('href', 'https://forgejo.org/');
|
||||
await save_visual(page);
|
||||
|
|
|
@ -438,8 +438,16 @@ func TestUserHints(t *testing.T) {
|
|||
func TestUserPronouns(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
|
||||
// user1 is admin, using user2 and user10 respectively instead.
|
||||
// This is explicitly mentioned here because of the unconventional
|
||||
// variable naming scheme.
|
||||
firstUserSession := loginUser(t, "user2")
|
||||
firstUserToken := getTokenForLoggedInUser(t, firstUserSession, auth_model.AccessTokenScopeWriteUser)
|
||||
|
||||
// This user has the HidePronouns setting enabled.
|
||||
// Check the fixture!
|
||||
secondUserSession := loginUser(t, "user10")
|
||||
secondUserToken := getTokenForLoggedInUser(t, secondUserSession, auth_model.AccessTokenScopeWriteUser)
|
||||
|
||||
adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
|
||||
adminSession := loginUser(t, adminUser.Name)
|
||||
|
@ -449,8 +457,10 @@ func TestUserPronouns(t *testing.T) {
|
|||
t.Run("user", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
// secondUserToken was chosen arbitrarily and should have no impact.
|
||||
// See next comment.
|
||||
req := NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(secondUserToken)
|
||||
resp := firstUserSession.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// We check the raw JSON, because we want to test the response, not
|
||||
// what it decodes into. Contents doesn't matter, we're testing the
|
||||
|
@ -468,16 +478,22 @@ func TestUserPronouns(t *testing.T) {
|
|||
// what it decodes into. Contents doesn't matter, we're testing the
|
||||
// presence only.
|
||||
assert.Contains(t, resp.Body.String(), `"pronouns":`)
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/users/user10")
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Same deal here.
|
||||
assert.Contains(t, resp.Body.String(), `"pronouns":`)
|
||||
})
|
||||
|
||||
t.Run("user/settings", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Set pronouns first
|
||||
// Set pronouns first for user2
|
||||
pronouns := "they/them"
|
||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/user/settings", &api.UserSettingsOptions{
|
||||
Pronouns: &pronouns,
|
||||
}).AddTokenAuth(token)
|
||||
}).AddTokenAuth(firstUserToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Verify the response
|
||||
|
@ -486,7 +502,7 @@ func TestUserPronouns(t *testing.T) {
|
|||
assert.Equal(t, pronouns, user.Pronouns)
|
||||
|
||||
// Verify retrieving the settings again
|
||||
req = NewRequest(t, "GET", "/api/v1/user/settings").AddTokenAuth(token)
|
||||
req = NewRequest(t, "GET", "/api/v1/user/settings").AddTokenAuth(firstUserToken)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
DecodeJSON(t, resp, &user)
|
||||
|
@ -497,22 +513,40 @@ func TestUserPronouns(t *testing.T) {
|
|||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Set the pronouns for user2
|
||||
pronouns := "she/her"
|
||||
pronouns := "he/him"
|
||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/admin/users/user2", &api.EditUserOption{
|
||||
Pronouns: &pronouns,
|
||||
}).AddTokenAuth(adminToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Verify the API response
|
||||
var user *api.User
|
||||
DecodeJSON(t, resp, &user)
|
||||
assert.Equal(t, pronouns, user.Pronouns)
|
||||
var user2 *api.User
|
||||
DecodeJSON(t, resp, &user2)
|
||||
assert.Equal(t, pronouns, user2.Pronouns)
|
||||
|
||||
// Verify via user2 too
|
||||
req = NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(token)
|
||||
// Verify via user2
|
||||
req = NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(firstUserToken)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &user)
|
||||
assert.Equal(t, pronouns, user.Pronouns)
|
||||
DecodeJSON(t, resp, &user2)
|
||||
assert.Equal(t, pronouns, user2.Pronouns) // TODO: This fails for some reason
|
||||
|
||||
// Set the pronouns for user10
|
||||
pronouns = "he/him"
|
||||
req = NewRequestWithJSON(t, "PATCH", "/api/v1/admin/users/user10", &api.EditUserOption{
|
||||
Pronouns: &pronouns,
|
||||
}).AddTokenAuth(adminToken)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Verify the API response
|
||||
var user10 *api.User
|
||||
DecodeJSON(t, resp, &user10)
|
||||
assert.Equal(t, pronouns, user10.Pronouns)
|
||||
|
||||
// Verify via user10
|
||||
req = NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(secondUserToken)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &user10)
|
||||
assert.Equal(t, pronouns, user10.Pronouns)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -520,10 +554,10 @@ func TestUserPronouns(t *testing.T) {
|
|||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Set the pronouns to a known state via the API
|
||||
pronouns := "she/her"
|
||||
pronouns := "they/them"
|
||||
req := NewRequestWithJSON(t, "PATCH", "/api/v1/user/settings", &api.UserSettingsOptions{
|
||||
Pronouns: &pronouns,
|
||||
}).AddTokenAuth(token)
|
||||
}).AddTokenAuth(firstUserToken)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
t.Run("profile view", func(t *testing.T) {
|
||||
|
@ -534,14 +568,14 @@ func TestUserPronouns(t *testing.T) {
|
|||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
userNameAndPronouns := strings.TrimSpace(htmlDoc.Find(".profile-avatar-name .username").Text())
|
||||
assert.Contains(t, userNameAndPronouns, pronouns)
|
||||
assert.NotContains(t, userNameAndPronouns, pronouns)
|
||||
})
|
||||
|
||||
t.Run("settings", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", "/user/settings")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
resp := firstUserSession.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Check that the field is present
|
||||
|
@ -550,12 +584,12 @@ func TestUserPronouns(t *testing.T) {
|
|||
assert.Equal(t, pronouns, pronounField)
|
||||
|
||||
// Check that updating the field works
|
||||
newPronouns := "they/them"
|
||||
newPronouns := "she/her"
|
||||
req = NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, "/user/settings"),
|
||||
"_csrf": GetCSRF(t, firstUserSession, "/user/settings"),
|
||||
"pronouns": newPronouns,
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
firstUserSession.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
|
||||
assert.Equal(t, newPronouns, user2.Pronouns)
|
||||
|
@ -886,11 +920,27 @@ func TestUserActivate(t *testing.T) {
|
|||
assert.False(t, authToken.IsExpired())
|
||||
assert.EqualValues(t, authToken.HashedValidator, auth_model.HashValidator(rawValidator))
|
||||
|
||||
req = NewRequest(t, "POST", "/user/activate?code="+code)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
t.Run("No password", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
unittest.AssertNotExistsBean(t, &auth_model.AuthorizationToken{ID: authToken.ID})
|
||||
unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "doesnotexist", IsActive: true})
|
||||
req = NewRequest(t, "POST", "/user/activate?code="+code)
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
unittest.AssertExistsIf(t, true, &auth_model.AuthorizationToken{ID: authToken.ID})
|
||||
unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "doesnotexist"}, "is_active = false")
|
||||
})
|
||||
|
||||
t.Run("With password", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req = NewRequestWithValues(t, "POST", "/user/activate?code="+code, map[string]string{
|
||||
"password": "examplePassword!1",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
unittest.AssertExistsIf(t, false, &auth_model.AuthorizationToken{ID: authToken.ID})
|
||||
unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "doesnotexist"}, "is_active = true")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserPasswordReset(t *testing.T) {
|
||||
|
|
162
web_src/fomantic/package-lock.json
generated
162
web_src/fomantic/package-lock.json
generated
|
@ -132,16 +132,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.3.tgz",
|
||||
"integrity": "sha512-z+j7DixNnfpdToYsOutStDgeRzJSMnbj8T1C/oQjB6Aa+kRfNjs/Fn7W6c8bmlt6mfy3FkgeKBRnDjxQow5dow==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz",
|
||||
"integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^5.0.0",
|
||||
"@octokit/graphql": "^8.1.2",
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/request-error": "^6.1.6",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"before-after-hook": "^3.0.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
|
@ -161,9 +161,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/endpoint": {
|
||||
"version": "10.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.2.tgz",
|
||||
"integrity": "sha512-XybpFv9Ms4hX5OCHMZqyODYqGTZ3H6K6Vva+M9LR7ib/xr1y1ZnlChYv9H680y77Vd/i/k+thXApeRASBQkzhA==",
|
||||
"version": "10.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz",
|
||||
"integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
@ -182,14 +182,14 @@
|
|||
"peer": true
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/request": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.0.tgz",
|
||||
"integrity": "sha512-kXLfcxhC4ozCnAXy2ff+cSxpcF0A1UqxjvYMqNuPIeOAzJbVWQ+dy5G2fTylofB/gTbObT8O6JORab+5XtA1Kw==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz",
|
||||
"integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^10.0.0",
|
||||
"@octokit/request-error": "^6.0.1",
|
||||
"@octokit/endpoint": "^10.1.3",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"fast-content-type-parse": "^2.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
|
@ -199,9 +199,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/request-error": {
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.6.tgz",
|
||||
"integrity": "sha512-pqnVKYo/at0NuOjinrgcQYpEbv4snvP3bKMRqHaD9kIsk9u1LCpb2smHZi8/qJfgeNqLo5hNW4Z7FezNdEo0xg==",
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz",
|
||||
"integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
@ -253,13 +253,13 @@
|
|||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.0.tgz",
|
||||
"integrity": "sha512-gejfDywEml/45SqbWTWrhfwvLBrcGYhOn50sPOjIeVvH6i7D16/9xcFA8dAJNp2HMcd+g4vru41g4E2RBiZvfQ==",
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz",
|
||||
"integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/request": "^9.2.2",
|
||||
"@octokit/types": "^13.8.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
|
@ -268,9 +268,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/endpoint": {
|
||||
"version": "10.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.2.tgz",
|
||||
"integrity": "sha512-XybpFv9Ms4hX5OCHMZqyODYqGTZ3H6K6Vva+M9LR7ib/xr1y1ZnlChYv9H680y77Vd/i/k+thXApeRASBQkzhA==",
|
||||
"version": "10.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz",
|
||||
"integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
@ -289,14 +289,14 @@
|
|||
"peer": true
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/request": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.0.tgz",
|
||||
"integrity": "sha512-kXLfcxhC4ozCnAXy2ff+cSxpcF0A1UqxjvYMqNuPIeOAzJbVWQ+dy5G2fTylofB/gTbObT8O6JORab+5XtA1Kw==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz",
|
||||
"integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^10.0.0",
|
||||
"@octokit/request-error": "^6.0.1",
|
||||
"@octokit/endpoint": "^10.1.3",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"fast-content-type-parse": "^2.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
|
@ -306,9 +306,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/request-error": {
|
||||
"version": "6.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.6.tgz",
|
||||
"integrity": "sha512-pqnVKYo/at0NuOjinrgcQYpEbv4snvP3bKMRqHaD9kIsk9u1LCpb2smHZi8/qJfgeNqLo5hNW4Z7FezNdEo0xg==",
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz",
|
||||
"integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
@ -477,6 +477,16 @@
|
|||
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/expect": {
|
||||
"version": "1.20.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz",
|
||||
|
@ -484,9 +494,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
|
||||
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
|
||||
"version": "22.13.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
|
||||
"integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
|
@ -1201,9 +1211,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
|
||||
"integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
|
@ -1239,9 +1249,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001699",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz",
|
||||
"integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==",
|
||||
"version": "1.0.30001700",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
|
||||
"integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
@ -1995,9 +2005,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.96",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.96.tgz",
|
||||
"integrity": "sha512-8AJUW6dh75Fm/ny8+kZKJzI1pgoE8bKLZlzDU2W1ENd+DXKJrx7I7l9hb8UWR4ojlnb5OlixMt00QWiYJoVw1w==",
|
||||
"version": "1.5.101",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz",
|
||||
"integrity": "sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
|
@ -4967,18 +4977,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
|
||||
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jquery": {
|
||||
|
@ -4988,14 +4998,14 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-beautify": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.2.tgz",
|
||||
"integrity": "sha512-mcG6CHJxxih+EFAbd5NEBwrosIs6MoJmiNLFYN6kj5SeJMf7n29Ii/H4lt6zGTvmdB9AApuj5cs4zydjuLeqjw==",
|
||||
"version": "1.15.3",
|
||||
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.3.tgz",
|
||||
"integrity": "sha512-rKKGuyTxGNlyN4EQKWzNndzXpi0bOl8Gl8YQAW1as/oMz0XhD6sHJO1hTvoBDOSzKuJb9WkwoAb34FfdkKMv2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"config-chain": "^1.1.13",
|
||||
"editorconfig": "^1.0.4",
|
||||
"glob": "^11.0.0",
|
||||
"glob": "^10.4.2",
|
||||
"js-cookie": "^3.0.5",
|
||||
"nopt": "^8.0.0"
|
||||
},
|
||||
|
@ -5018,38 +5028,35 @@
|
|||
}
|
||||
},
|
||||
"node_modules/js-beautify/node_modules/glob": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
|
||||
"integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==",
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^4.0.1",
|
||||
"minimatch": "^10.0.0",
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^2.0.0"
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/js-beautify/node_modules/minimatch": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
|
||||
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
|
@ -5481,13 +5488,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
|
||||
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/macos-release": {
|
||||
"version": "2.5.1",
|
||||
|
@ -6467,16 +6471,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
|
||||
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
"minipass": "^7.1.2"
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
|
|
|
@ -30,7 +30,6 @@ const sfc = {
|
|||
intervalID: null,
|
||||
currentJobStepsStates: [],
|
||||
artifacts: [],
|
||||
onHoverRerunIndex: -1,
|
||||
menuVisible: false,
|
||||
isFullScreen: false,
|
||||
timeVisible: {
|
||||
|
@ -457,13 +456,13 @@ export function initRepositoryActionView() {
|
|||
<div class="action-view-left">
|
||||
<div class="job-group-section">
|
||||
<div class="job-brief-list">
|
||||
<a class="job-brief-item" :href="run.link+'/jobs/'+index" :class="parseInt(jobIndex) === index ? 'selected' : ''" v-for="(job, index) in run.jobs" :key="job.id" @mouseenter="onHoverRerunIndex = job.id" @mouseleave="onHoverRerunIndex = -1">
|
||||
<a class="job-brief-item" :href="run.link+'/jobs/'+index" :class="parseInt(jobIndex) === index ? 'selected' : ''" v-for="(job, index) in run.jobs" :key="job.id">
|
||||
<div class="job-brief-item-left">
|
||||
<ActionRunStatus :locale-status="locale.status[job.status]" :status="job.status"/>
|
||||
<span class="job-brief-name tw-mx-2 gt-ellipsis">{{ job.name }}</span>
|
||||
</div>
|
||||
<span class="job-brief-item-right">
|
||||
<SvgIcon name="octicon-sync" role="button" :data-tooltip-content="locale.rerun" class="job-brief-rerun tw-mx-2 link-action" :data-url="`${run.link}/jobs/${index}/rerun`" v-if="job.canRerun && onHoverRerunIndex === job.id"/>
|
||||
<SvgIcon name="octicon-sync" role="button" :data-tooltip-content="locale.rerun" class="job-brief-rerun tw-mx-3 link-action" :data-url="`${run.link}/jobs/${index}/rerun`" v-if="job.canRerun"/>
|
||||
<span class="step-summary-duration">{{ job.duration }}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
|
Loading…
Add table
Reference in a new issue