Compare commits

...

8 Commits

Author SHA1 Message Date
techknowlogick
ad9f9cdc30 Add 1.6.1 changelog (#5500) 2018-12-09 21:06:16 +08:00
Lunny Xiao
8237fd4a2d fix topic name length on database (#5493) (#5495) 2018-12-09 02:57:49 +02:00
romankl
8e4a0a978a ensure that the closed_at is set for closed (#5450)
right now the `closed_at` field for json responses is not filled during
the `APIIssue` creation for api responses.

For a closed issue you get a result like:
```json
"state":"open","comments":0,"created_at":"2018-11-29T16:39:24+01:00",
"updated_at":"2018-11-30T10:49:19+01:00","closed_at":null,
"due_date":null,"pull_request":null}
```
which has no information about the closing date. (which exists in the
db and ui)
with this PR the result changes to this:

```json
:null,"assignee":null,"assignees":null,
"state":"closed",
"comments":0,"created_at":"2018-11-29T16:43:05+01:00",
"updated_at":"2018-12-02T19:17:05+01:00",
"closed_at":"2018-12-02T19:17:05+01:00",
"due_date":null,"pull_request":null}
```

fixes: https://github.com/go-gitea/gitea/issues/5446
Signed-off-by: Roman <romaaan.git@gmail.com>
2018-12-02 17:50:47 -05:00
Lanre Adelowo
c1275e2ba6 Admin should be able to delete repos even if he is not a member of the organization (#5443) (#5447) 2018-12-02 20:07:20 +02:00
romankl
7bc1faabdb word-break the WebHook url to prevent a ui-break (#5445)
right now, the url is displayed with an anchor tag with no classes. If
the url is really really long, the url will break out of the containing
div and (depending on the url length) the browser shows the horizontal
scrollbar.
This pr makes use of the already existing css class `dont-break-out`
which gives all the anchor the necessary properties to prevent the
break.
Another solution could be to introduce some classes like
`text text-break-word`, but that would duplicate the `dont-break-out`
class just for text elements that use the `text` class.

fixes: https://github.com/go-gitea/gitea/issues/5416
Signed-off-by: Roman <romaaan.git@gmail.com>
2018-12-02 10:47:45 -05:00
Lunny Xiao
e406dc058d Fix repository deletion when there is large number of issues in it (#5426) (#5434) 2018-11-30 09:38:35 -05:00
Lauris BH
328e38ebc7 Fix dependent issue searching when gitea is run in subpath (#5392) (#5400) 2018-11-25 19:27:17 -05:00
Daniel Balko
773addf727 Backported #5383 on v1.6: API: '/orgs/:org/repos': return private repos with read access (#5310) (#3829) (#5393)
Signed-off-by: Daniel Balko <inxonic+github@gmail.com>
2018-11-24 13:14:27 +02:00
11 changed files with 106 additions and 64 deletions

View File

@@ -4,6 +4,16 @@ 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.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)

View File

@@ -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)
}
}
})
}
}

View File

@@ -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()
}

View File

@@ -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"`

View File

@@ -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"
@@ -1841,51 +1842,51 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
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 {

View File

@@ -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"`

View File

@@ -2625,7 +2625,7 @@ 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

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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}}"/>

View File

@@ -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>