mirror of
https://github.com/go-gitea/gitea.git
synced 2025-08-15 23:10:33 +02:00
Compare commits
30 Commits
v1.6.0-rc2
...
v1.6.2
Author | SHA1 | Date | |
---|---|---|---|
|
2631f7f64d | ||
|
af4626a270 | ||
|
21c70e1ed2 | ||
|
b45d58805a | ||
|
200b974e19 | ||
|
800271ee1f | ||
|
e6362f3d23 | ||
|
716c2918be | ||
|
60d7b614fe | ||
|
9cf9a54dca | ||
|
2b4f87da46 | ||
|
ad9f9cdc30 | ||
|
8237fd4a2d | ||
|
8e4a0a978a | ||
|
c1275e2ba6 | ||
|
7bc1faabdb | ||
|
e406dc058d | ||
|
328e38ebc7 | ||
|
773addf727 | ||
|
0da8bc9ec0 | ||
|
5d69703d3c | ||
|
ffc0c7f611 | ||
|
8670decafb | ||
|
297e619074 | ||
|
e9b984e162 | ||
|
5995b65175 | ||
|
996ce8cc03 | ||
|
fe7cef0e1f | ||
|
464dcd1b66 | ||
|
68938d5dc4 |
183
CHANGELOG.md
183
CHANGELOG.md
@@ -4,29 +4,43 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.6.0-rc2](https://github.com/go-gitea/gitea/releases/tag/v1.6.0-rc2) - 2018-11-04
|
||||
## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
|
||||
* SECURITY
|
||||
* Add CSRF checking to reqToken and add reqToken to admin API routes (#5272) (#5250)
|
||||
* FEATURE
|
||||
* Add comment replies (#5147) (#5104)
|
||||
* Sanitize uploaded file names (#5571) (#5573)
|
||||
* HTMLEncode user added text (#5570) (#5575)
|
||||
* BUGFIXES
|
||||
* Fix wrong api request url for instances running in subfolders (#5261) (#5247)
|
||||
* Accept web-command cli flags if web-command is commited (#5245) (#5200)
|
||||
* Reduce join star, repo_topic, topic tables on repo search, to resolve extra columns problem on MSSQL (#5136) (#5229)
|
||||
* Fix data race on migrate repository (#5224) (#5230)
|
||||
* Add secret to all webhook's payload where it has been missing (#5208) (#5199)
|
||||
* Fix sqlite and MSSQL lock (#5210) (#5223) (#5214) (#5218) (#5176) (#5179)
|
||||
* Fix race on updatesize (#5190) (#5215)
|
||||
* Fix filtering issues by tags on main screen issues (#5219) (#3824)
|
||||
* Fix SQL quoting (#5137) (#5117)
|
||||
* Fix regex to support optional end line of old section in diff hunk (#5097) (#5096)
|
||||
* Fix indexer reindex bug when gitea restart (#5563) (#5564)
|
||||
* Remove a double slash in the HTTPS redirect with Let's Encrypt (#5537) (#5539)
|
||||
* Fix bug when a read perm user to edit his issue (#5516) (#5534)
|
||||
* Detect force push failure on deletion of protected branches (#5522) (#5531)
|
||||
* Let's Encrypt handler listens on correct port for certificate validation (#5525) (#5527)
|
||||
* Fix forgot deletion of notification when delete repository (#5506) (#5514)
|
||||
* Fix undeleted content when deleting user (#5429) (#5509)
|
||||
* Fix empty wiki (#5504) (#5508)
|
||||
|
||||
## [1.6.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.6.0-rc1) - 2018-10-17
|
||||
## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
|
||||
* BUGFIXES
|
||||
* Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
|
||||
* API: '/orgs/:org/repos': return private repos with read access (#5393)
|
||||
* Fix repository deletion when there is large number of issues in it (#5426) (#5434)
|
||||
* Word-break the WebHook url to prevent a ui-break (#5445)
|
||||
* Admin should be able to delete repos via the API even if they are not a member of the organization (#5443) (#5447)
|
||||
* Ensure that the `closed_at` is set for closed (#5450)
|
||||
* Fix topic name length on database (#5493) (#5495)
|
||||
|
||||
## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
|
||||
* BREAKING
|
||||
* Respect email privacy option in user search via API (#4512)
|
||||
* Simply remove tidb and deps (#3993)
|
||||
* Swagger.v1.json template (#3572)
|
||||
* SECURITY
|
||||
* Add CSRF checking to reqToken and add reqToken to admin API routes (#5272) (#5250)
|
||||
* Improve URL validation for external wiki and external issues (#4710)
|
||||
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
|
||||
* Don't disclose emails of all users when sending out emails (#4664)
|
||||
* Check that repositories can only be migrated to own user or organizations (#4366)
|
||||
* FEATURE
|
||||
* Add comment replies (#5147) (#5104)
|
||||
* Pull request review/approval and comment on code (#3748)
|
||||
* Added dependencies for issues (#2196) (#2531)
|
||||
* Add the ability to have built in themes in Gitea and provide dark theme arc-green (#4198)
|
||||
@@ -38,63 +52,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Add push webhook support for mirrored repositories (#4127)
|
||||
* Add csv file render support defaultly (#4105)
|
||||
* Add Recaptcha functionality to Gitea (#4044)
|
||||
* BUGFIXES
|
||||
* Fix release creation via API (#5076)
|
||||
* Remove links from topics in edit mode (#5026)
|
||||
* Fix missing AppSubUrl in few more templates (fixup) (#5021)
|
||||
* Fix missing AppSubUrl in some templates (#5020)
|
||||
* Hide outdated comments in file view (#5017)
|
||||
* Upgrade gopkg.in/testfixtures.v2 (#4999)
|
||||
* Disable debug routes unless PPROF is enabled in configuration (#4995)
|
||||
* Fix user menu item styling (#4985)
|
||||
* Fix layout of the topics editing form (#4971)
|
||||
* Fix null pointer dereference in ParseCommitWithSignature (#4962)
|
||||
* Fix url in discord webhook (#4953)
|
||||
* Detect charset and convert non UTF-8 files for display (#4950)
|
||||
* Make sure to catch the right error so it is displayed on the UI (#4945)
|
||||
* Fix(topics): don't redirect to explore page. (#4938)
|
||||
* Fix bug forget to remove Stopwatch when remove repository (#4928)
|
||||
* Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
|
||||
* Fix: Let's Encrypt configuration settings (#4911)
|
||||
* Fix: Crippled diff (#4726) (#4900)
|
||||
* Fix trimming of markup section names (#4863)
|
||||
* Issues api allow pulls and fix #4832 (#4852)
|
||||
* Do not autocreate directory for new users/orgs (#4828) (#4849)
|
||||
* Fix redirect with non-ascii branch names (#4764) (#4810)
|
||||
* Fix missing release title in webhook (#4783) (#4796)
|
||||
* User shouldn't be able to approve or reject his/her own PR (#4729)
|
||||
* Make sure to reset commit count in the cache on mirror syncing (#4720)
|
||||
* Fixed bug where team with admin privelege type doesn't get any unit (#4719)
|
||||
* Fix incorrect caption of webhook setting (#4701) (#4717)
|
||||
* Allow WIP marker to contains < or > (#4709)
|
||||
* Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
|
||||
* Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
|
||||
* Fix custom templates being ignored (#4638)
|
||||
* Fix starring icon after semantic ui update (#4628)
|
||||
* Fix Split-View line adjustment (#4622)
|
||||
* Fix integer constant overflows in tests (#4616)
|
||||
* Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
|
||||
* Fix bugs when too many IN variables (#4594)
|
||||
* Fix failure on creating pull request with assignees (#4419) (#4583)
|
||||
* Fix panic issue on update avatar email (#4580) (#4581)
|
||||
* Fix status code label for a successful webhook (#4540)
|
||||
* An inactive user shouldn't be able to be added as a collaborator (#4535)
|
||||
* Don't fail silently if trying to add a collaborator twice (#4533)
|
||||
* Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
|
||||
* Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
|
||||
* Fix migration from older releases (#4495)
|
||||
* Accept 'Data:' in commit graph (#4487)
|
||||
* Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
|
||||
* Relative URLs for LibreJS page (#4460)
|
||||
* Redirect to correct page after using scratch token (#4458)
|
||||
* Fix column droping for MSSQL that need new transaction for that (#4440)
|
||||
* Replace src with raw to fix image paths (#4377)
|
||||
* Add default merge options when creating new repository (#4369)
|
||||
* Fix docker build (#4358)
|
||||
* Fixes repo membership check in API (#4341)
|
||||
* Dep upgrade mysql lib (#4161)
|
||||
* Fix some issues with special chars in branch names (#3767)
|
||||
* Responsive design fixes (#4508)
|
||||
* ENHANCEMENT
|
||||
* Fix milestones sorted wrongly (#4987)
|
||||
* Allow api to create tags for releases if they don't exist (#4890)
|
||||
@@ -147,15 +104,87 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Added front-end topics validation (#4316)
|
||||
* Don't display buttons if there are no system notifications (#4280)
|
||||
* Issue due date api (#3890)
|
||||
* SECURITY
|
||||
* Improve URL validation for external wiki and external issues (#4710)
|
||||
* Make cookies HttpOnly and obey COOKIE_SECURE flag (#4706)
|
||||
* Don't disclose emails of all users when sending out emails (#4664)
|
||||
* Check that repositories can only be migrated to own user or organizations (#4366)
|
||||
* BUGFIXES
|
||||
* dont' send assign webhooks when creating issue (#5365)
|
||||
* Fix create team, update team missing units (#5188)
|
||||
* Fix file edit change preview functionality (#5300)
|
||||
* *ix bug when users have serval teams with different units on different repositories (#5307)
|
||||
* Fix U2F if gitea is configured in subpath (#5302)
|
||||
* Fix markdown image with link (#4675)
|
||||
* Remove maxlines option for file logger (#5282)
|
||||
* Fix wrong api request url for instances running in subfolders (#5261) (#5247)
|
||||
* Accept web-command cli flags if web-command is commited (#5245) (#5200)
|
||||
* Reduce join star, repo_topic, topic tables on repo search, to resolve extra columns problem on MSSQL (#5136) (#5229)
|
||||
* Fix data race on migrate repository (#5224) (#5230)
|
||||
* Add secret to all webhook's payload where it has been missing (#5208) (#5199)
|
||||
* Fix sqlite and MSSQL lock (#5210) (#5223) (#5214) (#5218) (#5176) (#5179)
|
||||
* Fix race on updatesize (#5190) (#5215)
|
||||
* Fix filtering issues by tags on main screen issues (#5219) (#3824)
|
||||
* Fix SQL quoting (#5137) (#5117)
|
||||
* Fix regex to support optional end line of old section in diff hunk (#5097) (#5096)
|
||||
* Fix release creation via API (#5076)
|
||||
* Remove links from topics in edit mode (#5026)
|
||||
* Fix missing AppSubUrl in few more templates (fixup) (#5021)
|
||||
* Fix missing AppSubUrl in some templates (#5020)
|
||||
* Hide outdated comments in file view (#5017)
|
||||
* Upgrade gopkg.in/testfixtures.v2 (#4999)
|
||||
* Disable debug routes unless PPROF is enabled in configuration (#4995)
|
||||
* Fix user menu item styling (#4985)
|
||||
* Fix layout of the topics editing form (#4971)
|
||||
* Fix null pointer dereference in ParseCommitWithSignature (#4962)
|
||||
* Fix url in discord webhook (#4953)
|
||||
* Detect charset and convert non UTF-8 files for display (#4950)
|
||||
* Make sure to catch the right error so it is displayed on the UI (#4945)
|
||||
* Fix(topics): don't redirect to explore page. (#4938)
|
||||
* Fix bug forget to remove Stopwatch when remove repository (#4928)
|
||||
* Fix bug when repo remained bare if multiple branches pushed in single push (#4923)
|
||||
* Fix: Crippled diff (#4726) (#4900)
|
||||
* Fix trimming of markup section names (#4863)
|
||||
* Issues api allow pulls and fix #4832 (#4852)
|
||||
* Do not autocreate directory for new users/orgs (#4828) (#4849)
|
||||
* Fix redirect with non-ascii branch names (#4764) (#4810)
|
||||
* Fix missing release title in webhook (#4783) (#4796)
|
||||
* User shouldn't be able to approve or reject his/her own PR (#4729)
|
||||
* Make sure to reset commit count in the cache on mirror syncing (#4720)
|
||||
* Fixed bug where team with admin privelege type doesn't get any unit (#4719)
|
||||
* Fix incorrect caption of webhook setting (#4701) (#4717)
|
||||
* Allow WIP marker to contains < or > (#4709)
|
||||
* Hide org/create menu item in Dashboard if user has no rights (#4678) (#4680)
|
||||
* Site admin could create repos even MAX_CREATION_LIMIT=0 (#4645)
|
||||
* Fix custom templates being ignored (#4638)
|
||||
* Fix starring icon after semantic ui update (#4628)
|
||||
* Fix Split-View line adjustment (#4622)
|
||||
* Fix integer constant overflows in tests (#4616)
|
||||
* Push whitelist now doesn't apply to branch deletion (#4601) (#4607)
|
||||
* Fix bugs when too many IN variables (#4594)
|
||||
* Fix failure on creating pull request with assignees (#4419) (#4583)
|
||||
* Fix panic issue on update avatar email (#4580) (#4581)
|
||||
* Fix status code label for a successful webhook (#4540)
|
||||
* An inactive user shouldn't be able to be added as a collaborator (#4535)
|
||||
* Don't fail silently if trying to add a collaborator twice (#4533)
|
||||
* Fix incorrect MergeWhitelistTeamIDs check in CanUserMerge function (#4519) (#4525)
|
||||
* Fix out-of-transaction query in removeOrgUser (#4521) (#4522)
|
||||
* Fix migration from older releases (#4495)
|
||||
* Accept 'Data:' in commit graph (#4487)
|
||||
* Update xorm to latest version and fix correct `user` table referencing in sql (#4473)
|
||||
* Relative URLs for LibreJS page (#4460)
|
||||
* Redirect to correct page after using scratch token (#4458)
|
||||
* Fix column droping for MSSQL that need new transaction for that (#4440)
|
||||
* Replace src with raw to fix image paths (#4377)
|
||||
* Add default merge options when creating new repository (#4369)
|
||||
* Fix docker build (#4358)
|
||||
* Fixes repo membership check in API (#4341)
|
||||
* Dep upgrade mysql lib (#4161)
|
||||
* Fix some issues with special chars in branch names (#3767)
|
||||
* Responsive design fixes (#4508)
|
||||
* TRANSLATION
|
||||
* Fix punctuation in English translation (#4958)
|
||||
* Fix translation (#4355)
|
||||
|
||||
## [1.5.3](https://github.com/go-gitea/gitea/releases/tag/v1.5.3) - 2018-10-31
|
||||
* SECURITY
|
||||
* Fix remote command execution vulnerability in upstream library (#5177) (#5196)
|
||||
|
||||
## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
|
||||
* SECURITY
|
||||
* Enforce token on api routes (#4840) (#4905)
|
||||
|
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@@ -11,11 +11,11 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:bf4f822f636b99ac7d4f8fa5210a7439bacaf8d1f15d5783956bdd5dd2069bdc"
|
||||
digest = "1:b194da40b41ae99546dfeec5a85f1fec2a6c51350d438e511ef90f4293c6dcd7"
|
||||
name = "code.gitea.io/sdk"
|
||||
packages = ["gitea"]
|
||||
pruneopts = "NUT"
|
||||
revision = "11c860c8e49a23be26e6d6c6a039a46ad2ae1d27"
|
||||
revision = "4f96d9ac89886e78c50de8c835ebe87461578a5e"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:3fcef06a1a6561955c94af6c7757a6fa37605eb653f0d06ab960e5bb80092195"
|
||||
|
24
cmd/hook.go
24
cmd/hook.go
@@ -112,10 +112,15 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
|
||||
if err != nil {
|
||||
log.GitLogger.Fatal(2, "retrieve protected branches information failed")
|
||||
fail("Internal error", fmt.Sprintf("retrieve protected branches information failed: %v", err))
|
||||
}
|
||||
|
||||
if protectBranch != nil && protectBranch.IsProtected() {
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
}
|
||||
|
||||
// detect force push
|
||||
if git.EmptySHA != oldCommitID {
|
||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
|
||||
@@ -126,17 +131,12 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// check and deletion
|
||||
if newCommitID == git.EmptySHA {
|
||||
fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
|
||||
} else {
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
userID, _ := strconv.ParseInt(userIDStr, 10, 64)
|
||||
canPush, err := private.CanUserPush(protectBranch.ID, userID)
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect user can push: %v", err)
|
||||
} else if !canPush {
|
||||
fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
cmd/web.go
13
cmd/web.go
@@ -80,7 +80,13 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
|
||||
Cache: autocert.DirCache(directory),
|
||||
Email: email,
|
||||
}
|
||||
go http.ListenAndServe(listenAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validatio happens here)
|
||||
go func() {
|
||||
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||
var err = http.ListenAndServe(setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||
if err != nil {
|
||||
log.Fatal(4, "Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||
}
|
||||
}()
|
||||
server := &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: m,
|
||||
@@ -96,7 +102,10 @@ func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
target := setting.AppURL + r.URL.RequestURI()
|
||||
// Remove the trailing slash at the end of setting.AppURL, the request
|
||||
// URI always contains a leading slash, which would result in a double
|
||||
// slash
|
||||
target := strings.TrimRight(setting.AppURL, "/") + r.URL.RequestURI()
|
||||
http.Redirect(w, r, target, http.StatusFound)
|
||||
}
|
||||
|
||||
|
@@ -212,21 +212,46 @@ func TestAPIViewRepo(t *testing.T) {
|
||||
func TestAPIOrgRepos(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
|
||||
user3 := models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User)
|
||||
// User3 is an Org. Check their repos.
|
||||
sourceOrg := models.AssertExistsAndLoadBean(t, &models.User{ID: 3}).(*models.User)
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiRepos []*api.Repository
|
||||
DecodeJSON(t, resp, &apiRepos)
|
||||
expectedLen := models.GetCount(t, models.Repository{OwnerID: sourceOrg.ID},
|
||||
models.Cond("is_private = ?", false))
|
||||
assert.Len(t, apiRepos, expectedLen)
|
||||
for _, repo := range apiRepos {
|
||||
assert.False(t, repo.Private)
|
||||
expectedResults := map[*models.User]struct {
|
||||
count int
|
||||
includesPrivate bool
|
||||
}{
|
||||
nil: {count: 1},
|
||||
user: {count: 2, includesPrivate: true},
|
||||
user2: {count: 3, includesPrivate: true},
|
||||
user3: {count: 1},
|
||||
}
|
||||
|
||||
for userToLogin, expected := range expectedResults {
|
||||
var session *TestSession
|
||||
var testName string
|
||||
var token string
|
||||
if userToLogin != nil && userToLogin.ID > 0 {
|
||||
testName = fmt.Sprintf("LoggedUser%d", userToLogin.ID)
|
||||
session = loginUser(t, userToLogin.Name)
|
||||
token = getTokenForLoggedInUser(t, session)
|
||||
} else {
|
||||
testName = "AnonymousUser"
|
||||
session = emptyTestSession(t)
|
||||
}
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
req := NewRequestf(t, "GET", "/api/v1/orgs/%s/repos?token="+token, sourceOrg.Name)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var apiRepos []*api.Repository
|
||||
DecodeJSON(t, resp, &apiRepos)
|
||||
assert.Len(t, apiRepos, expected.count)
|
||||
for _, repo := range apiRepos {
|
||||
if !expected.includesPrivate {
|
||||
assert.False(t, repo.Private)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -325,6 +325,10 @@ func (issue *Issue) APIFormat() *api.Issue {
|
||||
Updated: issue.UpdatedUnix.AsTime(),
|
||||
}
|
||||
|
||||
if issue.ClosedUnix != 0 {
|
||||
apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
|
||||
}
|
||||
|
||||
if issue.Milestone != nil {
|
||||
apiIssue.Milestone = issue.Milestone.APIFormat()
|
||||
}
|
||||
|
@@ -159,12 +159,13 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
|
||||
return fmt.Errorf("createAssigneeComment: %v", err)
|
||||
}
|
||||
|
||||
// if issue/pull is in the middle of creation - don't call webhook
|
||||
if isCreate {
|
||||
return nil
|
||||
}
|
||||
|
||||
mode, _ := accessLevel(sess, doer.ID, issue.Repo)
|
||||
if issue.IsPull {
|
||||
// if pull request is in the middle of creation - don't call webhook
|
||||
if isCreate {
|
||||
return nil
|
||||
}
|
||||
if err = issue.loadPullRequest(sess); err != nil {
|
||||
return fmt.Errorf("loadPullRequest: %v", err)
|
||||
}
|
||||
|
@@ -26,7 +26,6 @@ func addMultipleAssignees(x *xorm.Engine) error {
|
||||
IsClosed bool `xorm:"INDEX"`
|
||||
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
|
||||
NumComments int
|
||||
Ref string
|
||||
|
||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
|
@@ -5,6 +5,8 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
@@ -70,6 +72,13 @@ func removeStaleWatches(x *xorm.Engine) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var issueWatch IssueWatch
|
||||
if exist, err := sess.IsTableExist(&issueWatch); err != nil {
|
||||
return fmt.Errorf("IsExist IssueWatch: %v", err)
|
||||
} else if !exist {
|
||||
return nil
|
||||
}
|
||||
|
||||
repoCache := make(map[int64]*Repository)
|
||||
err := x.BufferSize(setting.IterateBufferSize).Iterate(new(Watch),
|
||||
func(idx int, bean interface{}) error {
|
||||
|
@@ -25,7 +25,7 @@ func reformatAndRemoveIncorrectTopics(x *xorm.Engine) (err error) {
|
||||
|
||||
type Topic struct {
|
||||
ID int64
|
||||
Name string `xorm:"UNIQUE"`
|
||||
Name string `xorm:"UNIQUE VARCHAR(25)"`
|
||||
RepoCount int
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
|
@@ -40,6 +40,14 @@ func (t *Team) getUnits(e Engine) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// GetUnitNames returns the team units names
|
||||
func (t *Team) GetUnitNames() (res []string) {
|
||||
for _, u := range t.Units {
|
||||
res = append(res, Units[u.Type].NameKey)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HasWriteAccess returns true if team has at least write level access mode.
|
||||
func (t *Team) HasWriteAccess() bool {
|
||||
return t.Authorize >= AccessModeWrite
|
||||
@@ -367,6 +375,24 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
|
||||
return fmt.Errorf("update: %v", err)
|
||||
}
|
||||
|
||||
// update units for team
|
||||
if len(t.Units) > 0 {
|
||||
for _, unit := range t.Units {
|
||||
unit.TeamID = t.ID
|
||||
}
|
||||
// Delete team-unit.
|
||||
if _, err := sess.
|
||||
Where("team_id=?", t.ID).
|
||||
Delete(new(TeamUnit)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(&t.Units); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update access for team members if needed.
|
||||
if authChanged {
|
||||
if err = t.getRepositories(sess); err != nil {
|
||||
@@ -525,6 +551,16 @@ func getUserTeams(e Engine, orgID, userID int64) (teams []*Team, err error) {
|
||||
Find(&teams)
|
||||
}
|
||||
|
||||
func getUserRepoTeams(e Engine, orgID, userID, repoID int64) (teams []*Team, err error) {
|
||||
return teams, e.
|
||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||
Join("INNER", "team_repo", "team_repo.team_id = team.id").
|
||||
Where("team.org_id = ?", orgID).
|
||||
And("team_user.uid=?", userID).
|
||||
And("team_repo.repo_id=?", repoID).
|
||||
Find(&teams)
|
||||
}
|
||||
|
||||
// GetUserTeams returns all teams that user belongs to in given organization.
|
||||
func GetUserTeams(orgID, userID int64) ([]*Team, error) {
|
||||
return getUserTeams(x, orgID, userID)
|
||||
|
@@ -32,6 +32,7 @@ import (
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/builder"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/mcuadros/go-version"
|
||||
"gopkg.in/ini.v1"
|
||||
@@ -364,7 +365,7 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
|
||||
return nil
|
||||
}
|
||||
|
||||
teams, err := getUserTeams(e, repo.OwnerID, userID)
|
||||
teams, err := getUserRepoTeams(e, repo.OwnerID, userID, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1837,55 +1838,56 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||
&RepoRedirect{RedirectRepoID: repoID},
|
||||
&Webhook{RepoID: repoID},
|
||||
&HookTask{RepoID: repoID},
|
||||
&Notification{RepoID: repoID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
|
||||
// Delete comments and attachments.
|
||||
issueIDs := make([]int64, 0, 25)
|
||||
attachmentPaths := make([]string, 0, len(issueIDs))
|
||||
if err = sess.
|
||||
Table("issue").
|
||||
Cols("id").
|
||||
Where("repo_id=?", repoID).
|
||||
Find(&issueIDs); err != nil {
|
||||
deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repoID})
|
||||
// Delete comments and attachments
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Comment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(issueIDs) > 0 {
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Comment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&IssueUser{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Reaction{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&IssueWatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Stopwatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueUser{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attachments := make([]*Attachment, 0, 5)
|
||||
if err = sess.
|
||||
In("issue_id", issueIDs).
|
||||
Find(&attachments); err != nil {
|
||||
return err
|
||||
}
|
||||
for j := range attachments {
|
||||
attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Reaction{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", issueIDs).Delete(&Attachment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueWatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Stopwatch{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attachmentPaths := make([]string, 0, 20)
|
||||
attachments := make([]*Attachment, 0, len(attachmentPaths))
|
||||
if err = sess.Join("INNER", "issue", "issue.id = attachment.issue_id").
|
||||
Where("issue.repo_id = ?", repoID).
|
||||
Find(&attachments); err != nil {
|
||||
return err
|
||||
}
|
||||
for j := range attachments {
|
||||
attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Attachment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
|
||||
|
@@ -535,6 +535,7 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
||||
if err = sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
sess.Close()
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
@@ -543,6 +544,10 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
||||
// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
|
||||
// outside any session scope independently.
|
||||
func RewriteAllPublicKeys() error {
|
||||
return rewriteAllPublicKeys(x)
|
||||
}
|
||||
|
||||
func rewriteAllPublicKeys(e Engine) error {
|
||||
//Don't rewrite key if internal server
|
||||
if setting.SSH.StartBuiltinServer {
|
||||
return nil
|
||||
@@ -569,7 +574,7 @@ func RewriteAllPublicKeys() error {
|
||||
}
|
||||
}
|
||||
|
||||
err = x.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
err = e.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||
return err
|
||||
})
|
||||
|
@@ -26,7 +26,7 @@ var topicPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
|
||||
// Topic represents a topic of repositories
|
||||
type Topic struct {
|
||||
ID int64
|
||||
Name string `xorm:"UNIQUE"`
|
||||
Name string `xorm:"UNIQUE VARCHAR(25)"`
|
||||
RepoCount int
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
|
@@ -4,6 +4,10 @@
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UnitType is Unit's Type
|
||||
type UnitType int
|
||||
|
||||
@@ -137,3 +141,16 @@ var (
|
||||
UnitTypeExternalWiki: UnitExternalWiki,
|
||||
}
|
||||
)
|
||||
|
||||
// FindUnitTypes give the unit key name and return unit
|
||||
func FindUnitTypes(nameKeys ...string) (res []UnitType) {
|
||||
for _, key := range nameKeys {
|
||||
for t, u := range Units {
|
||||
if strings.EqualFold(key, u.NameKey) {
|
||||
res = append(res, t)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@@ -1038,25 +1038,26 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
&EmailAddress{UID: u.ID},
|
||||
&UserOpenID{UID: u.ID},
|
||||
&Reaction{UserID: u.ID},
|
||||
&TeamUser{UID: u.ID},
|
||||
&Collaboration{UserID: u.ID},
|
||||
&Stopwatch{UserID: u.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
|
||||
// ***** START: PublicKey *****
|
||||
keys := make([]*PublicKey, 0, 10)
|
||||
if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("get all public keys: %v", err)
|
||||
}
|
||||
|
||||
keyIDs := make([]int64, len(keys))
|
||||
for i := range keys {
|
||||
keyIDs[i] = keys[i].ID
|
||||
}
|
||||
if err = deletePublicKeys(e, keyIDs...); err != nil {
|
||||
if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||
}
|
||||
rewriteAllPublicKeys(e)
|
||||
// ***** END: PublicKey *****
|
||||
|
||||
// ***** START: GPGPublicKey *****
|
||||
if _, err = e.Delete(&GPGKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("deleteGPGKeys: %v", err)
|
||||
}
|
||||
// ***** END: GPGPublicKey *****
|
||||
|
||||
// Clear assignee.
|
||||
if err = clearAssigneeByUserID(e, u.ID); err != nil {
|
||||
return fmt.Errorf("clear assignee: %v", err)
|
||||
@@ -1110,6 +1111,7 @@ func DeleteUser(u *User) (err error) {
|
||||
if err = sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
sess.Close()
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ func InitIssueIndexer(populateIndexer func() error) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = createIssueIndexer(); err != nil {
|
||||
if err = createIssueIndexer(setting.Indexer.IssuePath, issueIndexerLatestVersion); err != nil {
|
||||
log.Fatal(4, "InitIssuesIndexer: create index, %v", err)
|
||||
}
|
||||
if err = populateIndexer(); err != nil {
|
||||
@@ -69,7 +69,7 @@ func InitIssueIndexer(populateIndexer func() error) {
|
||||
}
|
||||
|
||||
// createIssueIndexer create an issue indexer if one does not already exist
|
||||
func createIssueIndexer() error {
|
||||
func createIssueIndexer(path string, latestVersion int) error {
|
||||
mapping := bleve.NewIndexMapping()
|
||||
docMapping := bleve.NewDocumentMapping()
|
||||
|
||||
@@ -100,8 +100,14 @@ func createIssueIndexer() error {
|
||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||
|
||||
var err error
|
||||
issueIndexer, err = bleve.New(setting.Indexer.IssuePath, mapping)
|
||||
return err
|
||||
issueIndexer, err = bleve.New(path, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
|
||||
Version: latestVersion,
|
||||
})
|
||||
}
|
||||
|
||||
// IssueIndexerBatch batch to add updates to
|
||||
|
@@ -84,7 +84,7 @@ func InitRepoIndexer(populateIndexer func() error) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = createRepoIndexer(); err != nil {
|
||||
if err = createRepoIndexer(setting.Indexer.RepoPath, repoIndexerLatestVersion); err != nil {
|
||||
log.Fatal(4, "CreateRepoIndexer: %v", err)
|
||||
}
|
||||
if err = populateIndexer(); err != nil {
|
||||
@@ -93,7 +93,7 @@ func InitRepoIndexer(populateIndexer func() error) {
|
||||
}
|
||||
|
||||
// createRepoIndexer create a repo indexer if one does not already exist
|
||||
func createRepoIndexer() error {
|
||||
func createRepoIndexer(path string, latestVersion int) error {
|
||||
var err error
|
||||
docMapping := bleve.NewDocumentMapping()
|
||||
numericFieldMapping := bleve.NewNumericFieldMapping()
|
||||
@@ -119,8 +119,13 @@ func createRepoIndexer() error {
|
||||
mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
|
||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||
|
||||
repoIndexer, err = bleve.New(setting.Indexer.RepoPath, mapping)
|
||||
return err
|
||||
repoIndexer, err = bleve.New(path, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rupture.WriteIndexMetadata(path, &rupture.IndexMetadata{
|
||||
Version: latestVersion,
|
||||
})
|
||||
}
|
||||
|
||||
func filenameIndexerID(repoID int64, filename string) string {
|
||||
|
@@ -8,7 +8,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -25,9 +24,6 @@ type FileLogWriter struct {
|
||||
// The opened file
|
||||
Filename string `json:"filename"`
|
||||
|
||||
Maxlines int `json:"maxlines"`
|
||||
maxlinesCurlines int
|
||||
|
||||
// Rotate at size
|
||||
Maxsize int `json:"maxsize"`
|
||||
maxsizeCursize int
|
||||
@@ -69,7 +65,6 @@ func (l *MuxWriter) SetFd(fd *os.File) {
|
||||
func NewFileWriter() LoggerInterface {
|
||||
w := &FileLogWriter{
|
||||
Filename: "",
|
||||
Maxlines: 1000000,
|
||||
Maxsize: 1 << 28, //256 MB
|
||||
Daily: true,
|
||||
Maxdays: 7,
|
||||
@@ -87,7 +82,6 @@ func NewFileWriter() LoggerInterface {
|
||||
// config like:
|
||||
// {
|
||||
// "filename":"log/gogs.log",
|
||||
// "maxlines":10000,
|
||||
// "maxsize":1<<30,
|
||||
// "daily":true,
|
||||
// "maxdays":15,
|
||||
@@ -116,15 +110,13 @@ func (w *FileLogWriter) StartLogger() error {
|
||||
func (w *FileLogWriter) docheck(size int) {
|
||||
w.startLock.Lock()
|
||||
defer w.startLock.Unlock()
|
||||
if w.Rotate && ((w.Maxlines > 0 && w.maxlinesCurlines >= w.Maxlines) ||
|
||||
(w.Maxsize > 0 && w.maxsizeCursize >= w.Maxsize) ||
|
||||
if w.Rotate && ((w.Maxsize > 0 && w.maxsizeCursize >= w.Maxsize) ||
|
||||
(w.Daily && time.Now().Day() != w.dailyOpenDate)) {
|
||||
if err := w.DoRotate(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.maxlinesCurlines++
|
||||
w.maxsizeCursize += size
|
||||
}
|
||||
|
||||
@@ -152,15 +144,6 @@ func (w *FileLogWriter) initFd() error {
|
||||
}
|
||||
w.maxsizeCursize = int(finfo.Size())
|
||||
w.dailyOpenDate = time.Now().Day()
|
||||
if finfo.Size() > 0 {
|
||||
content, err := ioutil.ReadFile(w.Filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.maxlinesCurlines = len(strings.Split(string(content), "\n"))
|
||||
} else {
|
||||
w.maxlinesCurlines = 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2018 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.
|
||||
|
||||
@@ -38,7 +39,16 @@ func (r *Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content []
|
||||
link = []byte(mLink)
|
||||
}
|
||||
|
||||
r.Renderer.Link(out, link, title, content)
|
||||
if len(content) > 10 && string(content[0:9]) == "<a href=\"" && bytes.Contains(content[9:], []byte("<img")) {
|
||||
// Image with link case: markdown `[![]()]()`
|
||||
// If the content is an image, then we change the original href around it
|
||||
// which points to itself to a new address "link"
|
||||
rightQuote := bytes.Index(content[9:], []byte("\""))
|
||||
content = bytes.Replace(content, content[9:9+rightQuote], link, 1)
|
||||
out.Write(content)
|
||||
} else {
|
||||
r.Renderer.Link(out, link, title, content)
|
||||
}
|
||||
}
|
||||
|
||||
// List renders markdown bullet or digit lists to HTML
|
||||
@@ -90,13 +100,6 @@ func (r *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
||||
r.Renderer.ListItem(out, text, flags)
|
||||
}
|
||||
|
||||
// Note: this section is for purpose of increase performance and
|
||||
// reduce memory allocation at runtime since they are constant literals.
|
||||
var (
|
||||
svgSuffix = []byte(".svg")
|
||||
svgSuffixWithMark = []byte(".svg?")
|
||||
)
|
||||
|
||||
// Image defines how images should be processed to produce corresponding HTML elements.
|
||||
func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
|
||||
prefix := r.URLPrefix
|
||||
@@ -104,22 +107,14 @@ func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byt
|
||||
prefix = util.URLJoin(prefix, "wiki", "raw")
|
||||
}
|
||||
prefix = strings.Replace(prefix, "/src/", "/raw/", 1)
|
||||
if len(link) > 0 {
|
||||
if markup.IsLink(link) {
|
||||
// External link with .svg suffix usually means CI status.
|
||||
// TODO: define a keyword to allow non-svg images render as external link.
|
||||
if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) {
|
||||
r.Renderer.Image(out, link, title, alt)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
lnk := string(link)
|
||||
lnk = util.URLJoin(prefix, lnk)
|
||||
lnk = strings.Replace(lnk, " ", "+", -1)
|
||||
link = []byte(lnk)
|
||||
}
|
||||
if len(link) > 0 && !markup.IsLink(link) {
|
||||
lnk := string(link)
|
||||
lnk = util.URLJoin(prefix, lnk)
|
||||
lnk = strings.Replace(lnk, " ", "+", -1)
|
||||
link = []byte(lnk)
|
||||
}
|
||||
|
||||
// Put a link around it pointing to itself by default
|
||||
out.WriteString(`<a href="`)
|
||||
out.Write(link)
|
||||
out.WriteString(`">`)
|
||||
|
@@ -73,6 +73,7 @@ func TestRender_Images(t *testing.T) {
|
||||
|
||||
url := "../../.images/src/02/train.jpg"
|
||||
title := "Train"
|
||||
href := "https://gitea.io"
|
||||
result := util.URLJoin(AppSubURL, url)
|
||||
|
||||
test(
|
||||
@@ -82,6 +83,9 @@ func TestRender_Images(t *testing.T) {
|
||||
test(
|
||||
"[["+title+"|"+url+"]]",
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
|
||||
test(
|
||||
"[]("+href+")",
|
||||
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
}
|
||||
|
||||
func testAnswers(baseURLContent, baseURLImages string) []string {
|
||||
|
@@ -1325,10 +1325,9 @@ func newLogService() {
|
||||
}
|
||||
|
||||
LogConfigs[i] = fmt.Sprintf(
|
||||
`{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
|
||||
`{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
|
||||
logPath,
|
||||
sec.Key("LOG_ROTATE").MustBool(true),
|
||||
sec.Key("MAX_LINES").MustInt(1000000),
|
||||
1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
|
||||
sec.Key("DAILY_ROTATE").MustBool(true),
|
||||
sec.Key("MAX_DAYS").MustInt(7))
|
||||
@@ -1391,10 +1390,9 @@ func NewXORMLogService(disableConsole bool) {
|
||||
logPath = path.Join(filepath.Dir(logPath), "xorm.log")
|
||||
|
||||
logConfigs = fmt.Sprintf(
|
||||
`{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
|
||||
`{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
|
||||
logPath,
|
||||
sec.Key("LOG_ROTATE").MustBool(true),
|
||||
sec.Key("MAX_LINES").MustInt(1000000),
|
||||
1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
|
||||
sec.Key("DAILY_ROTATE").MustBool(true),
|
||||
sec.Key("MAX_DAYS").MustInt(7))
|
||||
|
@@ -457,7 +457,7 @@ issues.next=Página Siguiente
|
||||
issues.open_title=Abierta
|
||||
issues.closed_title=Cerrada
|
||||
issues.num_comments=%d comentarios
|
||||
issues.commented_at=`comentado <a href="#%s"> %s`</a>
|
||||
issues.commented_at=`comentado <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario?
|
||||
issues.no_content=Aún no existe contenido.
|
||||
issues.close_issue=Cerrar
|
||||
|
@@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
function htmlEncode(text) {
|
||||
return jQuery('<div />').text(text).html()
|
||||
}
|
||||
|
||||
var csrf;
|
||||
var suburl;
|
||||
|
||||
@@ -312,12 +316,12 @@ function initCommentForm() {
|
||||
switch (input_id) {
|
||||
case '#milestone_id':
|
||||
$list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
|
||||
$(this).text() + '</a>');
|
||||
htmlEncode($(this).text()) + '</a>');
|
||||
break;
|
||||
case '#assignee_id':
|
||||
$list.find('.selected').html('<a class="item" href=' + $(this).data('href') + '>' +
|
||||
'<img class="ui avatar image" src=' + $(this).data('avatar') + '>' +
|
||||
$(this).text() + '</a>');
|
||||
htmlEncode($(this).text()) + '</a>');
|
||||
}
|
||||
$('.ui' + select_id + '.list .no-select').addClass('hide');
|
||||
$(input_id).val($(this).data('id'));
|
||||
@@ -1456,7 +1460,7 @@ function searchUsers() {
|
||||
$.each(response.data, function (i, item) {
|
||||
var title = item.login;
|
||||
if (item.full_name && item.full_name.length > 0) {
|
||||
title += ' (' + item.full_name + ')';
|
||||
title += ' (' + htmlEncode(item.full_name) + ')';
|
||||
}
|
||||
items.push({
|
||||
title: title,
|
||||
@@ -1530,7 +1534,7 @@ function initU2FAuth() {
|
||||
}
|
||||
u2fApi.ensureSupport()
|
||||
.then(function () {
|
||||
$.getJSON('/user/u2f/challenge').success(function(req) {
|
||||
$.getJSON(suburl + '/user/u2f/challenge').success(function(req) {
|
||||
u2fApi.sign(req.appId, req.challenge, req.registeredKeys, 30)
|
||||
.then(u2fSigned)
|
||||
.catch(function (err) {
|
||||
@@ -1543,16 +1547,16 @@ function initU2FAuth() {
|
||||
});
|
||||
}).catch(function () {
|
||||
// Fallback in case browser do not support U2F
|
||||
window.location.href = "/user/two_factor"
|
||||
window.location.href = suburl + "/user/two_factor"
|
||||
})
|
||||
}
|
||||
function u2fSigned(resp) {
|
||||
$.ajax({
|
||||
url:'/user/u2f/sign',
|
||||
type:"POST",
|
||||
url: suburl + '/user/u2f/sign',
|
||||
type: "POST",
|
||||
headers: {"X-Csrf-Token": csrf},
|
||||
data: JSON.stringify(resp),
|
||||
contentType:"application/json; charset=utf-8",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
}).done(function(res){
|
||||
window.location.replace(res);
|
||||
}).fail(function (xhr, textStatus) {
|
||||
@@ -1565,11 +1569,11 @@ function u2fRegistered(resp) {
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url:'/user/settings/security/u2f/register',
|
||||
type:"POST",
|
||||
url: suburl + '/user/settings/security/u2f/register',
|
||||
type: "POST",
|
||||
headers: {"X-Csrf-Token": csrf},
|
||||
data: JSON.stringify(resp),
|
||||
contentType:"application/json; charset=utf-8",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
success: function(){
|
||||
window.location.reload();
|
||||
},
|
||||
@@ -1623,7 +1627,7 @@ function initU2FRegister() {
|
||||
}
|
||||
|
||||
function u2fRegisterRequest() {
|
||||
$.post("/user/settings/security/u2f/request_register", {
|
||||
$.post(suburl + "/user/settings/security/u2f/request_register", {
|
||||
"_csrf": csrf,
|
||||
"name": $('#nickname').val()
|
||||
}).success(function(req) {
|
||||
@@ -2510,7 +2514,7 @@ function initTopicbar() {
|
||||
if (res.topics) {
|
||||
formattedResponse.success = true;
|
||||
for (var i=0;i < res.topics.length;i++) {
|
||||
formattedResponse.results.push({"description": res.topics[i].Name, "data-value":res.topics[i].Name})
|
||||
formattedResponse.results.push({"description": res.topics[i].Name, "data-value": res.topics[i].Name})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2625,13 +2629,13 @@ function initIssueList() {
|
||||
$('.new-dependency-drop-list')
|
||||
.dropdown({
|
||||
apiSettings: {
|
||||
url: suburl + '/api/v1/repos' + repolink + '/issues?q={query}',
|
||||
url: suburl + '/api/v1/repos/' + repolink + '/issues?q={query}',
|
||||
onResponse: function(response) {
|
||||
var filteredResponse = {'success': true, 'results': []};
|
||||
// Parse the response from the api to work with our dropdown
|
||||
$.each(response, function(index, issue) {
|
||||
filteredResponse.results.push({
|
||||
'name' : '#' + issue.number + ' ' + issue.title,
|
||||
'name' : '#' + issue.number + ' ' + htmlEncode(issue.title),
|
||||
'value' : issue.id
|
||||
});
|
||||
});
|
||||
|
@@ -196,5 +196,6 @@ func ToTeam(team *models.Team) *api.Team {
|
||||
Name: team.Name,
|
||||
Description: team.Description,
|
||||
Permission: team.Authorize.String(),
|
||||
Units: team.GetUnitNames(),
|
||||
}
|
||||
}
|
||||
|
@@ -89,6 +89,20 @@ func CreateTeam(ctx *context.APIContext, form api.CreateTeamOption) {
|
||||
Description: form.Description,
|
||||
Authorize: models.ParseAccessMode(form.Permission),
|
||||
}
|
||||
|
||||
unitTypes := models.FindUnitTypes(form.Units...)
|
||||
|
||||
if team.Authorize < models.AccessModeOwner {
|
||||
var units = make([]*models.TeamUnit, 0, len(form.Units))
|
||||
for _, tp := range unitTypes {
|
||||
units = append(units, &models.TeamUnit{
|
||||
OrgID: ctx.Org.Organization.ID,
|
||||
Type: tp,
|
||||
})
|
||||
}
|
||||
team.Units = units
|
||||
}
|
||||
|
||||
if err := models.NewTeam(team); err != nil {
|
||||
if models.IsErrTeamAlreadyExist(err) {
|
||||
ctx.Error(422, "", err)
|
||||
@@ -127,6 +141,19 @@ func EditTeam(ctx *context.APIContext, form api.EditTeamOption) {
|
||||
team.Name = form.Name
|
||||
team.Description = form.Description
|
||||
team.Authorize = models.ParseAccessMode(form.Permission)
|
||||
unitTypes := models.FindUnitTypes(form.Units...)
|
||||
|
||||
if team.Authorize < models.AccessModeOwner {
|
||||
var units = make([]*models.TeamUnit, 0, len(form.Units))
|
||||
for _, tp := range unitTypes {
|
||||
units = append(units, &models.TeamUnit{
|
||||
OrgID: ctx.Org.Organization.ID,
|
||||
Type: tp,
|
||||
})
|
||||
}
|
||||
team.Units = units
|
||||
}
|
||||
|
||||
if err := models.UpdateTeam(team, true); err != nil {
|
||||
ctx.Error(500, "EditTeam", err)
|
||||
return
|
||||
|
@@ -508,7 +508,7 @@ func Delete(ctx *context.APIContext) {
|
||||
owner := ctx.Repo.Owner
|
||||
repo := ctx.Repo.Repository
|
||||
|
||||
if owner.IsOrganization() {
|
||||
if owner.IsOrganization() && !ctx.User.IsAdmin {
|
||||
isOwner, err := owner.IsOwnedBy(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.Error(500, "IsOwnedBy", err)
|
||||
|
@@ -11,14 +11,13 @@ import (
|
||||
)
|
||||
|
||||
// listUserRepos - List the repositories owned by the given user.
|
||||
func listUserRepos(ctx *context.APIContext, u *models.User) {
|
||||
showPrivateRepos := ctx.IsSigned && (ctx.User.ID == u.ID || ctx.User.IsAdmin)
|
||||
repos, err := models.GetUserRepositories(u.ID, showPrivateRepos, 1, u.NumRepos, "")
|
||||
func listUserRepos(ctx *context.APIContext, u *models.User, private bool) {
|
||||
repos, err := models.GetUserRepositories(u.ID, private, 1, u.NumRepos, "")
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetUserRepositories", err)
|
||||
return
|
||||
}
|
||||
apiRepos := make([]*api.Repository, len(repos))
|
||||
apiRepos := make([]*api.Repository, 0, len(repos))
|
||||
var ctxUserID int64
|
||||
if ctx.User != nil {
|
||||
ctxUserID = ctx.User.ID
|
||||
@@ -29,7 +28,9 @@ func listUserRepos(ctx *context.APIContext, u *models.User) {
|
||||
ctx.Error(500, "AccessLevel", err)
|
||||
return
|
||||
}
|
||||
apiRepos[i] = repos[i].APIFormat(access)
|
||||
if ctx.IsSigned && ctx.User.IsAdmin || access >= models.AccessModeRead {
|
||||
apiRepos = append(apiRepos, repos[i].APIFormat(access))
|
||||
}
|
||||
}
|
||||
ctx.JSON(200, &apiRepos)
|
||||
}
|
||||
@@ -54,7 +55,8 @@ func ListUserRepos(ctx *context.APIContext) {
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
listUserRepos(ctx, user)
|
||||
private := ctx.IsSigned && (ctx.User.ID == user.ID || ctx.User.IsAdmin)
|
||||
listUserRepos(ctx, user, private)
|
||||
}
|
||||
|
||||
// ListMyRepos - list the repositories you own or have access to.
|
||||
@@ -106,5 +108,5 @@ func ListOrgRepos(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepositoryList"
|
||||
listUserRepos(ctx, ctx.Org.Organization)
|
||||
listUserRepos(ctx, ctx.Org.Organization, ctx.IsSigned)
|
||||
}
|
||||
|
@@ -559,6 +559,17 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + branchName + "/" + form.TreePath)
|
||||
}
|
||||
|
||||
func cleanUploadFileName(name string) string {
|
||||
name = strings.TrimLeft(name, "./\\")
|
||||
name = strings.Replace(name, "../", "", -1)
|
||||
name = strings.Replace(name, "..\\", "", -1)
|
||||
name = strings.TrimPrefix(path.Clean(name), ".git/")
|
||||
if name == ".git" {
|
||||
return ""
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// UploadFileToServer upload file to server file dir not git
|
||||
func UploadFileToServer(ctx *context.Context) {
|
||||
file, header, err := ctx.Req.FormFile("file")
|
||||
@@ -591,7 +602,13 @@ func UploadFileToServer(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
upload, err := models.NewUpload(header.Filename, buf, file)
|
||||
name := cleanUploadFileName(header.Filename)
|
||||
if len(name) == 0 {
|
||||
ctx.Error(500, "Upload file name is invalid")
|
||||
return
|
||||
}
|
||||
|
||||
upload, err := models.NewUpload(name, buf, file)
|
||||
if err != nil {
|
||||
ctx.Error(500, fmt.Sprintf("NewUpload: %v", err))
|
||||
return
|
||||
|
30
routers/repo/editor_test.go
Normal file
30
routers/repo/editor_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2018 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 repo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCleanUploadName(t *testing.T) {
|
||||
models.PrepareTestEnv(t)
|
||||
|
||||
var kases = map[string]string{
|
||||
".git/refs/master": "git/refs/master",
|
||||
"/root/abc": "root/abc",
|
||||
"./../../abc": "abc",
|
||||
"a/../.git": "a/.git",
|
||||
"a/../../../abc": "a/abc",
|
||||
"../../../acd": "acd",
|
||||
"../../.git/abc": "git/abc",
|
||||
"..\\..\\.git/abc": "git/abc",
|
||||
}
|
||||
for k, v := range kases {
|
||||
assert.EqualValues(t, v, cleanUploadFileName(k))
|
||||
}
|
||||
}
|
@@ -73,7 +73,6 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err
|
||||
|
||||
commit, err := wikiRepo.GetBranchCommit("master")
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
return wikiRepo, nil, err
|
||||
}
|
||||
return wikiRepo, commit, nil
|
||||
@@ -111,6 +110,9 @@ func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName strin
|
||||
func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, *git.TreeEntry) {
|
||||
wikiRepo, commit, err := findWikiRepoCommit(ctx)
|
||||
if err != nil {
|
||||
if !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@@ -51,8 +51,6 @@
|
||||
{{end}}
|
||||
{{if .RequireTribute}}
|
||||
<script src="{{AppSubUrl}}/vendor/plugins/tribute/tribute.min.js"></script>
|
||||
|
||||
{{if .Assignees}}
|
||||
<script>
|
||||
var issuesTribute = new Tribute({
|
||||
values: [
|
||||
@@ -73,7 +71,6 @@
|
||||
})
|
||||
issuesTribute.attach(document.getElementById('content'))
|
||||
</script>
|
||||
{{end}}
|
||||
<script>
|
||||
var emojiTribute = new Tribute({
|
||||
collection: [{
|
||||
|
@@ -3,9 +3,7 @@
|
||||
<div class="file-body file-code code-view code-diff">
|
||||
<table>
|
||||
<tbody>
|
||||
{{with .File}}
|
||||
{{template "repo/diff/section_unified" .}}
|
||||
{{end}}
|
||||
{{template "repo/diff/section_unified" dict "file" .File "root" $}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@@ -30,7 +30,7 @@
|
||||
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
|
||||
<a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a>
|
||||
{{if not .IsNewFile}}
|
||||
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "repo.release.preview"}}</a>
|
||||
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "preview"}}</a>
|
||||
<a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.editor.preview_changes"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@@ -338,7 +338,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{if .CanCreateIssueDependencies}}
|
||||
<input type="hidden" id="repolink" value="{{$.RepoLink}}">
|
||||
<input type="hidden" id="repolink" value="{{$.RepoRelPath}}">
|
||||
<!-- I know, there is probably a better way to do this -->
|
||||
<input type="hidden" id="issueIndex" value="{{.Issue.Index}}"/>
|
||||
|
||||
|
@@ -38,7 +38,7 @@
|
||||
{{else}}
|
||||
<span class="text grey"><i class="octicon octicon-primitive-dot"></i></span>
|
||||
{{end}}
|
||||
<a href="{{$.BaseLink}}/settings/hooks/{{.ID}}">{{.URL}}</a>
|
||||
<a class="dont-break-out" href="{{$.BaseLink}}/settings/hooks/{{.ID}}">{{.URL}}</a>
|
||||
<div class="ui right">
|
||||
<span class="text blue"><a href="{{$.BaseLink}}/settings/hooks/{{.ID}}"><i class="fa fa-pencil"></i></a></span>
|
||||
<span class="text red"><a class="delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}"><i class="fa fa-times"></i></a></span>
|
||||
|
@@ -6128,6 +6128,22 @@
|
||||
"admin"
|
||||
],
|
||||
"x-go-name": "Permission"
|
||||
},
|
||||
"units": {
|
||||
"type": "array",
|
||||
"enum": [
|
||||
"repo.code",
|
||||
"repo.issues",
|
||||
"repo.ext_issues",
|
||||
"repo.wiki",
|
||||
"repo.pulls",
|
||||
"repo.releases",
|
||||
"repo.ext_wiki"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Units"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"
|
||||
@@ -6503,6 +6519,22 @@
|
||||
"admin"
|
||||
],
|
||||
"x-go-name": "Permission"
|
||||
},
|
||||
"units": {
|
||||
"type": "array",
|
||||
"enum": [
|
||||
"repo.code",
|
||||
"repo.issues",
|
||||
"repo.ext_issues",
|
||||
"repo.wiki",
|
||||
"repo.pulls",
|
||||
"repo.releases",
|
||||
"repo.ext_wiki"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Units"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"
|
||||
@@ -7550,6 +7582,22 @@
|
||||
"owner"
|
||||
],
|
||||
"x-go-name": "Permission"
|
||||
},
|
||||
"units": {
|
||||
"type": "array",
|
||||
"enum": [
|
||||
"repo.code",
|
||||
"repo.issues",
|
||||
"repo.ext_issues",
|
||||
"repo.wiki",
|
||||
"repo.pulls",
|
||||
"repo.releases",
|
||||
"repo.ext_wiki"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Units"
|
||||
}
|
||||
},
|
||||
"x-go-package": "code.gitea.io/gitea/vendor/code.gitea.io/sdk/gitea"
|
||||
|
7
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
7
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
@@ -1,4 +1,5 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2018 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.
|
||||
|
||||
@@ -11,6 +12,8 @@ type Team struct {
|
||||
Description string `json:"description"`
|
||||
// enum: none,read,write,admin,owner
|
||||
Permission string `json:"permission"`
|
||||
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
|
||||
Units []string `json:"units"`
|
||||
}
|
||||
|
||||
// CreateTeamOption options for creating a team
|
||||
@@ -20,6 +23,8 @@ type CreateTeamOption struct {
|
||||
Description string `json:"description" binding:"MaxSize(255)"`
|
||||
// enum: read,write,admin
|
||||
Permission string `json:"permission"`
|
||||
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
|
||||
Units []string `json:"units"`
|
||||
}
|
||||
|
||||
// EditTeamOption options for editing a team
|
||||
@@ -29,4 +34,6 @@ type EditTeamOption struct {
|
||||
Description string `json:"description" binding:"MaxSize(255)"`
|
||||
// enum: read,write,admin
|
||||
Permission string `json:"permission"`
|
||||
// enum: repo.code,repo.issues,repo.ext_issues,repo.wiki,repo.pulls,repo.releases,repo.ext_wiki
|
||||
Units []string `json:"units"`
|
||||
}
|
||||
|
Reference in New Issue
Block a user