diff --git a/.github/issue_template.md b/.github/issue_template.md index 69ff704bbc14..95b97e4de5a6 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -30,6 +30,9 @@ ## Description + ... diff --git a/Makefile b/Makefile index 7dd7464acb2f..7d68e08fd0a4 100644 --- a/Makefile +++ b/Makefile @@ -573,7 +573,6 @@ release-windows: | $(DIST_DIRS) @hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ GO111MODULE=off $(GO) get -u src.techknowlogick.com/xgo; \ fi - @echo "Warning: windows version is built using golang 1.14" CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) . ifeq ($(CI),drone) cp /build/* $(DIST)/binaries @@ -709,7 +708,7 @@ pr\#%: clean-all golangci-lint: @hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ export BINARY="golangci-lint"; \ - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.35.2; \ + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.37.0; \ fi golangci-lint run --timeout 10m diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index 97882f9203b7..40933a7b333c 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -232,7 +232,7 @@ Generates a self-signed SSL certificate. Outputs to `cert.pem` and `key.pem` in directory and will overwrite any existing files. - Options: - - `--host value`: Comma seperated hostnames and ips which this certificate is valid for. + - `--host value`: Comma separated hostnames and ips which this certificate is valid for. Wildcards are supported. Required. - `--ecdsa-curve value`: ECDSA curve to use to generate a key. Optional. Valid options are P224, P256, P384, P521. diff --git a/integrations/api_admin_test.go b/integrations/api_admin_test.go index 79fdc4a9f701..fdcfc407892b 100644 --- a/integrations/api_admin_test.go +++ b/integrations/api_admin_test.go @@ -192,4 +192,18 @@ func TestAPIEditUser(t *testing.T) { errMap := make(map[string]interface{}) json.Unmarshal(resp.Body.Bytes(), &errMap) assert.EqualValues(t, "email is not allowed to be empty string", errMap["message"].(string)) + + user2 := models.AssertExistsAndLoadBean(t, &models.User{LoginName: "user2"}).(*models.User) + assert.Equal(t, false, user2.IsRestricted) + bTrue := true + req = NewRequestWithJSON(t, "PATCH", urlStr, api.EditUserOption{ + // required + LoginName: "user2", + SourceID: 0, + // to change + Restricted: &bTrue, + }) + session.MakeRequest(t, req, http.StatusOK) + user2 = models.AssertExistsAndLoadBean(t, &models.User{LoginName: "user2"}).(*models.User) + assert.Equal(t, true, user2.IsRestricted) } diff --git a/integrations/api_settings_test.go b/integrations/api_settings_test.go index 19a005387696..fdd8b02d625d 100644 --- a/integrations/api_settings_test.go +++ b/integrations/api_settings_test.go @@ -43,9 +43,11 @@ func TestAPIExposedSettings(t *testing.T) { DecodeJSON(t, resp, &repo) assert.EqualValues(t, &api.GeneralRepoSettings{ - MirrorsDisabled: setting.Repository.DisableMirrors, - HTTPGitDisabled: setting.Repository.DisableHTTPGit, - MigrationsDisabled: setting.Repository.DisableMigrations, + MirrorsDisabled: setting.Repository.DisableMirrors, + HTTPGitDisabled: setting.Repository.DisableHTTPGit, + MigrationsDisabled: setting.Repository.DisableMigrations, + TimeTrackingDisabled: false, + LFSDisabled: !setting.LFS.StartServer, }, repo) attachment := new(api.GeneralAttachmentSettings) diff --git a/models/action.go b/models/action.go index e8a1336566e1..47d056ae3a55 100644 --- a/models/action.go +++ b/models/action.go @@ -289,12 +289,13 @@ func (a *Action) GetIssueContent() string { // GetFeedsOptions options for retrieving feeds type GetFeedsOptions struct { - RequestedUser *User // the user we want activity for - RequestedTeam *Team // the team we want activity for - Actor *User // the user viewing the activity - IncludePrivate bool // include private actions - OnlyPerformedBy bool // only actions performed by requested user - IncludeDeleted bool // include deleted actions + RequestedUser *User // the user we want activity for + RequestedTeam *Team // the team we want activity for + Actor *User // the user viewing the activity + IncludePrivate bool // include private actions + OnlyPerformedBy bool // only actions performed by requested user + IncludeDeleted bool // include deleted actions + Date string // the day we want activity for: YYYY-MM-DD } // GetFeeds returns actions according to the provided options @@ -380,5 +381,17 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) { cond = cond.And(builder.Eq{"is_deleted": false}) } + if opts.Date != "" { + dateLow, err := time.Parse("2006-01-02", opts.Date) + if err != nil { + log.Warn("Unable to parse %s, filter not applied: %v", opts.Date, err) + } else { + dateHigh := dateLow.Add(86399000000000) // 23h59m59s + + cond = cond.And(builder.Gte{"created_unix": dateLow.Unix()}) + cond = cond.And(builder.Lte{"created_unix": dateHigh.Unix()}) + } + } + return cond, nil } diff --git a/models/action_test.go b/models/action_test.go index c6aaaaf06984..6dab676a706b 100644 --- a/models/action_test.go +++ b/models/action_test.go @@ -26,7 +26,7 @@ func TestAction_GetRepoLink(t *testing.T) { repo := AssertExistsAndLoadBean(t, &Repository{}).(*Repository) owner := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User) action := &Action{RepoID: repo.ID} - setting.AppSubURL = "/suburl/" + setting.AppSubURL = "/suburl" expected := path.Join(setting.AppSubURL, owner.Name, repo.Name) assert.Equal(t, expected, action.GetRepoLink()) } diff --git a/models/issue_comment.go b/models/issue_comment.go index b15b5169ff4c..6cc03ba0e8af 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -136,6 +136,8 @@ type Comment struct { MilestoneID int64 OldMilestone *Milestone `xorm:"-"` Milestone *Milestone `xorm:"-"` + TimeID int64 + Time *TrackedTime `xorm:"-"` AssigneeID int64 RemovedAssignee bool Assignee *User `xorm:"-"` @@ -541,6 +543,16 @@ func (c *Comment) LoadDepIssueDetails() (err error) { return err } +// LoadTime loads the associated time for a CommentTypeAddTimeManual +func (c *Comment) LoadTime() error { + if c.Time != nil || c.TimeID == 0 { + return nil + } + var err error + c.Time, err = GetTrackedTimeByID(c.TimeID) + return err +} + func (c *Comment) loadReactions(e Engine, repo *Repository) (err error) { if c.Reactions != nil { return nil @@ -692,6 +704,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err MilestoneID: opts.MilestoneID, OldProjectID: opts.OldProjectID, ProjectID: opts.ProjectID, + TimeID: opts.TimeID, RemovedAssignee: opts.RemovedAssignee, AssigneeID: opts.AssigneeID, AssigneeTeamID: opts.AssigneeTeamID, @@ -859,6 +872,7 @@ type CreateCommentOptions struct { MilestoneID int64 OldProjectID int64 ProjectID int64 + TimeID int64 AssigneeID int64 AssigneeTeamID int64 RemovedAssignee bool diff --git a/models/issue_stopwatch.go b/models/issue_stopwatch.go index a1c88503d899..19bd4ab2c569 100644 --- a/models/issue_stopwatch.go +++ b/models/issue_stopwatch.go @@ -100,6 +100,7 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error { Repo: issue.Repo, Content: SecToTime(timediff), Type: CommentTypeStopTracking, + TimeID: tt.ID, }); err != nil { return err } diff --git a/models/issue_tracked_time.go b/models/issue_tracked_time.go index 195f3e785034..9717944cbb38 100644 --- a/models/issue_tracked_time.go +++ b/models/issue_tracked_time.go @@ -162,6 +162,7 @@ func AddTime(user *User, issue *Issue, amount int64, created time.Time) (*Tracke Doer: user, Content: SecToTime(amount), Type: CommentTypeAddTimeManual, + TimeID: t.ID, }); err != nil { return nil, err } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 740e8cb3ee97..4fc737e1bfe4 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -292,6 +292,8 @@ var migrations = []Migration{ NewMigration("Add Sorting to ProjectBoard table", addSortingColToProjectBoard), // v172 -> v173 NewMigration("Add sessions table for go-chi/session", addSessionTable), + // v173 -> v174 + NewMigration("Add time_id column to Comment", addTimeIDCommentColumn), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v166.go b/models/migrations/v166.go index 3d6cf4f57f54..1b6e68b5733a 100644 --- a/models/migrations/v166.go +++ b/models/migrations/v166.go @@ -106,10 +106,8 @@ func recalculateUserEmptyPWD(x *xorm.Engine) (err error) { } // delete salt and algo where password is empty - if _, err = sess.Where(builder.Eq{"passwd": ""}.And(builder.Neq{"salt": ""}.Or(builder.Neq{"passwd_hash_algo": ""}))). - Cols("salt", "passwd_hash_algo").Update(&User{}); err != nil { - return err - } + _, err = sess.Where(builder.Eq{"passwd": ""}.And(builder.Neq{"salt": ""}.Or(builder.Neq{"passwd_hash_algo": ""}))). + Cols("salt", "passwd_hash_algo").Update(&User{}) - return sess.Commit() + return err } diff --git a/models/migrations/v173.go b/models/migrations/v173.go new file mode 100644 index 000000000000..dd4589066d9d --- /dev/null +++ b/models/migrations/v173.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "xorm.io/xorm" +) + +func addTimeIDCommentColumn(x *xorm.Engine) error { + type Comment struct { + TimeID int64 + } + + if err := x.Sync2(new(Comment)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + return nil +} diff --git a/models/notification.go b/models/notification.go index 362b49099407..32f3079bf417 100644 --- a/models/notification.go +++ b/models/notification.go @@ -6,7 +6,7 @@ package models import ( "fmt" - "path" + "strconv" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -413,7 +413,7 @@ func (n *Notification) HTMLURL() string { // APIURL formats a URL-string to the notification func (n *Notification) APIURL() string { - return setting.AppURL + path.Join("api/v1/notifications/threads", fmt.Sprintf("%d", n.ID)) + return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10) } // NotificationList contains a list of notifications diff --git a/models/pull.go b/models/pull.go index 0d4691aac94b..0eba65db4fad 100644 --- a/models/pull.go +++ b/models/pull.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" ) // PullRequestType defines pull request type @@ -638,3 +639,27 @@ func (pr *PullRequest) updateCommitDivergence(e Engine, ahead, behind int) error func (pr *PullRequest) IsSameRepo() bool { return pr.BaseRepoID == pr.HeadRepoID } + +// GetBaseBranchHTMLURL returns the HTML URL of the base branch +func (pr *PullRequest) GetBaseBranchHTMLURL() string { + if err := pr.LoadBaseRepo(); err != nil { + log.Error("LoadBaseRepo: %v", err) + return "" + } + if pr.BaseRepo == nil { + return "" + } + return pr.BaseRepo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(pr.BaseBranch) +} + +// GetHeadBranchHTMLURL returns the HTML URL of the head branch +func (pr *PullRequest) GetHeadBranchHTMLURL() string { + if err := pr.LoadHeadRepo(); err != nil { + log.Error("LoadHeadRepo: %v", err) + return "" + } + if pr.HeadRepo == nil { + return "" + } + return pr.HeadRepo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(pr.HeadBranch) +} diff --git a/models/repo.go b/models/repo.go index 62d64fbee918..03259d9e347a 100644 --- a/models/repo.go +++ b/models/repo.go @@ -264,7 +264,7 @@ func (repo *Repository) ColorFormat(s fmt.State) { repo.Name) } -// IsBeingMigrated indicates that repository is being migtated +// IsBeingMigrated indicates that repository is being migrated func (repo *Repository) IsBeingMigrated() bool { return repo.Status == RepositoryBeingMigrated } @@ -318,7 +318,7 @@ func (repo *Repository) CommitLink(commitID string) (result string) { // APIURL returns the repository API URL func (repo *Repository) APIURL() string { - return setting.AppURL + path.Join("api/v1/repos", repo.FullName()) + return setting.AppURL + "api/v1/repos/" + repo.FullName() } // GetCommitsCountCacheKey returns cache key used for commits count caching. @@ -613,7 +613,7 @@ func (repo *Repository) getReviewers(e Engine, doerID, posterID int64) ([]*User, // * for private repositories this returns all users that have read access or higher to the repository. // * for public repositories this returns all users that have write access or higher to the repository, // and all repo watchers. -// TODO: may be we should hava a busy choice for users to block review request to them. +// TODO: may be we should have a busy choice for users to block review request to them. func (repo *Repository) GetReviewers(doerID, posterID int64) ([]*User, error) { return repo.getReviewers(x, doerID, posterID) } diff --git a/models/user_avatar.go b/models/user_avatar.go index 1e9f0e2da405..871e176599cf 100644 --- a/models/user_avatar.go +++ b/models/user_avatar.go @@ -63,7 +63,7 @@ func (u *User) generateRandomAvatar(e Engine) error { // the local explore page. Function returns immediately. // When applicable, the link is for an avatar of the indicated size (in pixels). func (u *User) SizedRelAvatarLink(size int) string { - return strings.TrimSuffix(setting.AppSubURL, "/") + "/user/avatar/" + u.Name + "/" + strconv.Itoa(size) + return setting.AppSubURL + "/user/avatar/" + u.Name + "/" + strconv.Itoa(size) } // RealSizedAvatarLink returns a link to the user's avatar. When diff --git a/modules/context/context.go b/modules/context/context.go index bc48c1415de2..ea267dfb3fc6 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -188,6 +188,10 @@ func (ctx *Context) HTML(status int, name base.TplName) { return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms" } if err := ctx.Render.HTML(ctx.Resp, status, string(name), ctx.Data); err != nil { + if status == http.StatusInternalServerError && name == base.TplName("status/500") { + ctx.PlainText(http.StatusInternalServerError, []byte("Unable to find status/500 template")) + return + } ctx.ServerError("Render failed", err) } } diff --git a/modules/convert/user.go b/modules/convert/user.go index 010c92b969bb..f5d853fd4d10 100644 --- a/modules/convert/user.go +++ b/modules/convert/user.go @@ -17,12 +17,13 @@ func ToUser(user *models.User, signed, authed bool) *api.User { return nil } result := &api.User{ - ID: user.ID, - UserName: user.Name, - FullName: markup.Sanitize(user.FullName), - Email: user.GetEmail(), - AvatarURL: user.AvatarLink(), - Created: user.CreatedUnix.AsTime(), + ID: user.ID, + UserName: user.Name, + FullName: markup.Sanitize(user.FullName), + Email: user.GetEmail(), + AvatarURL: user.AvatarLink(), + Created: user.CreatedUnix.AsTime(), + Restricted: user.IsRestricted, } // hide primary email if API caller is anonymous or user keep email private if signed && (!user.KeepEmailPrivate || authed) { diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index a43fe4b3349f..0a92de17037e 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -8,6 +8,7 @@ package git import ( "bufio" + "errors" "fmt" "io" "io/ioutil" @@ -70,10 +71,15 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) { bufReader := bufio.NewReader(stdoutReader) _, typ, size, err := ReadBatchLine(bufReader) if err != nil { + if errors.Is(err, io.EOF) { + return nil, ErrNotExist{ID: id.String()} + } return nil, err } switch typ { + case "missing": + return nil, ErrNotExist{ID: id.String()} case "tag": // then we need to parse the tag // and load the commit diff --git a/modules/markup/html.go b/modules/markup/html.go index 67aec7371c8d..b254fd083f6b 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -89,11 +89,7 @@ func isLinkStr(link string) bool { func getIssueFullPattern() *regexp.Regexp { if issueFullPattern == nil { - appURL := setting.AppURL - if len(appURL) > 0 && appURL[len(appURL)-1] != '/' { - appURL += "/" - } - issueFullPattern = regexp.MustCompile(appURL + + issueFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) + `\w+/\w+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#]\S+.(\S+)?)?\b`) } return issueFullPattern @@ -324,8 +320,30 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { // give a generous extra 50 bytes res := make([]byte, 0, len(rawHTML)+50) + + // prepend "" res = append(res, ""...) - res = append(res, rawHTML...) + + // Strip out nuls - they're always invalid + start := bytes.IndexByte(rawHTML, '\000') + if start >= 0 { + res = append(res, rawHTML[:start]...) + start++ + for start < len(rawHTML) { + end := bytes.IndexByte(rawHTML[start:], '\000') + if end < 0 { + res = append(res, rawHTML[start:]...) + break + } else if end > 0 { + res = append(res, rawHTML[start:start+end]...) + } + start += end + 1 + } + } else { + res = append(res, rawHTML...) + } + + // close the tags res = append(res, ""...) // parse the HTML @@ -614,6 +632,9 @@ func mentionProcessor(ctx *postProcessCtx, node *html.Node) { mention := node.Data[loc.Start:loc.End] var teams string teams, ok := ctx.metas["teams"] + // FIXME: util.URLJoin may not be necessary here: + // - setting.AppURL is defined to have a terminal '/' so unless mention[1:] + // is an AppSubURL link we can probably fallback to concatenation. // team mention should follow @orgName/teamName style if ok && strings.Contains(mention, "/") { mentionOrgAndTeam := strings.Split(mention, "/") diff --git a/modules/setting/setting.go b/modules/setting/setting.go index be7ec16e10cc..783e440da1a9 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -66,17 +66,31 @@ const ( // settings var ( - // AppVer settings - AppVer string - AppBuiltWith string - AppStartTime time.Time - AppName string - AppURL string - AppSubURL string - AppSubURLDepth int // Number of slashes - AppPath string - AppDataPath string - AppWorkPath string + // AppVer is the version of the current build of Gitea. It is set in main.go from main.Version. + AppVer string + // AppBuiltWith represents a human readable version go runtime build version and build tags. (See main.go formatBuiltWith().) + AppBuiltWith string + // AppStartTime store time gitea has started + AppStartTime time.Time + // AppName is the Application name, used in the page title. + // It maps to ini:"APP_NAME" + AppName string + // AppURL is the Application ROOT_URL. It always has a '/' suffix + // It maps to ini:"ROOT_URL" + AppURL string + // AppSubURL represents the sub-url mounting point for gitea. It is either "" or starts with '/' and ends without '/', such as '/{subpath}'. + // This value is empty if site does not have sub-url. + AppSubURL string + // AppPath represents the path to the gitea binary + AppPath string + // AppWorkPath is the "working directory" of Gitea. It maps to the environment variable GITEA_WORK_DIR. + // If that is not set it is the default set here by the linker or failing that the directory of AppPath. + // + // AppWorkPath is used as the base path for several other paths. + AppWorkPath string + // AppDataPath is the default path for storing data. + // It maps to ini:"APP_DATA_PATH" and defaults to AppWorkPath + "/data" + AppDataPath string // Server settings Protocol Scheme @@ -594,8 +608,9 @@ func NewContext() { if (Protocol == HTTP && HTTPPort != "80") || (Protocol == HTTPS && HTTPPort != "443") { defaultAppURL += ":" + HTTPPort } - AppURL = sec.Key("ROOT_URL").MustString(defaultAppURL) - AppURL = strings.TrimSuffix(AppURL, "/") + "/" + AppURL = sec.Key("ROOT_URL").MustString(defaultAppURL + "/") + // This should be TrimRight to ensure that there is only a single '/' at the end of AppURL. + AppURL = strings.TrimRight(AppURL, "/") + "/" // Check if has app suburl. appURL, err := url.Parse(AppURL) @@ -606,7 +621,7 @@ func NewContext() { // This value is empty if site does not have sub-url. AppSubURL = strings.TrimSuffix(appURL.Path, "/") StaticURLPrefix = strings.TrimSuffix(sec.Key("STATIC_URL_PREFIX").MustString(AppSubURL), "/") - AppSubURLDepth = strings.Count(AppSubURL, "/") + // Check if Domain differs from AppURL domain than update it to AppURL's domain urlHostname := appURL.Hostname() if urlHostname != Domain && net.ParseIP(urlHostname) == nil && urlHostname != "" { diff --git a/modules/structs/admin_user.go b/modules/structs/admin_user.go index 8cd4dc59e861..ee1738579ab7 100644 --- a/modules/structs/admin_user.go +++ b/modules/structs/admin_user.go @@ -41,4 +41,5 @@ type EditUserOption struct { MaxRepoCreation *int `json:"max_repo_creation"` ProhibitLogin *bool `json:"prohibit_login"` AllowCreateOrganization *bool `json:"allow_create_organization"` + Restricted *bool `json:"restricted"` } diff --git a/modules/structs/settings.go b/modules/structs/settings.go index 5fd916affe91..e15c750356f6 100644 --- a/modules/structs/settings.go +++ b/modules/structs/settings.go @@ -6,9 +6,11 @@ package structs // GeneralRepoSettings contains global repository settings exposed by API type GeneralRepoSettings struct { - MirrorsDisabled bool `json:"mirrors_disabled"` - HTTPGitDisabled bool `json:"http_git_disabled"` - MigrationsDisabled bool `json:"migrations_disabled"` + MirrorsDisabled bool `json:"mirrors_disabled"` + HTTPGitDisabled bool `json:"http_git_disabled"` + MigrationsDisabled bool `json:"migrations_disabled"` + TimeTrackingDisabled bool `json:"time_tracking_disabled"` + LFSDisabled bool `json:"lfs_disabled"` } // GeneralUISettings contains global ui settings exposed by API diff --git a/modules/structs/user.go b/modules/structs/user.go index bf52cc9ed653..511e4c56ce24 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -30,6 +30,8 @@ type User struct { LastLogin time.Time `json:"last_login,omitempty"` // swagger:strfmt date-time Created time.Time `json:"created,omitempty"` + // Is user restricted + Restricted bool `json:"restricted"` } // MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 00ccd49cb401..4b9b648b2f79 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -174,6 +174,9 @@ func NewFuncMap() []template.FuncMap { "UseServiceWorker": func() bool { return setting.UI.UseServiceWorker }, + "EnableTimetracking": func() bool { + return setting.Service.EnableTimetracking + }, "FilenameIsImage": func(filename string) bool { mimeType := mime.TypeByExtension(filepath.Ext(filename)) return strings.HasPrefix(mimeType, "image/") diff --git a/options/license/DRL-1.0 b/options/license/DRL-1.0 new file mode 100644 index 000000000000..880686000faa --- /dev/null +++ b/options/license/DRL-1.0 @@ -0,0 +1,28 @@ +Detection Rule License (DRL) 1.0 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this rule set and associated documentation files (the "Rules"), to deal +in the Rules without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Rules, and to permit persons to whom the Rules are furnished +to do so, subject to the following conditions: + +If you share the Rules (including in modified form), you must retain the following +if it is supplied within the Rules: + +identification of the authors(s) ("author" field) of the Rule and any others +designated to receive attribution, in any reasonable manner requested by the +Rule author (including by pseudonym if designated). + +a URI or hyperlink to the Rule set or explicit Rule to the extent reasonably +practicable + +indicate the Rules are licensed under this Detection Rule License, and include +the text of, or the URI or hyperlink to, this Detection Rule License to the +extent reasonably practicable + +THE RULES ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR +A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE RULES OR THE USE OR OTHER DEALINGS IN THE RULES. diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index db444f8e20f2..3bc36b57bd4d 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -2051,7 +2051,6 @@ dashboard.cron.error=Chyba v naplánované úloze: %s: %[3]s dashboard.cron.finished=Naplánovaná úloha: %[1]s skončila dashboard.delete_inactive_accounts=Smazat všechny neaktivované účty dashboard.delete_inactive_accounts.started=Spuštěna úloha mazání všech neaktivovaných účtů. -dashboard.delete_repo_archives=Smazat všechny archivy repozitáře dashboard.delete_repo_archives.started=Spuštěna úloha smazání všech archivovaných repozitářů. dashboard.delete_missing_repos=Smazat všechny repozitáře, které nemají Git soubory dashboard.delete_missing_repos.started=Spuštěna úloha mazání všech repozitářů, které nemají Git soubory. diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index ee9e9dc678b3..980bb09f5dd6 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -2044,7 +2044,6 @@ dashboard.cron.error=Fehler in Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s ist beendet dashboard.delete_inactive_accounts=Alle nicht aktivierten Konten löschen dashboard.delete_inactive_accounts.started=Löschen aller nicht aktivierten Account-Aufgabe gestartet. -dashboard.delete_repo_archives=Alle Repository-Archive löschen dashboard.delete_repo_archives.started=Löschen aller Repository-Archive gestartet. dashboard.delete_missing_repos=Alle Repository-Datensätze mit verloren gegangenen Git-Dateien löschen dashboard.delete_missing_repos.started=Alle Repositories löschen, die die Git-Dateien-Aufgabe nicht gestartet haben. diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 8b0e5fd8bec0..8245df754a70 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -665,6 +665,7 @@ email_notifications.disable = Disable Email Notifications email_notifications.submit = Set Email Preference [repo] +new_repo_helper = A repository contains all project files, including revision history. Already have it elsewhere? Migrate repository. owner = Owner owner_helper = Some organizations may not show up in the dropdown due to a maximum repository count limit. repo_name = Repository Name @@ -687,17 +688,27 @@ use_template = Use this template generate_repo = Generate Repository generate_from = Generate From repo_desc = Description +repo_desc_helper = Enter short description (optional) repo_lang = Language repo_gitignore_helper = Select .gitignore templates. +repo_gitignore_helper_desc = Choose which files not to track from a list of templates for common languages. Typical artifacts generated by each language's build tools are included on .gitignore by default. issue_labels = Issue Labels issue_labels_helper = Select an issue label set. license = License license_helper = Select a license file. +license_helper_desc = A license governs what others can and can't do with your code. Not sure which one is right for your project? See Choose a license. readme = README readme_helper = Select a README file template. +readme_helper_desc = This is the place where you can write a complete description for your project. auto_init = Initialize Repository (Adds .gitignore, License and README) +trust_model_helper = Select trust model for signature verification. Possible options are: +trust_model_helper_collaborator = Collaborator: Trust signatures by collaborators +trust_model_helper_committer = Committer: Trust signatures that match committers +trust_model_helper_collaborator_committer = Collaborator+Committer: Trust signatures by collaborators which match the committer +trust_model_helper_default = Default: Use the default trust model for this installation create_repo = Create Repository default_branch = Default Branch +default_branch_helper = The default branch is the base branch for pull requests and code commits. mirror_prune = Prune mirror_prune_desc = Remove obsolete remote-tracking references mirror_interval = Mirror Interval (valid time units are 'h', 'm', 's'). 0 to disable automatic sync. @@ -1163,6 +1174,7 @@ issues.stop_tracking_history = `stopped working %s` issues.cancel_tracking = Discard issues.cancel_tracking_history = `cancelled time tracking %s` issues.add_time = Manually Add Time +issues.del_time = Delete this time log issues.add_time_short = Add Time issues.add_time_cancel = Cancel issues.add_time_history = `added spent time %s` @@ -2059,7 +2071,7 @@ dashboard.cron.error=Error in Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s has finished dashboard.delete_inactive_accounts = Delete all unactivated accounts dashboard.delete_inactive_accounts.started = Delete all unactivated accounts task started. -dashboard.delete_repo_archives = Delete all repository archives +dashboard.delete_repo_archives = "Delete all repositories' archives (ZIP, TAR.GZ, etc..)" dashboard.delete_repo_archives.started = Delete all repository archives task started. dashboard.delete_missing_repos = Delete all repositories missing their Git files dashboard.delete_missing_repos.started = Delete all repositories missing their Git files task started. diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 95fe653e74c6..53f58617e769 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -2023,7 +2023,6 @@ dashboard.cron.error=Error en Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s ha finalizado dashboard.delete_inactive_accounts=Eliminar todas las cuentas inactivas dashboard.delete_inactive_accounts.started=Se ha iniciado la tarea: "Eliminar todas las cuentas inactivas". -dashboard.delete_repo_archives=Eliminar todos los archivos de repositorios dashboard.delete_repo_archives.started=Se ha iniciado la tarea: "Eliminar todos los archivos del repositorios". dashboard.delete_missing_repos=Eliminar todos los repositorios que faltan sus archivos Git dashboard.delete_missing_repos.started=Se ha iniciado la tarea: "Eliminar todos los repositorios que faltan sus archivos Git". diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 52f55dab58ff..46179585aef9 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -1792,7 +1792,6 @@ dashboard.operation_switch=تعویض dashboard.operation_run=اجرا dashboard.clean_unbind_oauth=تمیز کردن اتصال بدون مرز OAuth dashboard.clean_unbind_oauth_success=تمامی اتصالات بدون مرز OAuth حذف شدند. -dashboard.delete_repo_archives=حذف تمامی مخازن بایگانی شده dashboard.delete_missing_repos=حذف تمامی مخازنی که پرونده‌های گیت آنها از بین رفته است dashboard.delete_generated_repository_avatars=حذف آواتار هایی که برای مخزن تولید شده اند dashboard.git_gc_repos=متراکم کردن تمامی زباله‌های مخازن diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 25e72f691485..e92d0a5410f7 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -1808,7 +1808,6 @@ dashboard.operation_switch=Basculer dashboard.operation_run=Exécuter dashboard.clean_unbind_oauth=Effacer les connexions OAuth associées dashboard.clean_unbind_oauth_success=Toutes les connexions OAuth associées ont été supprimées. -dashboard.delete_repo_archives=Supprimer toutes les archives du dépôt dashboard.delete_missing_repos=Supprimer tous les dépôts dont les fichiers Git sont manquants dashboard.delete_generated_repository_avatars=Supprimer les avatars de dépôt générés dashboard.check_repo_stats=Voir les statistiques de tous les dépôts diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index d654172ce49b..480d38485929 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -1925,7 +1925,6 @@ dashboard.cron.error=Errore in Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s ha finito dashboard.delete_inactive_accounts=Elimina tutti gli account non attivati dashboard.delete_inactive_accounts.started=Attività di eliminazione degli account non attivati iniziata. -dashboard.delete_repo_archives=Elimina tutti gli archivi dei repository dashboard.delete_repo_archives.started=Attività di eliminazione degli archivi del repository iniziata. dashboard.delete_missing_repos=Elimina tutti i repository mancanti dei loro file Git dashboard.delete_missing_repos.started=Elimina tutti i repository mancanti dei loro file Git. diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 84b4d1975a72..e9714148d41f 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -205,6 +205,8 @@ default_enable_timetracking=デフォルトでタイムトラッキング有効 default_enable_timetracking_popup=新しいリポジトリのタイムトラッキングをデフォルトで有効にします。 no_reply_address=メールを隠すときのドメイン no_reply_address_helper=メールアドレスを隠しているユーザーに使用するドメイン名。 例えば 'noreply.example.org' と設定した場合、ユーザー名 'joe' はGitに 'joe@noreply.example.org' としてログインすることになります。 +password_algorithm=パスワードハッシュアルゴリズム +password_algorithm_helper=パスワードハッシュアルゴリズムを設定します。 アルゴリズムにより動作要件と強度が異なります。 `argon2`は良い特性を備えていますが、多くのメモリを使用するため小さなシステムには適さない場合があります。 [home] uname_holder=ユーザー名またはメールアドレス @@ -1160,6 +1162,7 @@ issues.stop_tracking_history=`が作業を終了 %s` issues.cancel_tracking=中止 issues.cancel_tracking_history=`がタイムトラッキングを中止 %s` issues.add_time=手で時間を入力 +issues.del_time=このタイムログを削除 issues.add_time_short=時間入力 issues.add_time_cancel=キャンセル issues.add_time_history=`が作業時間を追加 %s` @@ -2056,7 +2059,7 @@ dashboard.cron.error=Cronでエラー: %s: %[3]s dashboard.cron.finished=Cron: %[1]s が完了 dashboard.delete_inactive_accounts=アクティベートされていないアカウントをすべて削除 dashboard.delete_inactive_accounts.started=アクティベートされていないアカウントをすべて削除するタスクを開始しました。 -dashboard.delete_repo_archives=リポジトリアーカイブをすべて削除 +dashboard.delete_repo_archives=リポジトリのアーカイブ (ZIP, TAR.GZ, etc..) をすべて削除 dashboard.delete_repo_archives.started=リポジトリアーカイブをすべて削除するタスクを開始しました。 dashboard.delete_missing_repos=Gitファイルが存在しないリポジトリをすべて削除 dashboard.delete_missing_repos.started=Gitファイルが存在しないリポジトリをすべて削除するタスクを開始しました。 diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index 7ac1b62ad42d..039634d6b155 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -1278,7 +1278,6 @@ dashboard.system_status=시스템 상태 dashboard.operation_name=작업 명 dashboard.operation_switch=스위치 dashboard.operation_run=실행 -dashboard.delete_repo_archives=모든 저장소 아카이브 삭제 dashboard.git_gc_repos=모든 저장소 가비지 콜렉트 dashboard.sync_external_users=외부 사용자 데이터 동기화 dashboard.server_uptime=서버를 켠 시간 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 8db1862aece4..6c90dc74865d 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -1973,7 +1973,6 @@ dashboard.cron.error=Kļūda Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s pabeigts dashboard.delete_inactive_accounts=Dzēst visus neaktivizētos kontus dashboard.delete_inactive_accounts.started=Uzdevums visu neaktivizēto kontu dzēšanai uzsākts. -dashboard.delete_repo_archives=Dzēst visu repozitoriju arhīvus dashboard.delete_repo_archives.started=Uzdevums visu repozitoriju arhīvu dzēšanai uzsākts. dashboard.delete_missing_repos=Dzēst visus repozitorijus, kam trūkst Git failu dashboard.delete_missing_repos.started=Uzdevums visu repozitoriju dzēšanai, kam trūkst git failu, uzsākts. diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index 3e52ca2de0fe..c8bcbd9c8a80 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -1251,6 +1251,7 @@ pulls.require_signed_wont_sign=De branch heeft ondertekende commits nodig, maar pulls.invalid_merge_option=Je kan de samenvoegingsoptie niet gebruiken voor deze pull-aanvraag. pulls.merge_conflict=Samenvoegen mislukt: Er was een conflict tijdens het samenvoegen. Hint: Probeer een andere strategie pulls.merge_conflict_summary=Foutmelding +pulls.rebase_conflict=Samenvoegen mislukt: Er was een conflict tijdens het rebasen van commit: %[1]s. Hint: Probeer een andere strategie pulls.rebase_conflict_summary=Foutmelding ; %[2]s
%[3]s
pulls.unrelated_histories=Samenvoegen mislukt: de HEAD en base delen geen gemeenschappelijke geschiedenis. Tip: Probeer een andere strategie @@ -1494,6 +1495,7 @@ settings.trust_model.collaborator.long=Medewerker: Vertrouw handtekeningen door settings.trust_model.collaborator.desc=Geldige handtekeningen door medewerkers van deze repository worden gemarkeerd als "vertrouwd" - (ongeacht of ze overeenkomen met de committer of niet). Anders worden geldige handtekeningen gemarkeerd als "niet vertrouwd" als de handtekening overeenkomt met de committer en "niet overeenkomend" als dat niet het geval is. settings.trust_model.committer=Committer settings.trust_model.committer.long=Committer: Vertrouw handtekeningen die overeenkomen met committers (Dit komt overeen met GitHub en zal Gitea ondertekende commits dwingen om Gitea als de committer te hebben) +settings.trust_model.committer.desc=Geldige handtekeningen worden alleen gemarkeerd als "vertrouwd" als ze overeenkomen met de committer, anders worden ze gemarkeerd als "niet overeenkomend". Dit zal Gitea dwingen om de committer te zijn aan ondertekende commits met de eigenlijke committer gemarkeerd als Co-Authored-By: en Co-Committed-By: trailer in de commit. De standaard Gitea-sleutel moet overeenkomen met een gebruiker in de database. settings.trust_model.collaboratorcommitter=Medewerker+Committer settings.trust_model.collaboratorcommitter.long=Medewerker+Committer: Vertrouw handtekeningen door medewerkers die overeenkomen met de committer settings.wiki_delete=Wiki-gegevens verwijderen @@ -1698,6 +1700,7 @@ settings.matrix.access_token=Toegangstoken settings.matrix.message_type=Bericht type settings.archive.button=Repo archiveren settings.archive.header=Deze Repo archiveren +settings.archive.text=Het archiveren van de repository maakt deze volledig alleen-lezen. Het is verborgen op het dashboard, er kan niet naar worden gecommit, en er kunnen geen kwesties of pull-aanvragen worden aangemaakt. settings.archive.success=De repo is succesvol gearchiveerd. settings.archive.error=Er is een fout opgetreden tijdens het archiveren van de repo. Zie het logboek voor meer informatie. settings.archive.error_ismirror=U kunt geen gespiegelde repo archiveren. @@ -1819,6 +1822,7 @@ branch.create_from=van '%s' branch.create_success=Branch '%s' is aangemaakt. branch.branch_already_exists=Branch '%s' bestaat al in deze repository. branch.branch_name_conflict=Branch naam '%s' conflicteert met de reeds bestaande branch '%s'. +branch.tag_collision=Branch '%s' kan niet worden aangemaakt als een label als dezelfde naam al bestaat in de repository. branch.deleted_by=Verwijderd door %s branch.restore_success=Branch '%s' is hersteld. branch.restore_failed=Herstellen van branch '%s' is mislukt. @@ -1880,9 +1884,11 @@ settings.change_orgname_prompt=Opmerking: het wijzigen van de organisatienaam ve settings.update_avatar_success=De avatar van de organisatie is aangepast. settings.delete=Verwijder organisatie settings.delete_account=Verwijder deze organisatie +settings.delete_prompt=Deze organisatie zal permanent worden verwijderd. U kunt dit NIET ongedaan maken! settings.confirm_delete_account=Bevestig verwijdering settings.delete_org_title=Verwijder organisatie settings.delete_org_desc=Deze organisatie zal permanent verwijderd worden. Doorgaan? +settings.hooks_desc=Een webhook toevoegen die door alle repositories in deze organisatie getriggerd kan worden. settings.labels_desc=Voeg labels toe die kunnen worden gebruikt bij problemen voor alle repositories in deze organisatie. @@ -1922,6 +1928,7 @@ teams.delete_team_success=Het team is verwijderd. teams.read_permission_desc=Dit team heeft Lees rechten: leden kunnen repositories lezen en klonen. teams.write_permission_desc=Dit team heeft Schrijf rechten: leden kunnen repositories lezen en push aanvragen verwerken. teams.admin_permission_desc=Dit team heeft beheersrechten: leden kunnen van en naar teamrepositories pullen, pushen, en er medewerkers aan toevoegen. +teams.create_repo_permission_desc=Daarnaast verleent dit team Maak repository permissie: leden kunnen nieuwe repositories maken in de organisatie. teams.repositories=Teamrepositories teams.search_repo_placeholder=Repository zoeken… teams.remove_all_repos_title=Verwijder alle team repositories @@ -1933,6 +1940,7 @@ teams.add_duplicate_users=Gebruiker is al een teamlid. teams.repos.none=Er konden geen repositories worden benaderd door dit team. teams.members.none=Geen leden in dit team. teams.specific_repositories=Specifieke repositories +teams.specific_repositories_helper=Leden zullen alleen toegang hebben tot repositories die expliciet aan het team zijn toegevoegd. Door dit te selecteren, worden niet repositories die al zijn toegevoegd met Alle repositories. teams.all_repositories=Alle repositories teams.all_repositories_helper=Team heeft toegang tot alle repositories. Door dit te selecteren worden alle bestaande repositories aan het team toegevoegd. teams.all_repositories_read_permission_desc=Dit team heeft Lees toegang tot alle repositories: leden kunnen repositories bekijken en klonen. @@ -1973,7 +1981,6 @@ dashboard.cron.error=Fout in cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s is klaar dashboard.delete_inactive_accounts=Verwijder alle niet geactiveerde accounts dashboard.delete_inactive_accounts.started=Verwijder alle niet geactiveerde accounts taak gestart. -dashboard.delete_repo_archives=Verwijder alle repositories archieven dashboard.delete_repo_archives.started=Verwijder alle repositoryarchieven taak gestart. dashboard.delete_missing_repos=Verwijder alle repositories waarvan hun Git bestanden missen dashboard.delete_missing_repos.started=Verwijder alle repositories die hun Git bestanden missen taak gestart. @@ -2157,6 +2164,7 @@ auths.sspi_strip_domain_names=Verwijder domeinnamen uit gebruikersnamen auths.sspi_separator_replacement=Scheidingsteken voor gebruik in plaats van \, / en @ auths.sspi_separator_replacement_helper=Het karakter dat moet worden gebruikt om de scheidingstekens van namen op downniveau logon te vervangen (bijv. de \ in "DOMAIN\user") en gebruikersverantwoordelijken (bijv. de @ in "user@example.org"). auths.sspi_default_language=Standaard gebruikerstaal +auths.sspi_default_language_helper=Standaardtaal voor gebruikers wordt automatisch gemaakt met SSPI authenticatiemethode. Laat leeg als u de taal automatisch wilt detecteren. auths.tips=Tips auths.tips.oauth2.general=OAuth2 authenticatie auths.tip.oauth2_provider=OAuth2 Provider @@ -2455,6 +2463,7 @@ error.generate_hash=Genereren van commit hash mislukt error.no_committer_account=Geen account gekoppeld aan het e-mailadres van de committer error.no_gpg_keys_found=Geen bekende sleutel gevonden voor deze handtekening in de database error.not_signed_commit=Geen ondertekende commit +error.probable_bad_default_signature=WAARSCHUWING! Hoewel de standaard sleutel dit ID heeft, is deze commit niet geverifieerd! Deze commit is VERDACHT. [units] error.no_unit_allowed_repo=U heeft geen toegang tot een enkele sectie van deze repository. diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index f96650e38aec..fab6e004abc1 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -1896,7 +1896,6 @@ dashboard.cron.error=Błąd w Cronie: %s: %[3]s dashboard.cron.finished=Cron: %[1]s zakończony dashboard.delete_inactive_accounts=Usuń wszystkie nieaktywowane konta dashboard.delete_inactive_accounts.started=Zadanie usuwania nieaktywowanych kont zostało rozpoczęte. -dashboard.delete_repo_archives=Usuń wszystkie archiwa repozytoriów dashboard.delete_repo_archives.started=Zadanie usuwania archiwów repozytoriów zostało rozpoczęte. dashboard.delete_missing_repos=Usuń wszystkie repozytoria, które nie mają plików Gita dashboard.delete_missing_repos.started=Zadanie usuwania repozytoriów, które nie mają plików Gita, zostało rozpoczęte. diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index f3ed538f3ace..c7cfe8a53a36 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -1732,7 +1732,6 @@ dashboard.task.process=Tarefa: %[1]s dashboard.task.unknown=Tarefa desconhecida: %[1]s dashboard.delete_inactive_accounts=Excluir todas as contas não ativadas dashboard.delete_inactive_accounts.started=A tarefa de apagar todas as contas não ativadas foi iniciada. -dashboard.delete_repo_archives=Excluir todos os arquivos do repositório dashboard.delete_missing_repos=Excluir todos os repositórios que não possuem seus arquivos Git dashboard.delete_generated_repository_avatars=Excluir avatares gerados do repositório dashboard.update_mirrors=Atualizar espelhamentos diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 3ace90e4a0f4..69507fdbfa42 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -1552,7 +1552,6 @@ settings.delete_team_tip=Esta equipa tem acesso a todos os repositórios e não settings.remove_team_success=O acesso da equipa ao repositório foi removido. settings.add_webhook=Adicionar automatismo web settings.add_webhook.invalid_channel_name=O nome de canal do automatismo web não pode estar vazio e não pode conter somente um caractere #. -settings.hooks_desc=Os automatismos web fazem pedidos HTTP POST automaticamente a um servidor quanto certos eventos Gitea são despoletados. Leia mais no guia sobre automatismos web. settings.webhook_deletion=Remover automatismo web settings.webhook_deletion_desc=Remover um automatismo web elimina as configurações e o histórico de entrega desse automatismo. Quer continuar? settings.webhook_deletion_success=O automatismo web foi removido. @@ -2011,7 +2010,6 @@ dashboard.cron.error=Erro no cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s concluído dashboard.delete_inactive_accounts=Eliminar todas as contas que não tenham sido habilitadas dashboard.delete_inactive_accounts.started=Foi iniciada a eliminação de todas as contas que não foram habilitadas. -dashboard.delete_repo_archives=Eliminar todos os arquivos dos repositórios dashboard.delete_repo_archives.started=Foi iniciada a tarefa de eliminação de todos os repositórios arquivados. dashboard.delete_missing_repos=Eliminar todos os repositórios que não tenham os seus ficheiros Git dashboard.delete_missing_repos.started=Foi iniciada a tarefa de eliminação de todos os repositórios que não têm ficheiros git. diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index a14a2fa1a91e..11793b2c1d94 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -1958,7 +1958,6 @@ dashboard.cron.error=Ошибка в задаче Cron: %s: %[3]s dashboard.cron.finished=Крон: %[1]s завершено dashboard.delete_inactive_accounts=Удалить все неактивированные учётные записи dashboard.delete_inactive_accounts.started=Удалить все запущенные задачи неактивированных аккаунтов. -dashboard.delete_repo_archives=Удаление всех архивов репозиториев dashboard.delete_repo_archives.started=Удаление всех архивов репозитория началось. dashboard.delete_missing_repos=Удалить все записи о репозиториях с отсутствующими файлами Git dashboard.delete_missing_repos.started=Задача по удалению всех репозиториев, в которых отсутствуют их git-файлы, начата. diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index 12df6146407a..74e2824b732d 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -1792,7 +1792,6 @@ dashboard.operation_switch=Byt till dashboard.operation_run=Kör dashboard.clean_unbind_oauth=Rena obundna OAuth anslutningar dashboard.clean_unbind_oauth_success=Alla obundna OAuth anslutningar har raderats. -dashboard.delete_repo_archives=Ta bort alla utvecklingskatalogers arkiv dashboard.delete_missing_repos=Ta bort alla utvecklingskataloger som saknar filer specifika för Git dashboard.delete_generated_repository_avatars=Ta bort genererade avatarer för utvecklingskatalogen dashboard.git_gc_repos=Rensa skräpfiler på samtliga utvecklingskataloger diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index 6a1b8fe1bb23..2837013d6f6b 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -205,6 +205,8 @@ default_enable_timetracking=Varsayılan Olarak Zaman Takibini Etkinleştir default_enable_timetracking_popup=Yeni depolar için zaman takibini varsayılan olarak etkinleştir. no_reply_address=Gizlenecek E-Posta Alan Adı no_reply_address_helper=Gizlenmiş e-posta adresine sahip kullanıcılar için alan adı. Örneğin 'ali' kullanıcı adı, gizlenmiş e-postalar için alan adı 'yanityok.ornek.org' olarak ayarlandığında Git günlüğüne 'ali@yanityok.ornek.org' olarak kaydedilecektir. +password_algorithm=Parola Hash Algoritması +password_algorithm_helper=Parola için hash algoritmasını ayarlayın. Algoritmalar değişen gereksinimlere ve güce sahiptirler. `argon2` iyi özelliklere sahip olmasına rağmen fazla miktarda bellek kullanır ve küçük sistemler için uygun olmayabilir. [home] uname_holder=Kullanıcı Adı veya E-Posta Adresi @@ -1160,6 +1162,7 @@ issues.stop_tracking_history=`%s çalışmayı durdurdu` issues.cancel_tracking=Yoksay issues.cancel_tracking_history=` %s zaman takibini iptal etti` issues.add_time=El ile Zaman Ekle +issues.del_time=Bu zaman kaydını sil issues.add_time_short=Zaman Ekle issues.add_time_cancel=İptal issues.add_time_history=`%s harcanan zaman eklendi` @@ -2056,7 +2059,7 @@ dashboard.cron.error=Cron Hatası: %s: %[3]s dashboard.cron.finished=Cron: %[1]s bitti dashboard.delete_inactive_accounts=Etkinleştirilmemiş tüm hesapları sil dashboard.delete_inactive_accounts.started=Etkinleştirilmemiş tüm hesapları silme görevi başladı. -dashboard.delete_repo_archives=Tüm arşiv depoları sil +dashboard.delete_repo_archives=Tüm depoların arşivlerini (ZIP, TAR.GZ, vb.) sil dashboard.delete_repo_archives.started=Tüm depo arşivlerini silme görevi başladı. dashboard.delete_missing_repos=Git dosyaları eksik olan tüm depoları sil dashboard.delete_missing_repos.started=Git dosyaları eksik olan tüm depoları silme görevi başladı. diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 07f6f737e8d1..658fbaef766d 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -1902,7 +1902,6 @@ dashboard.cron.error=Помилка в Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s завершено dashboard.delete_inactive_accounts=Видалити всі неактивовані облікові записи dashboard.delete_inactive_accounts.started=Запущено завдання видалення всі неактивованих облікових записів. -dashboard.delete_repo_archives=Видалити всі архіви репозиторіїв dashboard.delete_repo_archives.started=Запущено завдання видалення всіх архівів репозиторіїв. dashboard.delete_missing_repos=Видалити всі записи про репозиторії з відсутніми файлами Git dashboard.delete_missing_repos.started=Запущено завдання видалення всіх репозиторіїв, в яких відсутні файли Git. diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 7f5457d09cbd..9ca206d9954a 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -15,6 +15,7 @@ page=页面 template=模板 language=语言选项 notifications=通知 +active_stopwatch=活动时间跟踪器 create_new=创建… user_profile_and_more=个人信息和配置 signed_in_as=已登录用户 @@ -75,6 +76,7 @@ pull_requests=合并请求 issues=工单管理 milestones=里程碑 +ok=确定 cancel=取消 save=保存 add=添加 @@ -203,6 +205,8 @@ default_enable_timetracking=默认情况下启用时间跟踪 default_enable_timetracking_popup=默认情况下启用新存储库的时间跟踪。 no_reply_address=隐藏电子邮件 no_reply_address_helper=具有隐藏电子邮件地址的用户的域名。例如, 用户名 "joe" 将以 "joe@noreply.example.org" 的身份登录到 Git 中. 如果隐藏的电子邮件域设置为 "noreply.example.org"。 +password_algorithm=密码哈希算法 +password_algorithm_helper=设置密码哈希算法。 算法具有不同的要求和强度。 具有良好特性的`argon2`却会占用大量内存,可能不适用于小型系统。 [home] uname_holder=登录名或电子邮箱地址 @@ -216,6 +220,7 @@ my_mirrors=我的镜像 view_home=访问 %s search_repos=查找仓库… filter=其他过滤器 +filter_by_team_repositories=按团队仓库筛选 show_archived=已存档 show_both_archived_unarchived=显示已存档和未存档的 @@ -235,6 +240,8 @@ users=用户 organizations=组织 search=搜索 code=代码 +search.fuzzy=模糊 +search.match=匹配 repo_no_results=未找到匹配的仓库。 user_no_results=未找到匹配的用户。 org_no_results=未找到匹配的组织。 @@ -357,6 +364,7 @@ password_not_match=密码不匹配。 lang_select_error=从列表中选出语言 username_been_taken=用户名已被使用。 +username_change_not_local_user=非本地用户不允许更改用户名。 repo_name_been_taken=仓库名称已被使用。 repository_files_already_exist=此仓库已存在文件。请联系系统管理员。 repository_files_already_exist.adopt=此仓库已存在文件,只能被收录。 @@ -446,6 +454,7 @@ update_language_not_found=语言 %s 不可用。 update_profile_success=您的资料信息已经更新 change_username=您的用户名已更改。 change_username_prompt=注意:更改账号名将同时改变账号的URL +change_username_redirect_prompt=在被人使用前,旧用户名将会被重定向。 continue=继续操作 cancel=取消操作 language=界面语言 @@ -516,6 +525,7 @@ ssh_helper=需要帮助? 请查看有关 如何 gpg_helper=需要帮助吗?看一看 GitHub 关于GPG 的指导。 add_new_key=增加 SSH 密钥 add_new_gpg_key=添加的 GPG 密钥 +key_content_ssh_placeholder=以 'ssh-ed25519'、 'ssh-rsa'、 'ecdsa-sha2-nistp256'、'ecdsa-sha2-nistp384'、'ecdsa-sha2-nistp521'、 'sk-ecdsa-sha2-nistp256@openssh.com' 或 'sk-ssh-ed25519@openssh.com' 开头 key_content_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头 add_new_principal=添加规则 ssh_key_been_used=此 SSH 密钥已添加到服务器。 @@ -554,6 +564,7 @@ principal_state_desc=7 天内使用过该规则 show_openid=在个人信息上显示 hide_openid=在个人信息上隐藏 ssh_disabled=SSH 被禁用 +ssh_externally_managed=此 SSH 密钥是由外部管理的 manage_social=管理关联社交帐户 social_desc=这些外部账号已经绑定到你的Gitea账号。请确认这些账号,因为这些账号可以用来登录系统。 unbind=取消链接 @@ -620,6 +631,7 @@ or_enter_secret=或者输入密钥:%s then_enter_passcode=并输入应用程序中显示的密码: passcode_invalid=密码不正确。再试一次。 twofa_enrolled=你的账号已经启用了两步验证。请保存初始令牌(%s)到一个安全的地方,此令牌仅当前显示一次。 +twofa_failed_get_secret=获取 secret 失败。 u2f_desc=安全密钥是包含加密算法的硬件设备。它们可以用于两步验证。安全密钥必须支持 FIDO U2F 标准。 u2f_require_twofa=必须先启用两步验证才能使用安全密钥。 @@ -641,6 +653,7 @@ repos_none=你并不拥有任何仓库 delete_account=删除当前帐户 delete_prompt=此操作将永久删除您的用户帐户。它 不能 被撤消。 +delete_with_all_comments=你的帐户年龄小于 %s。为了避免幽灵评论,所有工单/合并请求的评论都将与它一起被删除。 confirm_delete_account=确认删除帐户 delete_account_title=删除当前帐户 delete_account_desc=确实要永久删除此用户帐户吗? @@ -652,6 +665,7 @@ email_notifications.submit=邮件通知设置 [repo] owner=拥有者 +owner_helper=由于最大存储库限制,一些组织可能不会显示在下拉列表中。 repo_name=仓库名称 repo_name_helper=好的存储库名称使用简短、深刻和独特的关键字。 repo_size=仓库大小 @@ -732,6 +746,8 @@ archive.title=此仓库已存档。您可以查看文件和克隆,但不能推 archive.issue.nocomment=此仓库已存档,您不能在此工单添加评论。 archive.pull.nocomment=此仓库已存档,您不能在此合并请求添加评论。 +form.reach_limit_of_creation_1=你已经达到了 %d 仓库的上限。 +form.reach_limit_of_creation_n=你已经达到了 %d 个仓库的上限。 form.name_reserved=仓库名称 '%s' 是被保留的。 form.name_pattern_not_allowed=仓库名称中不允许使用模式 "%s"。 @@ -766,6 +782,7 @@ migrate.github.description=从 Github.com 或者 Github Enterprise 迁移数据 migrate.git.description=从 Git 迁移数据 migrate.gitlab.description=从 GitLab.com 或者 自部署 GitLab 迁移数据 migrate.gitea.description=从 Gitea.com 或 自托管 Gitea 服务器迁移数据。 +migrate.gogs.description=正从 notabug.org 或其他自托管 Gogs 服务器迁移数据。 mirror_from=镜像自地址 forked_from=派生自 @@ -816,6 +833,8 @@ tag=Git标签 released_this=发布 file_raw=原始文件 file_history=文件历史 +file_view_source=源码模式 +file_view_rendered=渲染模式 file_view_raw=查看原始文件 file_permalink=永久链接 file_too_large=文件过大,无法显示。 @@ -857,6 +876,7 @@ editor.add=添加 '%s' editor.update=更新 '%s' editor.delete=删除 '%s' editor.commit_message_desc=添加一个可选的扩展描述... +editor.signoff_desc=在提交日志消息末尾添加签署人信息。 editor.commit_directly_to_this_branch=直接提交至 %s 分支。 editor.create_new_branch=为此提交创建一个 新的分支 并发起合并请求。 editor.create_new_branch_np=为此提交创建 新分支。 @@ -912,6 +932,9 @@ ext_issues=外部工单 ext_issues.desc=链接到外部工单跟踪系统。 projects=项目 +projects.desc=在项目看板中管理工单和合并请求。 +projects.description=描述(可选) +projects.description_placeholder=描述 projects.create=创建项目 projects.title=标题 projects.new=创建项目 @@ -935,6 +958,8 @@ projects.board.edit_title=新看板名称 projects.board.new_title=新看板名称 projects.board.new_submit=提交 projects.board.new=创建看板 +projects.board.set_default=设为默认 +projects.board.set_default_desc=将此面板设为未分类问题和合并请求的默认值 projects.board.delete=删除看板 projects.board.deletion_desc=删除项目看板会将所有相关问题移至“未分类”。继续吗? projects.open=开启 @@ -1018,6 +1043,7 @@ issues.filter_type.all_issues=所有工单 issues.filter_type.assigned_to_you=指派给您的 issues.filter_type.created_by_you=由您创建的 issues.filter_type.mentioning_you=提及您的 +issues.filter_type.review_requested=已请求评审 issues.filter_sort=排序 issues.filter_sort.latest=最新创建 issues.filter_sort.oldest=最早创建 @@ -1053,6 +1079,7 @@ issues.commented_at=`评论于 %s` issues.delete_comment_confirm=您确定要删除该条评论吗? issues.context.copy_link=复制链接 issues.context.quote_reply=引用回复 +issues.context.reference_issue=在新工单中引用 issues.context.edit=编辑 issues.context.delete=刪除 issues.no_content=这个人很懒,什么都没留下。 @@ -1079,6 +1106,8 @@ issues.re_request_review=再次请求审核 issues.is_stale=此评审之后代码有更新 issues.remove_request_review=移除审核请求 issues.remove_request_review_block=无法移除审核请求 +issues.dismiss_review=取消评审 +issues.dismiss_review_warning=您确定要取消此评审吗? issues.sign_in_require_desc=登录 并参与到对话中。 issues.edit=编辑 issues.cancel=取消 @@ -1123,12 +1152,17 @@ issues.lock.title=锁定有关此问题的对话。 issues.unlock.title=解锁有关此问题的对话。 issues.comment_on_locked=您不能对锁定的问题发表评论。 issues.tracker=时间跟踪 +issues.start_tracking_short=启动计时器 issues.start_tracking=开始时间跟踪 issues.start_tracking_history=`开始工作 %s` issues.tracker_auto_close=当此工单关闭时,自动停止计时器 +issues.tracking_already_started=`你已经开始对 另一个工单 进行时间跟踪!` +issues.stop_tracking=停止计时器 issues.stop_tracking_history=`停止工作 %s` +issues.cancel_tracking=放弃 issues.cancel_tracking_history=`取消时间跟踪 %s` issues.add_time=手动添加时间 +issues.del_time=删除此时间跟踪日志 issues.add_time_short=添加时间 issues.add_time_cancel=取消 issues.add_time_history=`添加耗时 %s` @@ -1187,6 +1221,8 @@ issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 issues.review.approve=已于 %s 批准这些更改 issues.review.comment=评审于 %s +issues.review.dismissed=取消 %s 的审核 %s +issues.review.dismissed_label=已取消 issues.review.left_comment=留下了一条评论 issues.review.content.empty=您需要留下一个注释,表明需要的更改。 issues.review.reject=请求变更 %s @@ -1206,6 +1242,7 @@ issues.review.resolve_conversation=已解决问题 issues.review.un_resolve_conversation=未解决问题 issues.review.resolved_by=标记问题为已解决 issues.assignee.error=因为未知原因,并非所有的指派都成功。 +issues.reference_issue.body=内容 pulls.desc=启用合并请求和代码评审。 pulls.new=创建合并请求 @@ -1436,6 +1473,8 @@ activity.git_stats_deletion_n=删除 %d 行 search=搜索 search.search_repo=搜索仓库... +search.fuzzy=模糊 +search.match=匹配 search.results=在 %s 中搜索 "%s" 的结果 settings=仓库设置 @@ -1516,6 +1555,7 @@ settings.trust_model.collaborator.long=协作者:信任协作者的签名 settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为“可信” - 不管他们是否是提交者。否则,如果签名匹配了提交者,有效的签名将被标记为“不可信”。 settings.trust_model.committer=提交者 settings.trust_model.committer.long=提交者: 信任与提交者匹配的签名 (匹配GitHub 并强制Gitea签名的提交者将Gitea作为提交者) +settings.trust_model.committer.desc=有效的签名只有与提交者匹配时才会被标记为“可信”,否则会被标记为“不匹配”。这会强制Gitea成为已签名提交的提交者,而实际提交者在提交中被标记为Co-authored-by: 和Co-committed-by: trailer。默认的Gitea密钥必须与数据库中的一位用户相匹配。 settings.trust_model.collaboratorcommitter=协作者+提交者 settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名 settings.trust_model.collaboratorcommitter.desc=如果匹配为提交者,此仓库中协作者的有效签名将被标记为“可信”。否则,如果签名匹配了提交者或者未匹配,有效的签名将被标记为“不可信”。这将强制 Gitea 在签名提交上将实际提交者加上 Co-Authored-By: 和 Co-Committed-By: 。默认的Gitea密钥必须匹配Gitea用户。 @@ -1915,6 +1955,7 @@ settings.visibility.private_shortname=私有 settings.update_settings=更新组织设置 settings.update_setting_success=组织设置已更新。 settings.change_orgname_prompt=注意:修改组织名称将会同时修改对应的URL。 +settings.change_orgname_redirect_prompt=在被人使用前,旧用户名将会被重定向。 settings.update_avatar_success=组织头像已经更新。 settings.delete=删除组织 settings.delete_account=删除当前组织 @@ -1986,6 +2027,7 @@ dashboard=管理面板 users=帐户管理 organizations=组织管理 repositories=仓库管理 +hooks=Web 钩子 authentication=认证源 emails=用户邮件 config=应用配置 @@ -2017,7 +2059,7 @@ dashboard.cron.error=任务中的错误: %s: %[3]s dashboard.cron.finished=任务:%[1]s 已经完成 dashboard.delete_inactive_accounts=删除所有未激活的帐户 dashboard.delete_inactive_accounts.started=删除所有未激活的账户任务已启动。 -dashboard.delete_repo_archives=删除所有仓库存档 +dashboard.delete_repo_archives=删除所有代码库的存档 (ZIP、 TAR、GZ, 等...) dashboard.delete_repo_archives.started=删除所有仓库存档任务已启动。 dashboard.delete_missing_repos=删除所有丢失 Git 文件的仓库 dashboard.delete_missing_repos.started=删除所有丢失 Git 文件的仓库任务已启动。 @@ -2036,6 +2078,7 @@ dashboard.resync_all_sshprincipals.desc=(内置的 SSH 服务器不需要。) dashboard.resync_all_hooks=重新同步所有仓库的 pre-receive、update 和 post-receive 钩子 dashboard.reinit_missing_repos=重新初始化所有丢失的 Git 仓库存在的记录 dashboard.sync_external_users=同步外部用户数据 +dashboard.cleanup_hook_task_table=清理 hook_task 表 dashboard.server_uptime=服务运行时间 dashboard.current_goroutine=当前 Goroutines 数量 dashboard.current_memory_usage=当前内存使用量 @@ -2102,6 +2145,7 @@ users.delete_account=删除帐户 users.still_own_repo=此用户仍然拥有一个或多个仓库。必须首先删除或转让这些仓库。 users.still_has_org=此用户是组织的成员。必须先从组织中删除用户。 users.deletion_success=用户帐户已被删除。 +users.reset_2fa=重置两步验证 emails.email_manage_panel=邮件管理 emails.primary=主要的 @@ -2134,8 +2178,13 @@ repos.forks=派生数 repos.issues=工单数 repos.size=大小 +defaulthooks=默认Web钩子 +defaulthooks.desc=当某些 Gitea 事件触发时,Web 钩子自动向服务器发出HTTP POST请求。这里定义的 web 钩子是默认值,将被复制到所有新的存储库中。详情请访问 web 钩子指南。 +defaulthooks.add_webhook=添加默认Web 钩子 +defaulthooks.update_webhook=更新默认 Web 钩子 systemhooks=系统 Web 钩子 +systemhooks.desc=当某些 Gitea 事件触发时,Web 钩子自动向服务器发出HTTP POST请求。这里定义的 web 钩子将作用于系统上的所有存储库,所以请考虑这可能带来的任何性能影响。了解详情请访问 web 钩子指南。 systemhooks.add_webhook=添加系统 Web 钩子 systemhooks.update_webhook=更新系统 Web 钩子 @@ -2186,6 +2235,7 @@ auths.enable_tls=启用 TLS 加密 auths.skip_tls_verify=忽略 TLS 验证 auths.pam_service_name=PAM 服务名称 auths.oauth2_provider=OAuth2 提供程序 +auths.oauth2_icon_url=图标 URL auths.oauth2_clientID=客户端 ID (键) auths.oauth2_clientSecret=客户端密钥 auths.openIdConnectAutoDiscoveryURL=OpenID 连接自动发现 URL @@ -2219,7 +2269,7 @@ auths.tip.google_plus=从谷歌 API 控制台 (https://console.developers.google auths.tip.openid_connect=使用 OpenID 连接发现 URL (/.well-known/openid-configuration) 来指定终点 auths.tip.twitter=访问 https://dev.twitter.com/apps,创建应用并确保启用了"允许此应用程序用于登录 Twitter"的选项。 auths.tip.discord=在 https://discordapp.com/developers/applications/me 上注册新应用程序 -auths.tip.gitea=注册一个新的 OAuth2 应用程序。可以访问 https://docs.gitea.io/en-us/oauth 2-product/ 查看帮助 。 +auths.tip.gitea=注册一个新的 OAuth2 应用程序,可以访问 https://docs.gitea.io/en-us/oauth2-provider/ 查看帮助 。 auths.tip.yandex=在 https://oauth.yandex.com/client/new 上创建一个新的应用程序。在“ Yandex.Passport API”这部分中选择以下权限:“访问电子邮件地址(Access to email address)”,“访问用户头像(Access to user avatar)”和“访问用户名,名字和姓氏,性别(Access to username, first name and surname, genderAccess to username, first name and surname, gender)” auths.tip.mastodon=输入您想要认证的 mastodon 实例的自定义 URL (或使用默认值) auths.edit=修改认证源 @@ -2476,6 +2526,9 @@ mirror_sync_delete=从镜像同步并从 %[3]s 删除了引 approve_pull_request=`同意了 %s#%[2]s` reject_pull_request=`建议变更 %s#%[2]s` publish_release=`发布了 "%[4]s" %[3]s` +review_dismissed=`取消了 %[4]s%[3]s#%[2]s 的评审` +review_dismissed_reason=原因: +create_branch=创建分支 %[3]s%[4]s [tool] ago=%s前 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index a0b298a2756f..c2878c3b5307 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -204,6 +204,8 @@ default_enable_timetracking=預設啟用時間追蹤 default_enable_timetracking_popup=預設情況下啟用新存儲庫的時間跟蹤。 no_reply_address=隱藏電子信箱域名 no_reply_address_helper=作為隱藏電子信箱使用者的域名。例如,如果隱藏的電子信箱域名設定為「noreply.example.org」,帳號「joe」將以「joe@noreply.example.org」的身份登錄到 Git 中。 +password_algorithm=密碼雜湊演算法 +password_algorithm_helper=設定密碼雜湊演算法。演算法有不同的需求和強度。「argon2」雖然有優秀的特性但會占用大量記憶體,所以可能不適用於小型系統。 [home] uname_holder=帳號或電子信箱 @@ -2055,7 +2057,6 @@ dashboard.cron.error=Cron 中的錯誤: %s: %[3]s dashboard.cron.finished=Cron: %[1]s 已完成 dashboard.delete_inactive_accounts=刪除所有未啟用帳戶 dashboard.delete_inactive_accounts.started=刪除所有未啟用帳戶的任務已啟動。 -dashboard.delete_repo_archives=刪除所有儲存庫存檔 dashboard.delete_repo_archives.started=刪除所有儲存庫存檔的任務已啟動。 dashboard.delete_missing_repos=刪除所有遺失 Git 檔案的儲存庫 dashboard.delete_missing_repos.started=刪除所有遺失 Git 檔案的儲存庫的任務已啟動。 diff --git a/routers/admin/admin.go b/routers/admin/admin.go index c8f9d8b35ba1..2b2328a93aee 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -364,7 +364,7 @@ func WorkerCancel(ctx *context.Context) { mq.CancelWorkers(pid) ctx.Flash.Info(ctx.Tr("admin.monitor.queue.pool.cancelling")) ctx.JSON(200, map[string]interface{}{ - "redirect": setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid), + "redirect": setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10), }) } @@ -387,7 +387,7 @@ func Flush(ctx *context.Context) { log.Error("Flushing failure for %s: Error %v", mq.Name, err) } }() - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) } // AddWorkers adds workers to a worker group @@ -401,23 +401,23 @@ func AddWorkers(ctx *context.Context) { number := ctx.QueryInt("number") if number < 1 { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.pool.addworkers.mustnumbergreaterzero")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } timeout, err := time.ParseDuration(ctx.Query("timeout")) if err != nil { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.pool.addworkers.musttimeoutduration")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } if _, ok := mq.Managed.(queue.ManagedPool); !ok { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.pool.none")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } mq.AddWorkers(number, timeout) ctx.Flash.Success(ctx.Tr("admin.monitor.queue.pool.added")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) } // SetQueueSettings sets the maximum number of workers and other settings for this queue @@ -430,7 +430,7 @@ func SetQueueSettings(ctx *context.Context) { } if _, ok := mq.Managed.(queue.ManagedPool); !ok { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.pool.none")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } @@ -445,7 +445,7 @@ func SetQueueSettings(ctx *context.Context) { maxNumber, err = strconv.Atoi(maxNumberStr) if err != nil { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.settings.maxnumberworkers.error")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } if maxNumber < -1 { @@ -459,7 +459,7 @@ func SetQueueSettings(ctx *context.Context) { number, err = strconv.Atoi(numberStr) if err != nil || number < 0 { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.settings.numberworkers.error")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } } else { @@ -470,7 +470,7 @@ func SetQueueSettings(ctx *context.Context) { timeout, err = time.ParseDuration(timeoutStr) if err != nil { ctx.Flash.Error(ctx.Tr("admin.monitor.queue.settings.timeout.error")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) return } } else { @@ -479,5 +479,5 @@ func SetQueueSettings(ctx *context.Context) { mq.SetPoolSettings(maxNumber, number, timeout) ctx.Flash.Success(ctx.Tr("admin.monitor.queue.settings.changed")) - ctx.Redirect(setting.AppSubURL + fmt.Sprintf("/admin/monitor/queue/%d", qid)) + ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10)) } diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index f148710c7971..116c622048d6 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -224,6 +224,9 @@ func EditUser(ctx *context.APIContext) { if form.ProhibitLogin != nil { u.ProhibitLogin = *form.ProhibitLogin } + if form.Restricted != nil { + u.IsRestricted = *form.Restricted + } if err := models.UpdateUser(u); err != nil { if models.IsErrEmailAlreadyUsed(err) || models.IsErrEmailInvalid(err) { diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go index 75ae1191a521..5f0e36386ef3 100644 --- a/routers/api/v1/org/member.go +++ b/routers/api/v1/org/member.go @@ -5,7 +5,6 @@ package org import ( - "fmt" "net/http" "code.gitea.io/gitea/models" @@ -153,8 +152,7 @@ func IsMember(ctx *context.APIContext) { } } - redirectURL := fmt.Sprintf("%sapi/v1/orgs/%s/public_members/%s", - setting.AppURL, ctx.Org.Organization.Name, userToCheck.Name) + redirectURL := setting.AppURL + "api/v1/orgs/" + ctx.Org.Organization.Name + "/public_members/" + userToCheck.Name ctx.Redirect(redirectURL, 302) } diff --git a/routers/api/v1/settings/settings.go b/routers/api/v1/settings/settings.go index 6095988404b0..cfb059a3acce 100644 --- a/routers/api/v1/settings/settings.go +++ b/routers/api/v1/settings/settings.go @@ -57,9 +57,11 @@ func GetGeneralRepoSettings(ctx *context.APIContext) { // "200": // "$ref": "#/responses/GeneralRepoSettings" ctx.JSON(http.StatusOK, api.GeneralRepoSettings{ - MirrorsDisabled: setting.Repository.DisableMirrors, - HTTPGitDisabled: setting.Repository.DisableHTTPGit, - MigrationsDisabled: setting.Repository.DisableMigrations, + MirrorsDisabled: setting.Repository.DisableMirrors, + HTTPGitDisabled: setting.Repository.DisableHTTPGit, + MigrationsDisabled: setting.Repository.DisableMigrations, + TimeTrackingDisabled: !setting.Service.EnableTimetracking, + LFSDisabled: !setting.LFS.StartServer, }) } diff --git a/routers/events/events.go b/routers/events/events.go index a1131f29e3e1..2b78d8603bae 100644 --- a/routers/events/events.go +++ b/routers/events/events.go @@ -5,13 +5,17 @@ package events import ( + "encoding/json" "net/http" "time" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/eventsource" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/routers/user" ) @@ -55,6 +59,8 @@ func Events(ctx *context.Context) { timer := time.NewTicker(30 * time.Second) + stopwatchTimer := time.NewTicker(setting.UI.Notification.MinTimeout) + loop: for { select { @@ -75,6 +81,32 @@ loop: case <-shutdownCtx.Done(): go unregister() break loop + case <-stopwatchTimer.C: + sws, err := models.GetUserStopwatches(ctx.User.ID, models.ListOptions{}) + if err != nil { + log.Error("Unable to GetUserStopwatches: %v", err) + continue + } + apiSWs, err := convert.ToStopWatches(sws) + if err != nil { + log.Error("Unable to APIFormat stopwatches: %v", err) + continue + } + dataBs, err := json.Marshal(apiSWs) + if err != nil { + log.Error("Unable to marshal stopwatches: %v", err) + continue + } + _, err = (&eventsource.Event{ + Name: "stopwatches", + Data: string(dataBs), + }).WriteTo(ctx.Resp) + if err != nil { + log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err) + go unregister() + break loop + } + ctx.Resp.Flush() case event, ok := <-messageChan: if !ok { break loop diff --git a/routers/repo/issue.go b/routers/repo/issue.go index fa1ee9977165..a9459a10ed93 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -1416,6 +1416,10 @@ func ViewIssue(ctx *context.Context) { ctx.ServerError("LoadPushCommits", err) return } + } else if comment.Type == models.CommentTypeAddTimeManual || + comment.Type == models.CommentTypeStopTracking { + // drop error since times could be pruned from DB.. + _ = comment.LoadTime() } } diff --git a/routers/repo/issue_timetrack.go b/routers/repo/issue_timetrack.go index 425f21511052..3b13770d61dc 100644 --- a/routers/repo/issue_timetrack.go +++ b/routers/repo/issue_timetrack.go @@ -10,13 +10,13 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" - auth "code.gitea.io/gitea/modules/forms" + "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/web" ) // AddTimeManually tracks time manually func AddTimeManually(c *context.Context) { - form := web.GetForm(c).(*auth.AddTimeManuallyForm) + form := web.GetForm(c).(*forms.AddTimeManuallyForm) issue := GetActionIssue(c) if c.Written() { return @@ -48,3 +48,39 @@ func AddTimeManually(c *context.Context) { c.Redirect(url, http.StatusSeeOther) } + +// DeleteTime deletes tracked time +func DeleteTime(c *context.Context) { + issue := GetActionIssue(c) + if c.Written() { + return + } + if !c.Repo.CanUseTimetracker(issue, c.User) { + c.NotFound("CanUseTimetracker", nil) + return + } + + t, err := models.GetTrackedTimeByID(c.ParamsInt64(":timeid")) + if err != nil { + if models.IsErrNotExist(err) { + c.NotFound("time not found", err) + return + } + c.Error(http.StatusInternalServerError, "GetTrackedTimeByID", err.Error()) + return + } + + // only OP or admin may delete + if !c.IsSigned || (!c.IsUserSiteAdmin() && c.User.ID != t.UserID) { + c.Error(http.StatusForbidden, "not allowed") + return + } + + if err = models.DeleteTime(t); err != nil { + c.ServerError("DeleteTime", err) + return + } + + c.Flash.Success(c.Tr("repo.issues.del_time_history", models.SecToTime(t.Time))) + c.Redirect(issue.HTMLURL()) +} diff --git a/routers/repo/pull.go b/routers/repo/pull.go index d3dd9e4fb544..15af2a2a3f33 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -301,6 +301,8 @@ func setMergeTarget(ctx *context.Context, pull *models.PullRequest) { ctx.Data["HeadTarget"] = pull.MustHeadUserName() + "/" + pull.HeadRepo.Name + ":" + pull.HeadBranch } ctx.Data["BaseTarget"] = pull.BaseBranch + ctx.Data["HeadBranchHTMLURL"] = pull.GetHeadBranchHTMLURL() + ctx.Data["BaseBranchHTMLURL"] = pull.GetBaseBranchHTMLURL() } // PrepareMergedViewPullInfo show meta information for a merged pull request view page diff --git a/routers/repo/search.go b/routers/repo/search.go index 42fe3d758478..481b64d184a8 100644 --- a/routers/repo/search.go +++ b/routers/repo/search.go @@ -40,8 +40,7 @@ func Search(ctx *context.Context) { ctx.Data["Keyword"] = keyword ctx.Data["Language"] = language ctx.Data["queryType"] = queryType - ctx.Data["SourcePath"] = setting.AppSubURL + "/" + - path.Join(ctx.Repo.Repository.Owner.Name, ctx.Repo.Repository.Name) + ctx.Data["SourcePath"] = path.Join(setting.AppSubURL, ctx.Repo.Repository.Owner.Name, ctx.Repo.Repository.Name) ctx.Data["SearchResults"] = searchResults ctx.Data["SearchResultLanguages"] = searchResultLanguages ctx.Data["RequireHighlightJS"] = true diff --git a/routers/routes/web.go b/routers/routes/web.go index a6af64f8748e..dd43663e3505 100644 --- a/routers/routes/web.go +++ b/routers/routes/web.go @@ -708,7 +708,7 @@ func RegisterRoutes(m *web.Route) { m.Get("/choose", context.RepoRef(), repo.NewIssueChooseTemplate) }) }, context.RepoMustNotBeArchived(), reqRepoIssueReader) - // FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest. + // FIXME: should use different URLs but mostly same logic for comments of issue and pull request. // So they can apply their own enable/disable logic on routers. m.Group("/issues", func() { m.Group("/{index}", func() { @@ -723,6 +723,7 @@ func RegisterRoutes(m *web.Route) { m.Combo("/comments").Post(repo.MustAllowUserComment, bindIgnErr(auth.CreateCommentForm{}), repo.NewComment) m.Group("/times", func() { m.Post("/add", bindIgnErr(auth.AddTimeManuallyForm{}), repo.AddTimeManually) + m.Post("/{timeid}/delete", repo.DeleteTime) m.Group("/stopwatch", func() { m.Post("/toggle", repo.IssueStopwatch) m.Post("/cancel", repo.CancelStopwatch) diff --git a/routers/user/home.go b/routers/user/home.go index a8a8a5f3d750..a8020b64e048 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -156,6 +156,7 @@ func Dashboard(ctx *context.Context) { IncludePrivate: true, OnlyPerformedBy: false, IncludeDeleted: false, + Date: ctx.Query("date"), }) if ctx.Written() { diff --git a/routers/user/notification.go b/routers/user/notification.go index 34939d14554f..523e945db9bb 100644 --- a/routers/user/notification.go +++ b/routers/user/notification.go @@ -174,7 +174,7 @@ func NotificationStatusPost(c *context.Context) { if c.Written() { return } - c.Data["Link"] = fmt.Sprintf("%snotifications", setting.AppURL) + c.Data["Link"] = setting.AppURL + "notifications" c.HTML(http.StatusOK, tplNotificationDiv) } diff --git a/routers/user/profile.go b/routers/user/profile.go index e19407baa78c..5dfee07d7622 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -202,6 +202,7 @@ func Profile(ctx *context.Context) { IncludePrivate: showPrivate, OnlyPerformedBy: true, IncludeDeleted: false, + Date: ctx.Query("date"), }) if ctx.Written() { return diff --git a/routers/utils/utils_test.go b/routers/utils/utils_test.go index ec5e69862aa3..78ab3d20ee4f 100644 --- a/routers/utils/utils_test.go +++ b/routers/utils/utils_test.go @@ -35,7 +35,7 @@ func TestIsValidSlackChannel(t *testing.T) { } func TestIsExternalURL(t *testing.T) { - setting.AppURL = "https://try.gitea.io" + setting.AppURL = "https://try.gitea.io/" type test struct { Expected bool RawURL string diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 1dcaea8560a0..2feaf1dda4d1 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -42,6 +42,7 @@ MaxTimeout: {{NotificationSettings.MaxTimeout}}, EventSourceUpdateTime: {{NotificationSettings.EventSourceUpdateTime}}, }, + EnableTimetracking: {{if EnableTimetracking}}true{{else}}false{{end}}, PageIsProjects: {{if .PageIsProjects }}true{{else}}false{{end}}, {{if .RequireTribute}} tributeValues: Array.from(new Map([ diff --git a/templates/repo/create.tmpl b/templates/repo/create.tmpl index 8bb3584ec650..4aabcb6bb377 100644 --- a/templates/repo/create.tmpl +++ b/templates/repo/create.tmpl @@ -9,6 +9,9 @@
{{template "base/alert" .}} + +

