mirror of
https://github.com/go-gitea/gitea.git
synced 2025-08-12 05:22:01 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
dc73b2748d | ||
|
31ad8b7026 | ||
|
d07edc5336 | ||
|
63cb160cb1 | ||
|
8d5c3d3d0b | ||
|
706d85b87d | ||
|
75e491c03e | ||
|
608f46e59c | ||
|
895764e7f5 | ||
|
21983965d0 | ||
|
e069a75817 | ||
|
ebb8fa610c | ||
|
c8fc7fce4a |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -4,6 +4,21 @@ 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.8.2](https://github.com/go-gitea/gitea/releases/tag/v1.8.2) - 2019-05-29
|
||||
* BUGFIXES
|
||||
* Fix possbile mysql invalid connnection error (#7051) (#7071)
|
||||
* Handle invalid administrator username on install page (#7060) (#7063)
|
||||
* Disable arm7 builds (#7037) (#7042)
|
||||
* Fix default for allowing new organization creation for new users (#7017) (#7034)
|
||||
* SearchRepositoryByName improvements and unification (#6897) (#7002)
|
||||
* Fix u2f registrationlist ToRegistrations() method (#6980) (#6982)
|
||||
* Allow collaborators to view repo owned by private org (#6965) (#6968)
|
||||
* Use AppURL for Oauth user link (#6894) (#6925)
|
||||
* Escape the commit message on issues update (#6901) (#6902)
|
||||
* Fix regression for API users search (#6882) (#6885)
|
||||
* Handle early git version's lack of get-url (#7065) (#7076)
|
||||
* Fix wrong init dependency on markup extensions (#7038) (#7074)
|
||||
|
||||
## [1.8.1](https://github.com/go-gitea/gitea/releases/tag/v1.8.1) - 2019-05-08
|
||||
* BUGFIXES
|
||||
* Fix 404 when sending pull requests in some situations (#6871) (#6873)
|
||||
|
2
Makefile
2
Makefile
@@ -336,7 +336,7 @@ release-linux:
|
||||
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
$(GO) get -u src.techknowlogick.com/xgo; \
|
||||
fi
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/*' -out gitea-$(VERSION) .
|
||||
xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
|
||||
ifeq ($(CI),drone)
|
||||
cp /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
@@ -15,7 +15,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup/external"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
@@ -120,8 +119,6 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
routers.GlobalInit()
|
||||
|
||||
external.RegisterParsers()
|
||||
|
||||
m := routes.NewMacaron()
|
||||
routes.RegisterRoutes(m)
|
||||
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/external"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
@@ -113,6 +114,7 @@ func runPR() {
|
||||
log.Printf("[PR] Setting up router\n")
|
||||
//routers.GlobalInit()
|
||||
external.RegisterParsers()
|
||||
markup.Init()
|
||||
m := routes.NewMacaron()
|
||||
routes.RegisterRoutes(m)
|
||||
|
||||
|
@@ -129,3 +129,18 @@ func TestAPIListUsers(t *testing.T) {
|
||||
numberOfUsers := models.GetCount(t, &models.User{}, "type = 0")
|
||||
assert.Equal(t, numberOfUsers, len(users))
|
||||
}
|
||||
|
||||
func TestAPIListUsersNotLoggedIn(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
req := NewRequest(t, "GET", "/api/v1/admin/users")
|
||||
MakeRequest(t, req, http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
func TestAPIListUsersNonAdmin(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
nonAdminUsername := "user2"
|
||||
session := loginUser(t, nonAdminUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
req := NewRequestf(t, "GET", "/api/v1/admin/users?token=%s", token)
|
||||
session.MakeRequest(t, req, http.StatusForbidden)
|
||||
}
|
||||
|
@@ -69,40 +69,41 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
name, requestURL string
|
||||
expectedResults
|
||||
}{
|
||||
{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
|
||||
{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50&private=false", expectedResults: expectedResults{
|
||||
nil: {count: 19},
|
||||
user: {count: 19},
|
||||
user2: {count: 19}},
|
||||
},
|
||||
{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
|
||||
{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10&private=false", expectedResults: expectedResults{
|
||||
nil: {count: 10},
|
||||
user: {count: 10},
|
||||
user2: {count: 10}},
|
||||
},
|
||||
{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search?default", expectedResults: expectedResults{
|
||||
{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search?default&private=false", expectedResults: expectedResults{
|
||||
nil: {count: 10},
|
||||
user: {count: 10},
|
||||
user2: {count: 10}},
|
||||
},
|
||||
{name: "RepositoriesByName", requestURL: fmt.Sprintf("/api/v1/repos/search?q=%s", "big_test_"), expectedResults: expectedResults{
|
||||
{name: "RepositoriesByName", requestURL: fmt.Sprintf("/api/v1/repos/search?q=%s&private=false", "big_test_"), expectedResults: expectedResults{
|
||||
nil: {count: 7, repoName: "big_test_"},
|
||||
user: {count: 7, repoName: "big_test_"},
|
||||
user2: {count: 7, repoName: "big_test_"}},
|
||||
},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user.ID), expectedResults: expectedResults{
|
||||
nil: {count: 4},
|
||||
user: {count: 8, includesPrivate: true},
|
||||
user2: {count: 4}},
|
||||
nil: {count: 5},
|
||||
user: {count: 9, includesPrivate: true},
|
||||
user2: {count: 5, includesPrivate: true}},
|
||||
},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser2", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user2.ID), expectedResults: expectedResults{
|
||||
nil: {count: 1},
|
||||
user: {count: 1},
|
||||
user2: {count: 2, includesPrivate: true}},
|
||||
user: {count: 2, includesPrivate: true},
|
||||
user2: {count: 2, includesPrivate: true},
|
||||
user4: {count: 1}},
|
||||
},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser3", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user3.ID), expectedResults: expectedResults{
|
||||
nil: {count: 1},
|
||||
user: {count: 1},
|
||||
user2: {count: 1},
|
||||
user: {count: 4, includesPrivate: true},
|
||||
user2: {count: 2, includesPrivate: true},
|
||||
user3: {count: 4, includesPrivate: true}},
|
||||
},
|
||||
{name: "RepositoriesOwnedByOrganization", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", orgUser.ID), expectedResults: expectedResults{
|
||||
@@ -112,12 +113,12 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser4", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user4.ID), expectedResults: expectedResults{
|
||||
nil: {count: 3},
|
||||
user: {count: 3},
|
||||
user4: {count: 6, includesPrivate: true}}},
|
||||
user: {count: 4, includesPrivate: true},
|
||||
user4: {count: 7, includesPrivate: true}}},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeSource", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "source"), expectedResults: expectedResults{
|
||||
nil: {count: 0},
|
||||
user: {count: 0},
|
||||
user4: {count: 0, includesPrivate: true}}},
|
||||
user: {count: 1, includesPrivate: true},
|
||||
user4: {count: 1, includesPrivate: true}}},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeFork", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "fork"), expectedResults: expectedResults{
|
||||
nil: {count: 1},
|
||||
user: {count: 1},
|
||||
@@ -136,8 +137,8 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
user4: {count: 2, includesPrivate: true}}},
|
||||
{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeCollaborative", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "collaborative"), expectedResults: expectedResults{
|
||||
nil: {count: 0},
|
||||
user: {count: 0},
|
||||
user4: {count: 0, includesPrivate: true}}},
|
||||
user: {count: 1, includesPrivate: true},
|
||||
user4: {count: 1, includesPrivate: true}}},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
@@ -164,14 +165,19 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
var body api.SearchResults
|
||||
DecodeJSON(t, response, &body)
|
||||
|
||||
assert.Len(t, body.Data, expected.count)
|
||||
repoNames := make([]string, 0, len(body.Data))
|
||||
for _, repo := range body.Data {
|
||||
repoNames = append(repoNames, fmt.Sprintf("%d:%s:%t", repo.ID, repo.FullName, repo.Private))
|
||||
}
|
||||
assert.Len(t, repoNames, expected.count)
|
||||
for _, repo := range body.Data {
|
||||
r := getRepo(t, repo.ID)
|
||||
hasAccess, err := models.HasAccess(userID, r)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, hasAccess)
|
||||
assert.NoError(t, err, "Error when checking if User: %d has access to %s: %v", userID, repo.FullName, err)
|
||||
assert.True(t, hasAccess, "User: %d does not have access to %s", userID, repo.FullName)
|
||||
|
||||
assert.NotEmpty(t, repo.Name)
|
||||
assert.Equal(t, repo.Name, r.Name)
|
||||
|
||||
if len(expected.repoName) > 0 {
|
||||
assert.Contains(t, repo.Name, expected.repoName)
|
||||
@@ -182,7 +188,7 @@ func TestAPISearchRepo(t *testing.T) {
|
||||
}
|
||||
|
||||
if !expected.includesPrivate {
|
||||
assert.False(t, repo.Private)
|
||||
assert.False(t, repo.Private, "User: %d not expecting private repository: %s", userID, repo.FullName)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
52
integrations/api_user_search_test.go
Normal file
52
integrations/api_user_search_test.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2019 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 models
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type SearchResults struct {
|
||||
OK bool `json:"ok"`
|
||||
Data []*api.User `json:"data"`
|
||||
}
|
||||
|
||||
func TestAPIUserSearchLoggedIn(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
adminUsername := "user1"
|
||||
session := loginUser(t, adminUsername)
|
||||
token := getTokenForLoggedInUser(t, session)
|
||||
query := "user2"
|
||||
req := NewRequestf(t, "GET", "/api/v1/users/search?token=%s&q=%s", token, query)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var results SearchResults
|
||||
DecodeJSON(t, resp, &results)
|
||||
assert.NotEmpty(t, results.Data)
|
||||
for _, user := range results.Data {
|
||||
assert.Contains(t, user.UserName, query)
|
||||
assert.NotEmpty(t, user.Email)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIUserSearchNotLoggedIn(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
query := "user2"
|
||||
req := NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var results SearchResults
|
||||
DecodeJSON(t, resp, &results)
|
||||
assert.NotEmpty(t, results.Data)
|
||||
for _, user := range results.Data {
|
||||
assert.Contains(t, user.UserName, query)
|
||||
assert.Empty(t, user.Email)
|
||||
}
|
||||
}
|
@@ -92,6 +92,15 @@ func TestPrivateOrg(t *testing.T) {
|
||||
req = NewRequest(t, "GET", "/privated_org/private_repo_on_private_org")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
// non-org member who is collaborator on repo in private org
|
||||
session = loginUser(t, "user4")
|
||||
req = NewRequest(t, "GET", "/privated_org")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
req = NewRequest(t, "GET", "/privated_org/public_repo_on_private_org") // colab of this repo
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
req = NewRequest(t, "GET", "/privated_org/private_repo_on_private_org")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
|
||||
// site admin
|
||||
session = loginUser(t, "user1")
|
||||
req = NewRequest(t, "GET", "/privated_org")
|
||||
|
@@ -7,6 +7,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -532,7 +533,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit, bra
|
||||
}
|
||||
refMarked[issue.ID] = true
|
||||
|
||||
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, c.Message)
|
||||
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, html.EscapeString(c.Message))
|
||||
if err = CreateRefComment(doer, repo, issue, message, c.Sha1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -9,3 +9,9 @@
|
||||
repo_id: 4
|
||||
user_id: 4
|
||||
mode: 2 # write
|
||||
|
||||
-
|
||||
id: 3
|
||||
repo_id: 38
|
||||
user_id: 4
|
||||
mode: 2 # write
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -277,6 +278,11 @@ func SetEngine() (err error) {
|
||||
// so use log file to instead print to stdout.
|
||||
x.SetLogger(log.XORMLogger)
|
||||
x.ShowSQL(setting.LogSQL)
|
||||
if DbCfg.Type == "mysql" {
|
||||
x.SetMaxIdleConns(0)
|
||||
x.SetConnMaxLifetime(3 * time.Second)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
"github.com/go-xorm/core"
|
||||
)
|
||||
|
||||
// RepositoryListDefaultPageSize is the default number of repositories
|
||||
@@ -112,15 +111,17 @@ func (repos MirrorRepositoryList) LoadAttributes() error {
|
||||
|
||||
// SearchRepoOptions holds the search options
|
||||
type SearchRepoOptions struct {
|
||||
Keyword string
|
||||
OwnerID int64
|
||||
OrderBy SearchOrderBy
|
||||
Private bool // Include private repositories in results
|
||||
Starred bool
|
||||
Page int
|
||||
IsProfile bool
|
||||
AllPublic bool // Include also all public repositories
|
||||
PageSize int // Can be smaller than or equal to setting.ExplorePagingNum
|
||||
UserID int64
|
||||
UserIsAdmin bool
|
||||
Keyword string
|
||||
OwnerID int64
|
||||
OrderBy SearchOrderBy
|
||||
Private bool // Include private repositories in results
|
||||
StarredByID int64
|
||||
Page int
|
||||
IsProfile bool
|
||||
AllPublic bool // Include also all public repositories
|
||||
PageSize int // Can be smaller than or equal to setting.ExplorePagingNum
|
||||
// None -> include collaborative AND non-collaborative
|
||||
// True -> include just collaborative
|
||||
// False -> incude just non-collaborative
|
||||
@@ -168,72 +169,79 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
|
||||
if opts.Page <= 0 {
|
||||
opts.Page = 1
|
||||
}
|
||||
|
||||
var cond = builder.NewCond()
|
||||
|
||||
if !opts.Private {
|
||||
if opts.Private {
|
||||
if !opts.UserIsAdmin && opts.UserID != 0 && opts.UserID != opts.OwnerID {
|
||||
// OK we're in the context of a User
|
||||
// We should be Either
|
||||
cond = cond.And(builder.Or(
|
||||
// 1. Be able to see all non-private repositories that either:
|
||||
cond.And(
|
||||
builder.Eq{"is_private": false},
|
||||
builder.Or(
|
||||
// A. Aren't in organisations __OR__
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})),
|
||||
// B. Isn't a private organisation. (Limited is OK because we're logged in)
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"visibility": structs.VisibleTypePrivate}))),
|
||||
),
|
||||
// 2. Be able to see all repositories that we have access to
|
||||
builder.In("id", builder.Select("repo_id").
|
||||
From("`access`").
|
||||
Where(builder.And(
|
||||
builder.Eq{"user_id": opts.UserID},
|
||||
builder.Gt{"mode": int(AccessModeNone)}))),
|
||||
// 3. Be able to see all repositories that we are in a team
|
||||
builder.In("id", builder.Select("`team_repo`.repo_id").
|
||||
From("team_repo").
|
||||
Where(builder.Eq{"`team_user`.uid": opts.UserID}).
|
||||
Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"))))
|
||||
}
|
||||
} else {
|
||||
// Not looking at private organisations
|
||||
// We should be able to see all non-private repositories that either:
|
||||
cond = cond.And(builder.Eq{"is_private": false})
|
||||
accessCond := builder.Or(
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}))),
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})))
|
||||
// A. Aren't in organisations __OR__
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})),
|
||||
// B. Isn't a private or limited organisation.
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}))))
|
||||
cond = cond.And(accessCond)
|
||||
}
|
||||
|
||||
// Restrict to starred repositories
|
||||
if opts.StarredByID > 0 {
|
||||
cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.StarredByID})))
|
||||
}
|
||||
|
||||
// Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate
|
||||
if opts.OwnerID > 0 {
|
||||
if opts.Starred {
|
||||
cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.OwnerID})))
|
||||
} else {
|
||||
var accessCond = builder.NewCond()
|
||||
if opts.Collaborate != util.OptionalBoolTrue {
|
||||
accessCond = builder.Eq{"owner_id": opts.OwnerID}
|
||||
}
|
||||
|
||||
if opts.Collaborate != util.OptionalBoolFalse {
|
||||
collaborateCond := builder.And(
|
||||
builder.Expr("repository.id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", opts.OwnerID),
|
||||
builder.Neq{"owner_id": opts.OwnerID})
|
||||
if !opts.Private {
|
||||
collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false))
|
||||
}
|
||||
|
||||
accessCond = accessCond.Or(collaborateCond)
|
||||
}
|
||||
|
||||
var exprCond builder.Cond
|
||||
if DbCfg.Type == core.POSTGRES {
|
||||
exprCond = builder.Expr("org_user.org_id = \"user\".id")
|
||||
} else if DbCfg.Type == core.MSSQL {
|
||||
exprCond = builder.Expr("org_user.org_id = [user].id")
|
||||
} else {
|
||||
exprCond = builder.Eq{"org_user.org_id": "user.id"}
|
||||
}
|
||||
|
||||
visibilityCond := builder.Or(
|
||||
builder.In("owner_id",
|
||||
builder.Select("org_id").From("org_user").
|
||||
LeftJoin("`user`", exprCond).
|
||||
Where(
|
||||
builder.And(
|
||||
builder.Eq{"uid": opts.OwnerID},
|
||||
builder.Eq{"visibility": structs.VisibleTypePrivate})),
|
||||
),
|
||||
builder.In("owner_id",
|
||||
builder.Select("id").From("`user`").
|
||||
Where(
|
||||
builder.Or(
|
||||
builder.Eq{"visibility": structs.VisibleTypePublic},
|
||||
builder.Eq{"visibility": structs.VisibleTypeLimited})),
|
||||
),
|
||||
builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})),
|
||||
)
|
||||
cond = cond.And(visibilityCond)
|
||||
|
||||
if opts.AllPublic {
|
||||
accessCond = accessCond.Or(builder.Eq{"is_private": false})
|
||||
}
|
||||
|
||||
cond = cond.And(accessCond)
|
||||
var accessCond = builder.NewCond()
|
||||
if opts.Collaborate != util.OptionalBoolTrue {
|
||||
accessCond = builder.Eq{"owner_id": opts.OwnerID}
|
||||
}
|
||||
|
||||
if opts.Collaborate != util.OptionalBoolFalse {
|
||||
collaborateCond := builder.And(
|
||||
builder.Or(
|
||||
builder.Expr("repository.id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", opts.OwnerID),
|
||||
builder.In("id", builder.Select("`team_repo`.repo_id").
|
||||
From("team_repo").
|
||||
Where(builder.Eq{"`team_user`.uid": opts.OwnerID}).
|
||||
Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"))),
|
||||
builder.Neq{"owner_id": opts.OwnerID})
|
||||
if !opts.Private {
|
||||
collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false))
|
||||
}
|
||||
|
||||
accessCond = accessCond.Or(collaborateCond)
|
||||
}
|
||||
|
||||
if opts.AllPublic {
|
||||
accessCond = accessCond.Or(builder.Eq{"is_private": false})
|
||||
}
|
||||
|
||||
cond = cond.And(accessCond)
|
||||
}
|
||||
|
||||
if opts.Keyword != "" {
|
||||
|
@@ -117,7 +117,7 @@ func TestSearchRepositoryByName(t *testing.T) {
|
||||
count: 4},
|
||||
{name: "PublicRepositoriesOfUserIncludingCollaborative",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15},
|
||||
count: 4},
|
||||
count: 5},
|
||||
{name: "PublicRepositoriesOfUser2IncludingCollaborative",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 18},
|
||||
count: 1},
|
||||
@@ -126,13 +126,13 @@ func TestSearchRepositoryByName(t *testing.T) {
|
||||
count: 3},
|
||||
{name: "PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true},
|
||||
count: 8},
|
||||
count: 9},
|
||||
{name: "PublicAndPrivateRepositoriesOfUser2IncludingCollaborative",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 18, Private: true},
|
||||
count: 4},
|
||||
{name: "PublicAndPrivateRepositoriesOfUser3IncludingCollaborative",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 20, Private: true},
|
||||
count: 6},
|
||||
count: 7},
|
||||
{name: "PublicRepositoriesOfOrganization",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, Collaborate: util.OptionalBoolFalse},
|
||||
count: 1},
|
||||
@@ -150,7 +150,7 @@ func TestSearchRepositoryByName(t *testing.T) {
|
||||
count: 19},
|
||||
{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
||||
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
|
||||
count: 24},
|
||||
count: 25},
|
||||
{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
|
||||
opts: &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
|
||||
count: 13},
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/mcuadros/go-version"
|
||||
)
|
||||
|
||||
// MirrorQueue holds an UniqueQueue object of the mirror
|
||||
@@ -70,7 +71,17 @@ func (m *Mirror) ScheduleNextUpdate() {
|
||||
}
|
||||
|
||||
func remoteAddress(repoPath string) (string, error) {
|
||||
cmd := git.NewCommand("remote", "get-url", "origin")
|
||||
var cmd *git.Command
|
||||
binVersion, err := git.BinVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if version.Compare(binVersion, "2.7", ">=") {
|
||||
cmd = git.NewCommand("remote", "get-url", "origin")
|
||||
} else {
|
||||
cmd = git.NewCommand("config", "--get", "remote.origin.url")
|
||||
}
|
||||
|
||||
result, err := cmd.RunInDir(repoPath)
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||
|
@@ -107,7 +107,17 @@ func getUserRepoPermission(e Engine, repo *Repository, user *User) (perm Permiss
|
||||
repo.mustOwner(e)
|
||||
}
|
||||
|
||||
if repo.Owner.IsOrganization() && !HasOrgVisible(repo.Owner, user) {
|
||||
var isCollaborator bool
|
||||
if user != nil {
|
||||
isCollaborator, err = repo.isCollaborator(e, user.ID)
|
||||
if err != nil {
|
||||
return perm, err
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent strangers from checking out public repo of private orginization
|
||||
// Allow user if they are collaborator of a repo within a private orginization but not a member of the orginization itself
|
||||
if repo.Owner.IsOrganization() && !HasOrgVisible(repo.Owner, user) && !isCollaborator {
|
||||
perm.AccessMode = AccessModeNone
|
||||
return
|
||||
}
|
||||
@@ -146,9 +156,7 @@ func getUserRepoPermission(e Engine, repo *Repository, user *User) (perm Permiss
|
||||
perm.UnitsMode = make(map[UnitType]AccessMode)
|
||||
|
||||
// Collaborators on organization
|
||||
if isCollaborator, err := repo.isCollaborator(e, user.ID); err != nil {
|
||||
return perm, err
|
||||
} else if isCollaborator {
|
||||
if isCollaborator {
|
||||
for _, u := range repo.Units {
|
||||
perm.UnitsMode[u.Type] = perm.AccessMode
|
||||
}
|
||||
|
@@ -48,7 +48,7 @@ type U2FRegistrationList []*U2FRegistration
|
||||
|
||||
// ToRegistrations will convert all U2FRegistrations to u2f.Registrations
|
||||
func (list U2FRegistrationList) ToRegistrations() []u2f.Registration {
|
||||
regs := make([]u2f.Registration, len(list))
|
||||
regs := make([]u2f.Registration, 0, len(list))
|
||||
for _, reg := range list {
|
||||
r, err := reg.Parse()
|
||||
if err != nil {
|
||||
|
@@ -832,10 +832,9 @@ func CreateUser(u *User) (err error) {
|
||||
return err
|
||||
}
|
||||
u.HashPassword(u.Passwd)
|
||||
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
|
||||
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation
|
||||
u.MaxRepoCreation = -1
|
||||
u.Theme = setting.UI.DefaultTheme
|
||||
u.AllowCreateOrganization = !setting.Admin.DisableRegularOrgCreation
|
||||
|
||||
if _, err = sess.Insert(u); err != nil {
|
||||
return err
|
||||
|
@@ -261,6 +261,8 @@ func TestCreateUser_Issue5882(t *testing.T) {
|
||||
{&User{Name: "GiteaBot2", Email: "GiteaBot2@gitea.io", Passwd: passwd, MustChangePassword: false}, true},
|
||||
}
|
||||
|
||||
setting.Service.DefaultAllowCreateOrganization = true
|
||||
|
||||
for _, v := range tt {
|
||||
setting.Admin.DisableRegularOrgCreation = v.disableOrgCreation
|
||||
|
||||
|
@@ -15,6 +15,14 @@ import (
|
||||
func Init() {
|
||||
getIssueFullPattern()
|
||||
NewSanitizer()
|
||||
|
||||
// since setting maybe changed extensions, this will reload all parser extensions mapping
|
||||
extParsers = make(map[string]Parser)
|
||||
for _, parser := range parsers {
|
||||
for _, ext := range parser.Extensions() {
|
||||
extParsers[strings.ToLower(ext)] = parser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parser defines an interface for parsering markup file to HTML
|
||||
|
@@ -93,6 +93,10 @@ sqlite_helper = File path for the SQLite3 database.<br>Enter an absolute path if
|
||||
err_empty_db_path = The SQLite3 database path cannot be empty.
|
||||
no_admin_and_disable_registration = You cannot disable user self-registration without creating an administrator account.
|
||||
err_empty_admin_password = The administrator password cannot be empty.
|
||||
err_empty_admin_email = The administrator email cannot be empty.
|
||||
err_admin_name_is_reserved = Administrator Username is invalid, username is reserved
|
||||
err_admin_name_pattern_not_allowed = Administrator Username is invalid, username is pattern is not allowed
|
||||
err_admin_name_is_invalid = Administrator Username is invalid
|
||||
|
||||
general_title = General Settings
|
||||
app_name = Site Title
|
||||
|
@@ -326,7 +326,7 @@ func GetAllUsers(ctx *context.APIContext) {
|
||||
|
||||
results := make([]*api.User, len(users))
|
||||
for i := range users {
|
||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin)
|
||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||
}
|
||||
|
||||
ctx.JSON(200, &results)
|
||||
|
@@ -55,6 +55,15 @@ func Search(ctx *context.APIContext) {
|
||||
// description: search only for repos that the user with the given id owns or contributes to
|
||||
// type: integer
|
||||
// format: int64
|
||||
// - name: starredBy
|
||||
// in: query
|
||||
// description: search only for repos that the user with the given id has starred
|
||||
// type: integer
|
||||
// format: int64
|
||||
// - name: private
|
||||
// in: query
|
||||
// description: include private repositories this user has access to (defaults to true)
|
||||
// type: boolean
|
||||
// - name: page
|
||||
// in: query
|
||||
// description: page number of results to return (1-based)
|
||||
@@ -95,6 +104,10 @@ func Search(ctx *context.APIContext) {
|
||||
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
|
||||
TopicOnly: ctx.QueryBool("topic"),
|
||||
Collaborate: util.OptionalBoolNone,
|
||||
Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")),
|
||||
UserIsAdmin: ctx.IsSigned && ctx.User.IsAdmin,
|
||||
UserID: ctx.Data["SignedUserID"].(int64),
|
||||
StarredByID: ctx.QueryInt64("starredBy"),
|
||||
}
|
||||
|
||||
if ctx.QueryBool("exclusive") {
|
||||
@@ -139,42 +152,6 @@ func Search(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
var err error
|
||||
if opts.OwnerID > 0 {
|
||||
var repoOwner *models.User
|
||||
if ctx.User != nil && ctx.User.ID == opts.OwnerID {
|
||||
repoOwner = ctx.User
|
||||
} else {
|
||||
repoOwner, err = models.GetUserByID(opts.OwnerID)
|
||||
if err != nil {
|
||||
ctx.JSON(500, api.SearchError{
|
||||
OK: false,
|
||||
Error: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if repoOwner.IsOrganization() {
|
||||
opts.Collaborate = util.OptionalBoolFalse
|
||||
}
|
||||
|
||||
// Check visibility.
|
||||
if ctx.IsSigned {
|
||||
if ctx.User.ID == repoOwner.ID {
|
||||
opts.Private = true
|
||||
} else if repoOwner.IsOrganization() {
|
||||
opts.Private, err = repoOwner.IsOwnedBy(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.JSON(500, api.SearchError{
|
||||
OK: false,
|
||||
Error: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repos, count, err := models.SearchRepositoryByName(opts)
|
||||
if err != nil {
|
||||
ctx.JSON(500, api.SearchError{
|
||||
|
@@ -67,7 +67,7 @@ func Search(ctx *context.APIContext) {
|
||||
|
||||
results := make([]*api.User, len(users))
|
||||
for i := range users {
|
||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin)
|
||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||
}
|
||||
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
|
@@ -19,6 +19,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/mailer"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/external"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/ssh"
|
||||
|
||||
@@ -75,6 +76,7 @@ func GlobalInit() {
|
||||
|
||||
if setting.InstallLock {
|
||||
highlight.NewContext()
|
||||
external.RegisterParsers()
|
||||
markup.Init()
|
||||
if err := initDBEngine(); err == nil {
|
||||
log.Info("ORM engine initialization successful!")
|
||||
|
@@ -213,18 +213,42 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check admin password.
|
||||
if len(form.AdminName) > 0 && len(form.AdminPasswd) == 0 {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminPasswd"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), tplInstall, form)
|
||||
return
|
||||
}
|
||||
if form.AdminPasswd != form.AdminConfirmPasswd {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminPasswd"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplInstall, form)
|
||||
return
|
||||
// Check admin user creation
|
||||
if len(form.AdminName) > 0 {
|
||||
// Ensure AdminName is valid
|
||||
if err := models.IsUsableUsername(form.AdminName); err != nil {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminName"] = true
|
||||
if models.IsErrNameReserved(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_admin_name_is_reserved"), tplInstall, form)
|
||||
return
|
||||
} else if models.IsErrNamePatternNotAllowed(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_admin_name_pattern_not_allowed"), tplInstall, form)
|
||||
return
|
||||
}
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_admin_name_is_invalid"), tplInstall, form)
|
||||
return
|
||||
}
|
||||
// Check Admin email
|
||||
if len(form.AdminEmail) == 0 {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminEmail"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_email"), tplInstall, form)
|
||||
return
|
||||
}
|
||||
// Check admin password.
|
||||
if len(form.AdminPasswd) == 0 {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminPasswd"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), tplInstall, form)
|
||||
return
|
||||
}
|
||||
if form.AdminPasswd != form.AdminConfirmPasswd {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminPasswd"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplInstall, form)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if form.AppURL[len(form.AppURL)-1] != '/' {
|
||||
|
@@ -435,50 +435,20 @@ func showOrgProfile(ctx *context.Context) {
|
||||
count int64
|
||||
err error
|
||||
)
|
||||
if ctx.IsSigned && !ctx.User.IsAdmin {
|
||||
env, err := org.AccessibleReposEnv(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("AccessibleReposEnv", err)
|
||||
return
|
||||
}
|
||||
env.SetSort(orderBy)
|
||||
if len(keyword) != 0 {
|
||||
env.AddKeyword(keyword)
|
||||
}
|
||||
repos, err = env.Repos(page, setting.UI.User.RepoPagingNum)
|
||||
if err != nil {
|
||||
ctx.ServerError("env.Repos", err)
|
||||
return
|
||||
}
|
||||
count, err = env.CountRepos()
|
||||
if err != nil {
|
||||
ctx.ServerError("env.CountRepos", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
showPrivate := ctx.IsSigned && ctx.User.IsAdmin
|
||||
if len(keyword) == 0 {
|
||||
repos, err = models.GetUserRepositories(org.ID, showPrivate, page, setting.UI.User.RepoPagingNum, orderBy.String())
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepositories", err)
|
||||
return
|
||||
}
|
||||
count = models.CountUserRepositories(org.ID, showPrivate)
|
||||
} else {
|
||||
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Keyword: keyword,
|
||||
OwnerID: org.ID,
|
||||
OrderBy: orderBy,
|
||||
Private: showPrivate,
|
||||
Page: page,
|
||||
IsProfile: true,
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Keyword: keyword,
|
||||
OwnerID: org.ID,
|
||||
OrderBy: orderBy,
|
||||
Private: ctx.IsSigned,
|
||||
UserIsAdmin: ctx.IsSigned && ctx.User.IsAdmin,
|
||||
UserID: ctx.Data["SignedUserID"].(int64),
|
||||
Page: page,
|
||||
IsProfile: true,
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := org.GetMembers(); err != nil {
|
||||
|
@@ -259,7 +259,7 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) {
|
||||
ctx.Data["Application"] = app
|
||||
ctx.Data["RedirectURI"] = form.RedirectURI
|
||||
ctx.Data["State"] = form.State
|
||||
ctx.Data["ApplicationUserLink"] = "<a href=\"" + setting.LocalURL + app.User.LowerName + "\">@" + app.User.Name + "</a>"
|
||||
ctx.Data["ApplicationUserLink"] = "<a href=\"" + setting.AppURL + app.User.LowerName + "\">@" + app.User.Name + "</a>"
|
||||
ctx.Data["ApplicationRedirectDomainHTML"] = "<strong>" + form.RedirectURI + "</strong>"
|
||||
// TODO document SESSION <=> FORM
|
||||
ctx.Session.Set("client_id", app.ClientID)
|
||||
|
@@ -158,83 +158,47 @@ func Profile(ctx *context.Context) {
|
||||
}
|
||||
case "stars":
|
||||
ctx.Data["PageIsProfileStarList"] = true
|
||||
if len(keyword) == 0 {
|
||||
repos, err = ctxUser.GetStarredRepos(showPrivate, page, setting.UI.User.RepoPagingNum, orderBy.String())
|
||||
if err != nil {
|
||||
ctx.ServerError("GetStarredRepos", err)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = ctxUser.GetStarredRepoCount(showPrivate)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetStarredRepoCount", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Keyword: keyword,
|
||||
OwnerID: ctxUser.ID,
|
||||
OrderBy: orderBy,
|
||||
Private: showPrivate,
|
||||
Page: page,
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
Starred: true,
|
||||
Collaborate: util.OptionalBoolFalse,
|
||||
TopicOnly: topicOnly,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Keyword: keyword,
|
||||
OrderBy: orderBy,
|
||||
Private: ctx.IsSigned,
|
||||
UserIsAdmin: ctx.IsSigned && ctx.User.IsAdmin,
|
||||
UserID: ctx.Data["SignedUserID"].(int64),
|
||||
Page: page,
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
StarredByID: ctxUser.ID,
|
||||
Collaborate: util.OptionalBoolFalse,
|
||||
TopicOnly: topicOnly,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Repos"] = repos
|
||||
ctx.Data["Page"] = paginater.New(int(count), setting.UI.User.RepoPagingNum, page, 5)
|
||||
ctx.Data["Total"] = count
|
||||
default:
|
||||
if len(keyword) == 0 {
|
||||
var total int
|
||||
repos, err = models.GetUserRepositories(ctxUser.ID, showPrivate, page, setting.UI.User.RepoPagingNum, orderBy.String())
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepositories", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Repos"] = repos
|
||||
|
||||
if showPrivate {
|
||||
total = ctxUser.NumRepos
|
||||
} else {
|
||||
count, err := models.GetPublicRepositoryCount(ctxUser)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetPublicRepositoryCount", err)
|
||||
return
|
||||
}
|
||||
total = int(count)
|
||||
}
|
||||
|
||||
ctx.Data["Page"] = paginater.New(total, setting.UI.User.RepoPagingNum, page, 5)
|
||||
ctx.Data["Total"] = total
|
||||
} else {
|
||||
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Keyword: keyword,
|
||||
OwnerID: ctxUser.ID,
|
||||
OrderBy: orderBy,
|
||||
Private: showPrivate,
|
||||
Page: page,
|
||||
IsProfile: true,
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
Collaborate: util.OptionalBoolFalse,
|
||||
TopicOnly: topicOnly,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Repos"] = repos
|
||||
ctx.Data["Page"] = paginater.New(int(count), setting.UI.User.RepoPagingNum, page, 5)
|
||||
ctx.Data["Total"] = count
|
||||
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
|
||||
Keyword: keyword,
|
||||
OwnerID: ctxUser.ID,
|
||||
OrderBy: orderBy,
|
||||
Private: ctx.IsSigned,
|
||||
UserIsAdmin: ctx.IsSigned && ctx.User.IsAdmin,
|
||||
UserID: ctx.Data["SignedUserID"].(int64),
|
||||
Page: page,
|
||||
IsProfile: true,
|
||||
PageSize: setting.UI.User.RepoPagingNum,
|
||||
Collaborate: util.OptionalBoolFalse,
|
||||
TopicOnly: topicOnly,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("SearchRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Repos"] = repos
|
||||
ctx.Data["Page"] = paginater.New(int(count), setting.UI.User.RepoPagingNum, page, 5)
|
||||
ctx.Data["Total"] = count
|
||||
}
|
||||
|
||||
ctx.Data["ShowUserEmail"] = len(ctxUser.Email) > 0 && ctx.IsSigned && (!ctxUser.KeepEmailPrivate || ctxUser.ID == ctx.User.ID)
|
||||
|
@@ -1085,6 +1085,19 @@
|
||||
"name": "uid",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "search only for repos that the user with the given id has starred",
|
||||
"name": "starredBy",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "include private repositories this user has access to (defaults to true)",
|
||||
"name": "private",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page number of results to return (1-based)",
|
||||
|
Reference in New Issue
Block a user