{{.i18n.Tr "repo.new_repo_helper" "/repo/migrate" | Safe}}

+ {{if not .CanCreateRepo}}

{{.i18n.Tr (TrN .i18n.Lang .MaxCreationLimit "repo.form.reach_limit_of_creation_1" "repo.form.reach_limit_of_creation_n") .MaxCreationLimit}}

@@ -59,7 +62,7 @@
- +
@@ -135,6 +138,7 @@ {{end}}
+ {{.i18n.Tr "repo.repo_gitignore_helper_desc"}}
@@ -148,6 +152,7 @@ {{end}}
+ {{.i18n.Tr "repo.license_helper_desc" "https://choosealicense.com/" | Str2html}}
@@ -161,6 +166,7 @@ {{end}}
+ {{.i18n.Tr "repo.readme_helper_desc"}}
@@ -171,6 +177,7 @@
+ {{.i18n.Tr "repo.default_branch_helper"}}
@@ -185,6 +192,15 @@
{{.i18n.Tr "repo.settings.trust_model.collaboratorcommitter"}}
+
+ {{.i18n.Tr "repo.trust_model_helper"}} +
    +
  • {{.i18n.Tr "repo.trust_model_helper_collaborator"}}
  • +
  • {{.i18n.Tr "repo.trust_model_helper_committer"}}
  • +
  • {{.i18n.Tr "repo.trust_model_helper_collaborator_committer"}}
  • +
  • {{.i18n.Tr "repo.trust_model_helper_default"}}
  • +
+
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index b971c6b1ae69..cfacde96486f 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -276,6 +276,7 @@ {{.Poster.GetDisplayName}} {{$.i18n.Tr "repo.issues.stop_tracking_history" $createdStr | Safe}} + {{ template "repo/issue/view_content/comments_delete_time" Dict "ctx" $ "comment" . }}
{{svg "octicon-clock"}} {{.Content}} @@ -291,6 +292,7 @@ {{.Poster.GetDisplayName}} {{$.i18n.Tr "repo.issues.add_time_history" $createdStr | Safe}} + {{ template "repo/issue/view_content/comments_delete_time" Dict "ctx" $ "comment" . }}
{{svg "octicon-clock"}} {{.Content}} diff --git a/templates/repo/issue/view_content/comments_delete_time.tmpl b/templates/repo/issue/view_content/comments_delete_time.tmpl new file mode 100644 index 000000000000..a28d222f860a --- /dev/null +++ b/templates/repo/issue/view_content/comments_delete_time.tmpl @@ -0,0 +1,21 @@ +{{ if .comment.Time }} {{/* compatibility with time comments made before v1.14 */}} + {{ if (not .comment.Time.Deleted) }} + {{ if (or .ctx.IsAdmin (and .ctx.IsSigned (eq .ctx.SignedUserID .comment.PosterID))) }} + + + + + {{end}} + {{end}} +{{end}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 3a21a9271b2a..9df7d7ed44e2 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -348,7 +348,7 @@ {{end}}
-